我创建了一个程序list(X,Y)
来检查列表Y中的所有元素是否小于X.
代码如下。
list(X,[]).
list(X,[Y|Z]):-X>Y,list(X,Z).
我输入list(3,[1,2])
时效果很好。但是,如果我键入list(3,Y
)以查找仅包含小于3的元素的列表,则会出错。
?- list(3,[1,2]).
true .
?- list(3,Y).
Y = [] ;
ERROR: >/2: Arguments are not sufficiently instantiated
我看过一些有同样错误的帖子,但我仍然不明白我的代码哪个部分出错了。
这是一个从互联网上找到的类似例子。
greater(X,Y,Z)
会返回大于Z
的{{1}} Y
部分。
X
问题是,greater(X,[],[]).
greater(X,[H|Y],[H|Z]) :- H>X, greater(X,Y,Z).
greater(X,[H|Y],Z) :- H=<X, greater(X,Y,Z).
?- greater(2,[1,2,3], Y).
Y = [3].
和greater(X,Y,Z)
的代码之间有什么区别,因此在调用list(X,Y)
时没有错误。
感谢您提供的任何帮助。
答案 0 :(得分:3)
因为 - 根据你的评论判断 - 你似乎在推理整数:这是使用有限域约束的教科书示例,几乎所有现代Prolog实现都可以使用这些约束并推广整数运算,以便你可以在所有方向上使用它
如果您只使用有限域约束(#>)/2
而不是低级算术原语{{1>,您的代码与B-Prolog,GNU Prolog,SICStus,SWI和YAP等完全一致。 }}:
(>)/2
限制条件允许您使用此谓词,您也可以使用:- use_module(library(clpfd)).
list(X, []).
list(X, [Y|Z]):- X#>Y, list(X,Z).
表达,如下面的查询中所示:
maplist/2
即使是最常见的查询,也没有实例化任何参数,也提供了有用的答案:
?- maplist(#>(3), [1,2]).
true.
?- maplist(#>(X), [1,2]).
X in 3..sup.
?- maplist(#>(3), [A,B]).
A in inf..2,
B in inf..2.
?- maplist(#>(X), [Y,Z]).
Z#=<X+ -1,
Y#=<X+ -1.
编辑:此外,您现在添加的示例可以通过有限域约束更加通用:
?- maplist(#>(X), Ls).
Ls = [] ;
Ls = [_G1022],
_G1022#=<X+ -1 ;
Ls = [_G1187, _G1190],
_G1190#=<X+ -1,
_G1187#=<X+ -1 ;
etc.
您现在可以在所有方向上使用它,例如:
:- use_module(library(clpfd)).
greater(_, [], []).
greater(X, [H|Y], [H|Z]) :- H #> X, greater(X, Y, Z).
greater(X, [H|Y], Z) :- H #=< X, greater(X, Y, Z).
原始版本无法做到这一点,原作者的作者可能不知道约束。