所以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运算符,你会如何重写它?
答案 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/3
和arg/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