prolog avoiding duplicate predicates

烈酒焚心 提交于 2019-12-13 17:52:33

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!