1

We have this assignment for our Prolog course. After two months of one hour per week of Prolog, it is still an enigma to me, my thinking seems unable to adapt from procedural languages - yet.

There is a knowledge base containing predicates/functors with the same name and arities 1, 2 and 3. The call form should be

search(functor_name, argument, S).

The answers should find all occurrences with this functor name and argument, regardless of arity. The answers should be of the form:

S = functor_name(argument);
S = functor_name(argument,_);
S = functor_name(_,argument);
S = functor_name(argument,_,_);
S = functor_name(_,argument,_);
S = functor_name(_,_,argument);
false.

I have found out that I could use call to test if the entry in the knowledge base exists.

But call does not seem to work with a variable for the functor name. I am totally baffled, no idea how to use a variable for a functor name.

UPDATE:

My question has been partly answered. My new code gives me true and false for arities 1, 2 and 3 (see below).

search(Person,Predicate) :-
   ID = Person, Key = Predicate, current_functor(Key,1),
   call(Key,ID)
 ; ID = Person, Key = Predicate, current_functor(Key,2),
   (call(Key,ID,_);call(Key,_,ID))
 ; ID = Person, Key = Predicate, current_functor(Key,3),
   (call(Key,ID,_,_);call(Key,_,ID,_);call(Key,_,_,ID)).

UPDATE2:

Another partial answer has come in. That one gives me S as a list of terms, but the "other" arguments are placeholders:

search2(Predicate, Arg, S) :-
   ( Arity = 2 ; Arity = 3 ; Arity = 4 ),
   functor(S, Predicate, Arity),
   S =.. [_,Predicate|Args],
   member(Arg, Args).

The result is quite nice. Still missing: the Predicate should not be inside the brackets and the other arguments should be taken literally from the knowledge base, not written as placeholders. The current result looks like this:

 ?- search2(parent,lars,S).
S = parent(parent, lars) ;
S = parent(parent, lars, _G1575) ;
S = parent(parent, _G1574, lars) ;
S = parent(parent, lars, _G1575, _G1576) ;
S = parent(parent, _G1574, lars, _G1576) ;
S = parent(parent, _G1574, _G1575, lars).

I am giving up with this question, because the question was posed in the wrong way from the beginning. I should have asked more specifically - which I could not, because I am still no good in Prolog.

@false helped me most. I am accepting his answer.

4

2 回答 2

4

这里有两种方法,一种是“传统的”(1970 年代),它实际上实现了你想要的:

search(F, Arg, S) :-
   ( N = 1 ; N = 2 ; N = 3 ), % more compactly: between(1,3, N)
   functor(S, F, N),
   S =.. [_|Args],            % more compactly: between(1,N, I), arg(I,S,Arg)
   member(Arg, Args).

另一个重新考虑目标的明确构建。实际上,如果你有一个 functorF和 arguments A1,你可以立即编写目标A2,而无需使用or 。A3call(F, A1, A2, A3)functor/3(=..)/2

call(F, A1, A2, A3)使用代替有许多优点Goal =.. [F, A1, A2, A3], call(Goal): 在许多情况下,它更干净、更快,并且更容易进行类型检查。此外,当使用模块系统时,对潜在模块资格的处理F将无缝工作。而(=..)/2必须明确地处理所有丑陋的细节,那就是更多的代码,更多的错误。

search(F,A,call(F,A)).
search(F,A,call(F,A,_)).
search(F,A,call(F,_,A)).
search(F,A,call(F,A,_,_)).
search(F,A,call(F,_,A,_)).
search(F,A,call(F,_,_,A)).

如果你想缩短这个,那么宁愿call/N动态构造:

search(F, Arg, S) :-
   ( N = 2 ; N = 3 ; N = 4 ),
   functor(S, call, N),
   S =.. [_,F|Args],
   member(Arg, Args).

请注意, call 需要一个额外的函子参数F

于 2014-06-10T09:45:00.153 回答
3

您可以使用“univ”运算符 ,=..来动态构建目标:

?- F=member, X=1, L=[1,2,3], Goal =.. [F, X, L], call(Goal).
F = member,
X = 1,
L = [1, 2, 3],
Goal = member(1, [1, 2, 3]) .
于 2014-06-10T09:04:01.353 回答