recursion - Prolog中的递归成功加法
问题描述
add(0,Y,Y).
add(succ(X),Y,succ(Z)) :-
add(X,Y,Z).
我不明白这个是如何工作的。如果我运行查询:
add(succ(succ(succ(0))), succ(succ(0)), R)
它如何从第一个参数中删除 succ ?
如果我运行它:
X=succ(succ(succ(0)))
Y=succ(succ(0))
R=?
这满足了身体。我们将它们输入到头部:
add(succ(X),Y,succ(Z)) %% becomes
add(succ(succ(succ(0))),succ(succ(0)),succ(R))
即它看起来好像它只是添加了成功,而不是从第一个参数中删除它们?我看到关于这个确切问题的另一篇文章,但这对我来说没有意义。
解决方案
当您调用目标add(succ(succ(succ(0))), succ(succ(0)), R)
并且 Prolog 尝试使用 head 执行子句时add(succ(X),Y,succ(Z))
,就会发生统一。统一是 Prolog 的核心概念之一,理解它很重要。统一也是操作员执行的=
操作。执行子句头部时发生的情况与执行以下等效查询时发生的情况完全相同:
?- add(succ(succ(succ(0))), succ(succ(0)), R) = add(succ(X),Y,succ(Z)).
重要的是要理解统一不仅仅是“拆包”或“构建”术语,而是两者同时进行。
它可以从术语中“提取”信息:
?- X = f(a), Y = f(Z), X = Y.
X = Y, Y = f(a),
Z = a.
在这里,我们发现这a
是 中f
函子的参数X
。
它可以“构造”术语:
?- X = f(Y), Y = g(h).
X = f(g(h)),
Y = g(h).
在这里,我们将术语“插入”g(h)
到Y
.X
它也可以同时对多个术语进行:
?- X = f(a, B), Y = f(A, b), X = Y.
X = Y, Y = f(a, b),
B = b,
A = a.
这里统一“解开”了这两个f
术语,然后在每个术语中“填充”了一个洞。
现在,有了这些知识,你的例子中的统一有什么作用?
?- add(succ(succ(succ(0))), succ(succ(0)), R) = add(succ(X),Y,succ(Z)).
R = succ(Z),
X = Y, Y = succ(succ(0)).
特别是,当succ(succ(succ(0)))
与 统一时succ(X)
, this 将绑定X
到succ(succ(0))
。不受整个术语的约束,X
而仅与“内部”部分有关。这就是从论点中删除一级的原因。succ(succ(succ(0)))
succ
推荐阅读
- three.js - 如何使用 jquery 和三个 js 从这段代码中获取材质颜色
- python - re.findall() 在使用 \w*$ 时返回空元素,而预计只返回最后一个单词
- scala - 在 Spark 中找不到 CarbonData 类 CarbonSessionStateBuilder 错误
- atom-editor - 原子缩进问题
- apache-kafka - 当架构注册表需要 TLS 客户端身份验证时,无法从数据流作业连接到架构注册表
- python - 使用 shutil.copyfileobj 时出现 AttributeError
- c# - 正确的 Web 方法响应长度处理
- java - 无法使用 jasypt 加密进行 maven 发布
- c# - 从公共类中的 appsettings.json 文件中获取值
- php - 自定义数组