Prolog GNU - Univ运营商?解释它

时间:2010-11-09 00:41:17

标签: prolog operator-keyword backtracking meta-predicate

所以univ运营商。我并不完全理解。

例如:

foo(PredList,[H|_]) :- bar(PredList,H).
foo(PredList,[_|T]) :- foo(PredList,T),!.

bar([H|_],Item) :- G =.. [H,Item],G.
bar([_|T],Item) :- bar(T,Item).

这是做什么的?这样可以查看另一个谓词是否为真。我不明白“..”的作用。

如果没有univ运算符,你会如何重写它?

2 个答案:

答案 0 :(得分:15)

Univ(=..)将一个术语分解为一个成分列表,或者从这样的列表中构造一个术语。尝试:

?- f(x,y) =.. L.
L = [f, x, y].

?- f(x,y,z) =.. [f|Args].
Args = [x, y, z].

?- Term =.. [g,x,y].
Term = g(x, y).

bar似乎在PredList Item上调用每个谓词,foo回溯Item。 (使用变量作为谓词不可移植; call谓词应该是首选。)

修改:Kaarel是对的,univ可以被functor/3arg/3取代,如下所示:

bar([H|_],Item) :-
    functor(Goal,H,1),   % unifies Goal with H(_)
    arg(1,Goal,Item),    % unifies first argument of Goal with Item
    call(Goal).          % use this for portability

答案 1 :(得分:2)

我认为最合适的改写是:

 bar( [H|_], Item ) :- call(H, Item).

call/n尚未成为ISO核心标准的一部分,但它们可能会在不久的将来成为(*)。许多Prolog系统已经支持它们。

{1}}优先于简单call/n(=..)/2 + functor/3解决方案,有一个原因。 arg/3解决方案能够处理闭包(**)。

使用简单的call/n(=..)/2 + functor/3解决方案,只能使用第一个列表参数中的原子调用arg/3。例如:

bar/2

对于闭包,我们不限于原子,我们可以节省一些编码工作。例如,我们可以直接执行以下操作:

 p1(1).
 p2(2).
 ?- bar( [p1, p2], 1 ).
 Yes
 ?- bar( [p1, p2], 2 ).
 Yes
 ?- bar( [p1, p2], 3 ).
 No

最好的问候

(*)
技术勘误2草案 http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#call

(**)
谁发明了它?: ?- bar( [=(1), =(2)], 1 ). Yes ?- bar( [=(1), =(2)], 2 ). Yes ?- bar( [=(1), =(2)], 3 ). No 谓词
http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/naish.html