有人能给我解释一下为什么这个prolog查询是这样工作的吗?它的定义是:
add(0,Y,Y).
add(succ(X),Y,succ(Z)):- add(X,Y,Z).
考虑到这一点:
?- add(succ(succ(succ(0))), succ(succ(0)), R).
下面是查询的跟踪:
Call: (6) add(succ(succ(succ(0))), succ(succ(0)), R)
Call: (7) add(succ(succ(0)), succ(succ(0)), _G648)
Call: (8) add(succ(0), succ(succ(0)), _G650)
Call: (9) add(0, succ(succ(0)), _G652)
Exit: (9) add(0, succ(succ(0)), succ(succ(0)))
Exit: (8) add(succ(0), succ(succ(0)), succ(succ(succ(0))))
Exit: (7) add(succ(succ(0)), succ(succ(0)),
succ(succ(succ(succ(0)))))
Exit: (6) add(succ(succ(succ(0))), succ(succ(0)),
succ(succ(succ(succ(succ(0))))))
关于该教程,最让我困惑的部分是,在第一个参数中,succ被剥离,并递归。然而,在递归时,R获得了一个成功的.怎么做?!另外,在第一个出口(9),零从哪里来?我是prolog的新手,我正在尝试理解这门语言作为家庭作业。任何帮助都非常感谢。
注意:对于任何感兴趣的人,指向本教程的链接是http://www.learnprolognow.org/lpnpage.php?pagetype=html&pageid=lpn-htmlse9
发布于 2012-04-25 14:37:19
然后,跟踪将显示已完成的实际工作的详细信息,并允许您从历史的角度查看它。
当Prolog必须选择一个规则(一个call
)时,它会使用您给它的name
(所谓的functor
),并尝试unify
规则头部中的每个参数。然后我们通常说,Prolog还考虑了arity
,即参数的数量,用于选择。
Unification
试图“使相等”两项,值得注意的结果是所谓的变量的bindings
。您已经知道变量是以Uppercase
开头的那些名称。这样的名称标识规则中的未指定值,即参数为placeholders
。为了避免混淆,当Prolog显示轨迹时,变量会被重命名,这样我们就可以识别它们,因为相关的细节是在证明过程中建立的identities
或绑定。
然后,您可以在trace中看到这样的_G648
符号。R是唯一的(只在顶层调用中出现),所以这个Prolog友好地保留了用户友好的名称,但Z来自程序,可能会出现多次,然后被重命名。
回答这个问题
?- add(succ(succ(succ(0))), succ(succ(0)), R).
Prolog首先尝试匹配
add(0,Y,Y).
并且失败,因为succ( 0 ))不能等于0。然后尝试
add(succ(X),Y,succ(Z)) :- add(X,Y,Z).
因此,必须解决这些绑定(在调用者术语的左侧):
succ(succ(succ(0))) = succ(X)
succ(succ(0)) = Y
R = Z
你可以看到为什么X变成了succ(succ(0))
,我们有一个新的目标要证明,也就是刚刚建立了绑定的规则主体add(X,Y,Z)
:
以此类推。直到X变为0
并且目标匹配
add(0,Y,Y).
HTH
发布于 2018-05-31 21:19:48
(6) Call: add(succ(succ(succ(0))), succ(succ(0)), R) % R = succ(_G648)
(7) Call: add(succ(succ(0)), succ(succ(0)), _G648) % _G648 = succ(_G650)
(8) Call: add(succ(0), succ(succ(0)), _G650) % _G650 = succ(_G652)
(9) Call: add(0, succ(succ(0)), _G652) % _G652 = succ(succ(0))
(9) Exit: add(0, succ(succ(0)), succ(succ(0)))
(8) Exit: add(succ(0), succ(succ(0)), succ(succ(succ(0))))
(7) Exit: add(succ(succ(0)), succ(succ(0)), succ(succ(succ(succ(0)))))
(6) Exit: add(succ(succ(succ(0))), succ(succ(0)), succ(succ(succ(succ(succ(0))))))
正如您所看到的,四个出口是多余的,最终的答案在(9) Exit
点上已经知道了;在这一点上只有一个出口就足够了:
% R = succ(_G648)
% _G648 = succ(_G650)
% _G650 = succ(_G652)
% _G652 = succ(succ(0))
% thus,
% R = succ( succ( succ( succ(succ(0)) )))
这确实是在尾部调用优化下发生的事情,因为谓词定义确实是尾部递归的,并且R
下的结果是以自顶向下的方式构建的,“洞”逐渐被逻辑变量的实例化所填补。
https://stackoverflow.com/questions/10308557
复制相似问题