考虑一个(元逻辑)谓词var_in_vars(Var, Vars)
,它采用变量Var
和变量列表Vars
,如果Var
出现Vars
则成功。因此,我们不需要确保Var
是变量,也不需要Vars
是变量列表。
在ISO Prolog中表达这一点的最紧凑和规范的方法是什么?这是ISO / IEC 13211-1:1995中的overview of the built-ins,包括Cor.2:2012。
?- var_in_vars(V, [U,V,W]).
true.
?- var_in_vars(V, [X,Y,Z]).
false.
答案 0 :(得分:8)
一种可能性:
var_in_vars(V, Vs) :- \+ unify_with_occurs_check(V, Vs).
和更短:
var_in_vars(V, Vs) :- \+ subsumes_term(V, Vs).
编辑:未来的读者,请考虑问题的背景,这是一个特定的紧凑性挑战,涉及在特定情况下ISO谓词的表达性。
在其他情况下,您可能会从以下定义中获益更多:
var_in_vars(V, Vs) :-
must_be(list, Vs),
once((member(X, Vs), V == X)).
答案 1 :(得分:7)
这个定义通过了测试,但是......我是否会错过一些微妙的内容?
var_in_vars(V, [H|_]) :- V == H, !.
var_in_vars(V, [_|T]) :- var_in_vars(V, T).
答案 2 :(得分:5)
这是另一个,虽然有点复杂:
var_in_vars(V, Vs) :-
term_variables(Vs+V, Ws),
Ws == Vs.
所以这依赖于变量访问的精确顺序。由于标准中这是well defined,我们可以依赖它们
...根据他们在从左到右遍历中的第一次出现...
这个定义的一个缺点是它的最小成本与Vs
的长度成正比。但由于内部遍历通常非常有效地实现,因此这不是一个问题。
它有一个很大的优势:只有Vs
是变量列表才能成功。
答案 3 :(得分:2)
另一种解决方案是:
var_in_vars(V, Vs) :-
\+ (V = Vs, acyclic_term(Vs)).
但是@mat的解决方案更好,更优雅,而@CapelliC的解决方案在很长一段时间内是最便携的解决方案(subsumes_term/2
谓词最近才被标准化,并非所有系统都提供{{1谓词)。
答案 4 :(得分:2)
解决方案@false可以简化为:
var_in_vars(V, Vs) :-
term_variables(Vs+V, Vs).
当V
是Vs
列表的成员时,第二个参数返回Vs
(由于Vs+V
项的从左到右的遍历)。当V
不是Vs
的成员时,第二个参数返回的列表中包含的元素多于Vs
,因此无法与其统一。虽然在第二个论证中存在隐含的统一,但在任何情况下都不存在创建循环术语的危险。即统一是STO在这个简化的解决方案中不是问题。
但是简化值得它w.r.t.性能?使用等式(==)/2
有可能提前失败,从而使原始解决方案更快。
答案 5 :(得分:0)
解决方案: 简短
var_in_vars(V, Vs) :- \+ subsumes_term(V, Vs).
备选方案1: 简单
var_in_vars(V, Vs) :- \+ unify_with_occurs_check(V, Vs).
备选方案2: 视情况而定,这可能更合适
var_in_vars(V, Vs) :-
must_be(list, Vs),
once((member(X, Vs), V == X)).
备选方案3: 更复杂
var_in_vars(V, Vs) :-
term_variables(Vs+V, Ws),
Ws == Vs.
备选方案4: 其他可能性
var_in_vars(V, [H|_]) :- V == H, !.
var_in_vars(V, [_|T]) :- var_in_vars(V, T).
链接:
注意:问题的上下文,这是一个特定的紧凑性挑战,涉及在特定情况下ISO谓词的表达性。