理解特定 Prolog 递归谓词时遇到问题
我正在学习 Prolog。
我有这个递归谓词:
添加(0,Y,Y)。
添加(succ(X),Y,succ(Z)):-
添加(X,Y,Z)。
好吧,经验丰富的 Prolog 程序员可能会理解这个谓词的作用。乍一看,这并不难理解;当给定两个数字作为第一个和第二个参数时,它将返回将它们相加的结果作为第三个参数。听起来很简单?的确。
但我在理解它实际上是如何工作的方面遇到了一个重大问题。我已经多次阅读了这个谓词的描述,但我仍然无法理解它实际上是如何工作的。这就是我寻求帮助的原因。
通过查询:add(succ(succ(succ(0))), succ(succ(0)), R)。
Prolog 将实例化,从而将 R
返回为 succ(succ(succ(succ(succ(0)))))
。美好的。这一定是正确的。但我不知道为什么会这样。
我无法理解的是 Prolog 如何和为什么从原始查询中剥离最外层的 succ
函子。同样,由于它是递归的,它将结果作为参数传递给自身,从而剥离最外层的 succ 函子,直到目标可以统一。我确实了解 succ(Z)
和参数 R
的工作原理,但我似乎无法理解它实际上如何剥离最外层的 succ
> 函子,如前所述。对我来说,它似乎是添加一个succ
而不是删除它,因为谓词定义中的succ(X)
。
非常感谢任何帮助。提前致谢!
I'm in the process of learning Prolog.
I have this recursive predicate:
add(0,Y,Y).
add(succ(X),Y,succ(Z)) :-
add(X,Y,Z).
Alright, so experienced Prolog programmers will probably understand what this predicate does. At first sight it doesn't look too hard to understand; when given two numerals as the first and second argument, it will return the result of adding them up as its third argument. Sounds simple? Indeed.
But I have a major problem comprehending how this actually works. I've re-read the description of this predicate many times but yet I am not able to understand how it actually works. And that's why I'm asking for help.
By querying this:add(succ(succ(succ(0))), succ(succ(0)), R).
Prolog will instantiate and thus return R
as succ(succ(succ(succ(succ(0)))))
. Fine. This must be correct. However I have no clue why it is so.
What I have problems understanding is how and why Prolog strips off the outermost succ
functor from the original query. Again, as it is recursive, it passes on the results as arguments onto itself, and thus stripping off the outermost succ
functor until the goal can be unified. I do understand how the succ(Z)
and the argument R
works, but I am seemingly unable to comprehend how it actually strips off the outermost succ
functor, as mentioned. For me, it seems like it's adding a succ
instead of stripping it, because of succ(X)
in the predicate definition.
Any help is greatly appreciated. Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Prolog 看到行
add(succ(X),Y,succ(Z)) ...
并认为“哦,它可以与查询add(succ(succ(succ) (0))), succ(succ(0)), R).
,因为我可以设置(统一)X=succ(succ(0)), Y=succ(succ(0)), succ (Z)=R!” Prolog 的重要条件,决定它能做到的是 succ(succ(succ(0))) 可以匹配到succ(X )
,剩下的就简单了,因为Y和R可以在这第一步中任意设置(它们还没有统一)。并且succ(succ(succ(0)))
可以与succ(X)
匹配,因为 succ(A) 可以在任何时间 A 与 succ(B) 匹配可以匹配到B——你看计算机不难决定它。下一步是 Prolog 查看该行的其余部分 (:-
add(X,Y,Z)
) 并生成查询add(succ(succ(0)), succ( succ(0)), Z)
。请记住 succ(Z)=R 并且它不会改变,直到(如果)计算路径被拒绝。下一个查询将是add(succ(0), succ(succ(0)), Z')
,其中 succ(Z')=Z。然后add(0, succ(succ(0)), Z'')
,其中 succ(Z'')=Z'。然后Prolog可以使用第一条规则,确定
Z''=Y=succ(succ(0))
。然后就没有什么可做的了,所以它只需向输出写入R=succ(Z)=succ(succ(Z'))=succ(succ(succ(Y)))=succ(succ( succ(succ(succ(0)))))
。Prolog sees the line
add(succ(X),Y,succ(Z)) ...
and thinks "oh, it can be matched to the queryadd(succ(succ(succ(0))), succ(succ(0)), R).
, because I can set (unify) X=succ(succ(0)), Y=succ(succ(0)), succ(Z)=R !" The important condition for Prolog, the one that determines it can do it is thatsucc(succ(succ(0)))
can be matched tosucc(X)
, the rest is just simple, because Y and R can be in this first step set arbitrarily (they are not unified yet). Andsucc(succ(succ(0)))
can be matched tosucc(X)
just because succ(A) can be matched to succ(B) any time A can be matched to B - you see it is not very hard for computer to decide it.The next step is that Prolog looks at the rest of the line (:-
add(X,Y,Z)
) and generate queryadd(succ(succ(0)), succ(succ(0)), Z)
. Remember that succ(Z)=R and it won't change until (if) the computation path is rejected. The next query will beadd(succ(0), succ(succ(0)), Z')
, where succ(Z')=Z. Thenadd(0, succ(succ(0)), Z'')
, where succ(Z'')=Z'.Then can Prolog use the first rule, determine that
Z''=Y=succ(succ(0))
. Then there is nothing left to do, so it just write to the output thatR=succ(Z)=succ(succ(Z'))=succ(succ(succ(Y)))=succ(succ(succ(succ(succ(0)))))
.