Prolog, how to show multiple output in write()

2019-06-21 13:07发布

问题:

go :-   match(Mn,Fn),
        write('--Matching Result--'),
        nl,
        write(Mn),
        write(' match with '),
        write(Fn),
        match(Mn1,Fn1).


person(may,female,25,blue).
person(rose,female,20,blue).
person(hock,male,30,blue).
person(ali,male,24,blue).
match(Mn,Fn):-person(Fn,'female',Fage,Fatt),
person(Mn,'male',Mage,Matt),
Mage>=Fage,
Fatt=Matt.

Hi,this is my code...but it's only can show the 1 output...but there are 3 pair of matching in match(X,Y).how to show them all in my go function.

Thank you

回答1:

You get all your matches if you force backtracking, usually by entering ; (e.g. in SWI Prolog). But you also see that you are getting unnecessary outputs true. This is because the last clause in go is match(Mn1,Fn1). This clause succeeds three times and binds the variables Mn1,Fn1 but then only true is output, because you do not write() after that clause. The fourth time match(Mn1,Fn1) fails and by backtracking you come back to the first clause match(Mn,Fn) that matches, the match is output, etc.

You surely do not want to have this behavior. You should remove the last clause match(Mn1,Fn1) in go. Now by pressing ; you get the 3 matches without any output true in between.

But what you likely want is that the program does the backtracking. To achieve this, you just need to force backtracking by adding false as the last clause. To get proper formatting of the output, use the following program. The last clause go2. is added to get true at the very end.

go2 :- write('--Matching Result--'), nl,
    match(Mn,Fn),
    write(Mn), write(' match with '), write(Fn), nl,
    fail.
go2.

This technique is called failure driven loop.



回答2:

If you have any predicate that has multiple results and want to to find all of them, you should use findall/3

For example, in your case, you could do something like:

findall([X,Y], match(X,Y),L).

L will be a list that will contain all the X,Y that satisfy match(X,Y) in the format [X,Y]. for example, assuming that:

match(m1,f1).
match(m2,f2).

the result will be L = [ [m1,f1], [m2,f2] ]

note that you can define the format as you wish, for example you could write:

findall(pair(X,Y), match(X,Y), L).
L = [ pair(m1,f1), pair(m2,f2) ]

findall( X, match(X,Y), L).
L = [ m1, m2]

findall( 42, match(X,Y), L).
L = [42, 42]

then you have to recurse on the list to print them.

However, if you wish to find one result, run some code and then continue you could use forall/2:

forall(match(X,Y), my_print(X,Y).


回答3:

Prolog is a lazy language. Which means that it will stop once it has found a condition that made your problem true. This will be the very first match alone.

IF your code is working (I haven't tried it), then you should try and run the match-statement like this in your prolog inspector: match(X,Y)

The prolog inspector will return all states and print them for you.



标签: prolog