Prolog为列表元素赋值

Prolog为列表元素赋值,prolog,Prolog,我不熟悉Prolog,我要处理的问题如下:给定一个变量列表,我想为该列表的每个元素分配一个值,然后检查包含其中一些变量的限制是否为真。这是我认为它应该如何工作的一个例子: predicate(L1, Restriction) :- foreach(member(Var,L1), Var = 1), Restriction. 但当我在控制台中写入时: ? - predicate([A,B,C], A==1). 或 或 他们都是假的 在foreach循环之后,A、B和C不都应该等

我不熟悉Prolog,我要处理的问题如下:给定一个变量列表,我想为该列表的每个元素分配一个值,然后检查包含其中一些变量的限制是否为真。这是我认为它应该如何工作的一个例子:

predicate(L1, Restriction) :-
    foreach(member(Var,L1), Var = 1),
    Restriction.
但当我在控制台中写入时:

? - predicate([A,B,C], A==1).

他们都是假的


在foreach循环之后,
A
B
C
不都应该等于1吗?

问题在于
foreach/2
谓词的工作方式。第一个参数用作生成器,第二个参数用作生成器每个解决方案的测试。但是谓词创建了一个连词,其中每个元素都是第二个参数的副本。由于这种复制,生成器中的变量永远不会被实例化(因为您正在实例化副本)。此语义可以通过以下查询进行说明:

?- foreach(member(Var, [A,B,C]), Var = 1), var(A), var(B), var(C).
true.
由于您的限制是
谓词/2
调用是一个相等测试,并且变量不等于整数,因此所有调用都失败

如果您打算创建一个给定长度的列表,其中所有元素都等于给定的术语,那么有几种方法可以实现。例如,仅使用标准内置谓词:

?- findall(1, between(1, 3, _), List).
List = [1, 1, 1].

保罗很好地解释了问题所在(+1)。也许你应该像这样修改你的代码

predicate(L1, Restriction) :-
    maplist(=(1), L1),
    Restriction.
这就产生了预期的产出

?- predicate([A,B,C], A==1).
A = B, B = C, C = 1.

请记住,prolog中没有“赋值”的概念。而是用"统一"来代替。这是一个重要的区别。我可以看到maplist是如何完成这项工作的。但是,如果我想使一个列表的所有元素都等于另一个列表的相应值,该怎么办?假设我们有L1=[A,B,C]和L2=[1,2,3]。我应该如何处理谓词的实现,以便将1分配给A,2分配给B,3分配给C,然后才测试限制(涉及A,B,C)?使用
maplist/3
而不是
maplist/2
maplist(=),L1,L2)
。这确实有效。非常感谢。我还注意到,仅仅写L1=L2会得到相同的结果。我没想到我所要达到的目标是如此微不足道。然而,提到映射列表谓词的主要原因是,您可以使用任何关系,包括谓词。当然,例如,
(=)/2
(=)/2
没有意义。
predicate(L1, Restriction) :-
    maplist(=(1), L1),
    Restriction.
?- predicate([A,B,C], A==1).
A = B, B = C, C = 1.