Loops SWI Prolog foreach/2

Loops SWI Prolog foreach/2,loops,prolog,swi-prolog,Loops,Prolog,Swi Prolog,考虑 ?- length(L, 4), foreach(member(M,L),(length(M,4))). L = [_28602, _28608, _28614, _28620]. vs 我希望得到后一个结果,但是使用member是表达“所有内容”的更整洁的方式 我已经尝试添加一些日志到调试中,但我不能理解它的头绪 ?- length(L, 4), foreach((member(M,L),write(M),writeln(L)),(length(M,4))). _3400[_3400,

考虑

?- length(L, 4), foreach(member(M,L),(length(M,4))).
L = [_28602, _28608, _28614, _28620].
vs

我希望得到后一个结果,但是使用
member
是表达“所有内容”的更整洁的方式

我已经尝试添加一些日志到调试中,但我不能理解它的头绪

?- length(L, 4), foreach((member(M,L),write(M),writeln(L)),(length(M,4))).
_3400[_3400,_4060,_4066,_4072]
_3400[_4054,_3400,_4066,_4072]
_3400[_4054,_4060,_3400,_4072]
_3400[_4054,_4060,_4066,_3400]
L = [_4054, _4060, _4066, _4072].
还有更复杂的日志记录和修改:

?- length(L, 3), foreach((member(M,L),write((m,M," ")),write((l,L," ")),length(M,3),write((m,M," ")),writeln((l,L))),(true)).
m,_60830, l,[_60830,_61872,_61878], m,[_61944,_61950,_61956], l,[[_61944,_61950,_61956],_61872,_61878]
m,_60830, l,[_61866,_60830,_61878], m,[_61944,_61950,_61956], l,[_61866,[_61944,_61950,_61956],_61878]
m,_60830, l,[_61866,_61872,_60830], m,[_61944,_61950,_61956], l,[_61866,_61872,[_61944,_61950,_61956]]
L = [_61866, _61872, _61878].
特别是最后一点,使我怀疑生成器中的任何变量(foreach的第一项)在调用foreach时都被有效地深度复制,并且在每个循环上都重置了副本。它将保留已绑定的结构,但在
foreach
中统一任何结构只会统一副本,而不是原始。这是正确的推论吗?关于
foreach
的操作方式,我还需要知道其他信息吗?文档非常简单

(我确实想出了一个办法来做我原来想做的事,我想:

loop(Gen, Cond) :-
    aggregate(bag(X),call(Gen,X),L),maplist(Cond,L).

?- length(L,4),loop({L}/[X]>>(member(X,L)),[X]>>(length(X,4))).
只是有点笨重。不过,也许特异性是好的。)

在x64-win64上使用SWI Prolog 8.0.3版。

实际上说明了您认为正在发生的事情:


连接的每个成员都是目标的一个副本,其中它与生成器共享的变量由相应解决方案中的值填充

人们看不到
foreach/2的大量使用
forall/2
我认为更常用,但这两种方法都不是标准的。查看所有/2
文档,我注意到以下注意事项:

如果您的目的是创建变量绑定,那么forall/2控制结构是不够的。您可能正在寻找maplist/2、findall/3或foreach/2

果然,我们可以用
maplist/2
和lamba表达式完成您在这里尝试的操作:

?- length(L, 4), maplist([X]>>(length(X,4)), L).
L = [[_9462, _9468, _9474, _9480], 
     [_9558, _9564, _9570, _9576], 
     [_9654, _9660, _9666, _9672], 
     [_9750, _9756, _9762, _9768]].
您也可以使用
findall/3

?- length(L, 4), findall(X, (member(X, L), length(X, 4)), Xs).
L = [_10432, _10438, _10444, _10450],
Xs = [[_10580, _10586, _10592, _10598], 
      [_10550, _10556, _10562, _10568], 
      [_10520, _10526, _10532, _10538], 
      [_10490, _10496, _10502, _10508]].
注意,在后一种情况下,结果不是L,而是Xs

我认为这两种方法都比你提出的代码好一些,这对我来说似乎有点复杂,尽管我认为代码>聚合/代码>应该更经常使用。

< P>实际上说出你所相信的正在发生的事情:


连接的每个成员都是目标的一个副本,其中它与生成器共享的变量由相应解决方案中的值填充

人们看不到
foreach/2的大量使用
forall/2
我认为更常用,但这两种方法都不是标准的。查看所有/2
文档,我注意到以下注意事项:

如果您的目的是创建变量绑定,那么forall/2控制结构是不够的。您可能正在寻找maplist/2、findall/3或foreach/2

果然,我们可以用
maplist/2
和lamba表达式完成您在这里尝试的操作:

?- length(L, 4), maplist([X]>>(length(X,4)), L).
L = [[_9462, _9468, _9474, _9480], 
     [_9558, _9564, _9570, _9576], 
     [_9654, _9660, _9666, _9672], 
     [_9750, _9756, _9762, _9768]].
您也可以使用
findall/3

?- length(L, 4), findall(X, (member(X, L), length(X, 4)), Xs).
L = [_10432, _10438, _10444, _10450],
Xs = [[_10580, _10586, _10592, _10598], 
      [_10550, _10556, _10562, _10568], 
      [_10520, _10526, _10532, _10538], 
      [_10490, _10496, _10502, _10508]].
注意,在后一种情况下,结果不是L,而是Xs


我认为这两种方法都比你提出的代码好一些,这对我来说有点复杂,尽管我认为“代码>聚合<代码>更经常使用。

”它与生成器共享的变量用相应的解决方案填充了值。没有清楚地表明所说的值实际上是绑定在
foreach
之外的内容的副本……但是,这是我可能得到的最接近的答案,所以,好吧。对于我的具体例子,你们的替代方法更好,但我的意图是更一般的“对于每个解决方案X,在目标Y中应用它,并保持它的界限”;不过谢谢你。不管怎样,我的问题是关于
foreach
的操作,所以…足够好了。@Erhannis它清楚地表明目标是复制的。我认为这一点再清楚不过了。我也很惊讶,
foreach/2
使用副本,但我认为,你想要的是
setof/3
和friends所做的更具体的版本(其中
findall/3
就是其中之一)
aggregate
是更现代的版本。所以我想你可能有你需要的工具
foreach/2
只是不在其中,但它不是被复制的目标。它是生成器中特定存在的变量。至少,这是我在我的帖子中问到的。@Erhannis如果我复制一个术语并在该副本中统一变量,那么原始版本实际上什么都没有发生。这个查询的输出是否让您感到惊讶<代码>长度(L,4),成员(X,L),复制项(X,Y),Y=3。
在我的初始示例中,目标没有被复制;不明确。发电机也不是
foreach(成员(M,L),(长度(M,4))
减少到
\+(成员(M,L),\+长度(M,4))
。我不太清楚
\+
是如何工作的,因此我目前无法提供更多的分析。在任何情况下…我有一个函数可以做我想做的,所以我很好。“它与生成器共享的变量中填充了相应解决方案中的值”并不能清楚地表明所述值实际上是绑定在
foreach
之外的值的副本…但是,这是我可能得到的最接近的答案,所以,好啊对于我的具体例子,你们的替代方法更好,但我的意图是更一般的“对于每个解决方案X,在目标Y中应用它,并保持它的界限”;不过谢谢你。不管怎样,我的问题是关于
foreach
的操作,所以…足够好了。@Erhannis它清楚地表明目标是复制的。我认为这一点再清楚不过了。我也很惊讶,
foreach/2
使用副本,但我认为,你想要的是
setof/3
和friends所做的更具体的版本(其中
findall/3
就是其中之一)
aggregate
是更现代的版本。所以我想你可能有你需要的工具
foreach/2
只是不在其中,但它不是被复制的目标。这是变数