所以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 运算符,你将如何重写它?
所以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 运算符,你将如何重写它?
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
on Item
,并foo
在 s 上回溯Item
。(使用变量作为谓词是不可移植的;call
应该首选谓词。)
编辑: Kaarel 是对的,univ 可以替换为functor/3
and 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
我认为最合适的重写是:
bar( [H|_], Item ) :- call(H, Item).
call/n
尚未成为 ISO 核心标准的一部分,但它们可能会在不久的将来成为 (*)。许多 Prolog 系统已经支持它们。
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
使用闭包,我们不限于原子,我们可能会节省一些编码工作。例如我们可以直接执行以下操作:
?- bar( [=(1), =(2)], 1 ).
Yes
?- bar( [=(1), =(2)], 2 ).
Yes
?- bar( [=(1), =(2)], 3 ).
No
最好的祝福
(*)
技术勘误草案 2
http://www.complang.tuwien.ac.at/ulrich/iso-prolog/dtc2#call
(**)
谁发明了它?:call/n
谓词
http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/naish.html