foreach - SWI-Prolog 的`foreach/2` 是否涉及`freeze/2`?
问题描述
在 SWI Prolog 的foreach/2上,我们读到:
包含foreach/2
谓词的“聚合”库的兼容性被声明为
Quintus, SICStus 4. forall/2 是内置的 SWI-Prolog,term_variables/3 是具有不同语义的内置 SWI-Prolog。
foreach(:Generator, :Goal)
对于生成器的每个证明,我们依次制作具有适当替换的Goal副本,然后按顺序执行这些副本。例如,
foreach(between(1,3,I), p(I))
等价于p(1), p(2), p(3)
。请注意,这与
forall/2
. 例如,forall(between(1,3,I), p(I))
相当于
\+ \+ p(1), \+ \+ p(2), \+ \+ p(3)
.诀窍
foreach/2
是确保正确恢复 未出现在Generator中的Goal变量。(如果没有这样的变量,你不妨使用。)forall/2
就像,这个谓词在Generator
forall/2
上做了一个失败驱动的循环 。与 不同的是,目标作为普通连词执行,并且可能以多种方式成功。forall/2
以 SWI Prolog 页面为例,没有最终统一:
?- foreach(between(1,4,X), dif(X,Y)).
dif(Y, 4),
dif(Y, 3),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1),
dif(Y, 3),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1),
dif(Y, 2),
dif(Y, 1),
dif(Y, 1).
我不确定为什么会有所有dif/2
实例化的输出以及为什么会有相同子目标的重复。
foreach/2
应该确定 multiple 的合取dif(Y,i)
为真,因为未绑定的变量Y
显然dif
来自整数i。
但现在:
?- foreach(between(1,4,X), dif(X,Y)), Y = 5.
Y = 5.
好的,所以除了Y=5
目标成功之外没有输出。但是有什么Y=5
变化呢?之后foreach/2
,Prolog 已经能够确定这foreach/2
是真的(考虑到当时运行的状态Y
)foreach/2
,所以添加Y=5
不应该改变任何东西。
但是之后:
?- foreach(between(1,4,X), dif(X,Y)), Y = 2.
false.
后来的统一改变了foreach/2
. 如何?
我认为可能会freeze/2
涉及Y
到使情况变得有趣,例如,我们确实在计算:
freeze(Y,foreach(between(1,4,X), dif(X,Y))).
这或多或少可以解释打印输出。例如:
?- freeze(Y,foreach(between(1,4,X), dif(X,Y))).
freeze(Y, foreach(between(1, 4, X), dif(X, Y))).
?- freeze(Y,foreach(between(1,4,X), dif(X,Y))), Y=5.
Y = 5.
?- freeze(Y,foreach(between(1,4,X), dif(X,Y))), Y=2.
false.
这是怎么回事?
解决方案
您观察到的“冻结”行为是由于 dif/2 而不是 foreach/2。
谓词 dif/2 确保它的两个参数不相同并且不会变得相同。因此,如果两个参数可能变得相同,则 dif/2 将暂停,直到它可以确定它们是否相同。
推荐阅读
- node.js - NPM 运行开始:“系统找不到指定的路径。”
- swift - 在 UITableView 中选择单个单元格以转到 UITableView 以显示不同的学生列表数据
- azure - 在 Azure DevOps 中设置/更改默认组织
- java - Restlet 请求对象不包含身份验证信息
- android - 带有 SurfaceView 的 Android MediaPlayer 在 Prepare() 方法上失败
- django - Annotate 中的 ExpressionWrapper 在 django 中不起作用
- c++ - C++ 2 维向量
- javascript - React Router 没有在登录和注销时重定向
- matlab - 使用matlab绘制归一化自相关
- string - MIPS 将用户输入作为字符串输入并转换为以 33 为底的整数