问题
I was wondering whether it is possible to test whether a predicate already exists (with the same information) to then avoid the user being able to input the same information again.
I have already managed to do it for a single predicate:
:- dynamic(test/2).
test(a,b).
top(X,Y) :-
(test(X,Y),
write('Yes'),!
;write('No'),!
).
This version works just fine, returning 'Yes' if the information already exists and 'No' if it doesn't.
I was wondering whether it would be possible to do this for multiple prediactes, not just for 'test/2'; I have tried to replace the predicate 'test' with a variable Pred but unfortunately I get a syntax error when I try to compile it. Here is my attempt:
main(Pred,X,Y) :-
(Pred(X,Y),
write('Yes'),!
;write('No'),!
).
Is it even possible to do something like this and if it is how would it be possible?
Btw I am using GNU Prolog if it helps.
Thank you very much for your help :D !!
回答1:
You want call/2, to call a dynamic goal with arguments, evaluated at runtime. In your case, it would be call(Pred,X,Y)
:
main(Pred,X,Y) :-
(
call(Pred,X,Y),
write('Yes'),!
)
;
(
write('No'),!
).
Do note that Pred/2
must resolve to an actual predicate at runtime, and you will need to build a different rule for each number of arguments.
@Tomas-By's answer, using (=..)/2 lets you create a single rule, with a list of args, but with the same caveats regarding predicates existing, albeit with an extra line:
main(Pred,L) :- % where L is a list of args [X,Y|...]
Term =.. [Pred | L],
(
Term,
write('Yes'),!
)
;
(
write('No'),!
).
And, as pointed out in the comments by @lurker, in either instance, using (->)/2:
(call(Pred,X,Y) -> write('Yes') ; write('No'))
or
(Term -> write('Yes') ; write('No'))
may be preferable as the destruction of choice points is limited to the if->then;else structure.
回答2:
There is an operator =.. for constructing terms, as in:
Term =.. [Op,V1,V2]
not sure if that is in Gnu Prolog.
Using Sicstus:
xxx(1,2).
check(Pred,X,Y) :-
Term =.. [Pred,X,Y],
( Term ->
write('Yes')
; write('No') ).
and after loading the file:
| ?- check(xxx,1,2).
Yes
来源:https://stackoverflow.com/questions/42071334/prolog-avoiding-duplicate-predicates