Prolog:满足目标的可变实例化

时间:2017-01-03 03:24:17

标签: prolog variable-assignment

在阅读时钟,Mellish的 Prolog编程(2003)时出现了问题。

假设我们使用列表从一个句子映射到另一个句子

change(keith, he).
change(very, too).
change(X, X).

alter([], []). 
alter([H|T], [X|Y]) :- change(H, X), alter(T, Y).

有人可以阐明变量是如何实例化的吗?我的书并没有特别深入。

例如,使用跟踪时:

Call: (7) alter([keith, is, very, cool], _G2676) ? creep
Call: (8) change(keith, _G2756) ? creep
Exit: (8) change(keith, he) ? creep
Call: (8) alter([is, very, cool], _G2757) ? creep
Call: (9) change(is, _G2759) ? creep
Exit: (9) change(is, is) ? creep
Call: (9) alter([very, cool], _G2760) ? creep
Call: (10) change(very, _G2762) ? creep
Exit: (10) change(very, too) ? creep
Call: (10) alter([cool], _G2763) ? creep
Call: (11) change(cool, _G2765) ? creep
Exit: (11) change(cool, cool) ? creep
Call: (11) alter([], _G2766) ? creep
Exit: (11) alter([], []) ? creep
Exit: (10) alter([cool], [cool]) ? creep
Exit: (9) alter([very, cool], [too, cool]) ? creep
Exit: (8) alter([is, very, cool], [is, too, cool]) ? creep
Exit: (7) alter([keith, is, very, cool], [he, is, too, cool]) ? creep
B = [he, is, too, cool] .

我看到打开了几个内存地址引用,就像在规则中遇到alter时一样,并递归配对为:

alter([is, very, cool], ???? tail of Z

看起来新Y将取Z的尾部值,但由于Z只是对内存中某个点的引用,这些变量在返回之前如何赋值?同样源于这种混淆的是,我无法清楚地表明变更谓词中尾部X中的值如何能够“建立”,从而保留变更谓词中的新值。 。

1 个答案:

答案 0 :(得分:2)

你带来了很多程序性的想法("行李")来阅读这条痕迹。让我们尝试用Prolog的眼睛阅读它:

Call: (7) alter([keith, is, very, cool], _G2676) ? creep

Prolog只是在这里重申你的目标。您可以忽略生成的变量_G2676中的数字;它不是内存位置,生成这些变量名称的方法因实现和平台而异,Prolog中没有机制来读取任意内存位置,这些生成的变量数字对你来说几乎无法访问每一种感觉。它只是一个内部记账的东西。

你可能发出了这样的查询:

?- alter([keith, is, very, cool], B).

这样想。你问Prolog,"证明alter([keith, is, very, cool], B)并告诉我B是什么。"所以它会尝试去做。

Call: (8) change(keith, _G2756) ? creep

这里发生了什么? Prolog查看了您的查询,发现您正在使用alter/2。它将alter/2 head 替换为alter/2 body 。快速Prolog解剖课:

alter([H|T], [X|Y]) :- change(H, X), alter(T, Y).
-------------------    --------------------------
   "the head"                  "the body" 

所以Prolog说,"要证明alter([keith,is,very,cool], B)我必须用alter([H|T], [X|Y]) = [keith,is,very,cool][H|T] = B证明[X|Y] 。 (Prolog以合理的方式管理这些变量名。)所以现在Prolog用change(H, X), alter(T, Y)替换活动查询。除外,[H|T] = [keith|[is,very,cool]]B = [X|Y]。因此,在跟踪中打印的内容是:

Call: (8) change(keith, _G2756) ? creep

现在Prolog必须查看它的第一个change/2子句,并查找change(keith, he)。所以Prolog说,"啊哈! X = he"然后打印:

Exit: (8) change(keith, he) ? creep

Prolog现在说,"好吧,我只需要通过查看alter/2正文中的下一步来完成我在一秒钟前开始的查询,这是:

Call: (8) alter([is, very, cool], _G2757) ? creep

好吧,就像以前一样,Prolog现在要用alter/2的主体替换alter/2查询并尝试实现它,这意味着它现在必须证明:

Call: (9) change(is, _G2759) ? creep

这个稍微有点儿,因为change/2的第一个条款不匹配。 Prolog无法将keithis统一起来,因此它会失败并转到第二个子句。它无法将isvery统一起来,因此会转到第三个子句并将is与自身统一起来:

Exit: (9) change(is, is) ? creep

这个过程重复,处理非常/太酷和冷却,然后Prolog用完列表成分,然后输入alter/2的基本情况:

Call: (11) alter([], _G2766) ? creep
Exit: (11) alter([], []) ? creep

如果您需要注意,您应该注意到带有匿名变量的查询行开始Call:表示Prolog正在更改问题,当Prolog回答问题时,该行以{开头{1}}。还有一些其他的东西可以开始告诉你关于Prolog的执行模型的其他事情:Exit:Retry:。但是你没有在这里,因为你的查询实际上是第一次尝试。

从这里开始,你得到Fail:,因为一切都已成功统一,Prolog基本完成。但这就是"建立"正在发生:

Exit

这里发生的事情是Exit: (11) alter([], []) ? creep Exit: (10) alter([cool], [cool]) ? creep Exit: (9) alter([very, cool], [too, cool]) ? creep Exit: (8) alter([is, very, cool], [is, too, cool]) ? creep Exit: (7) alter([keith, is, very, cool], [he, is, too, cool]) ? creep 被证明了,所以它返回到外部调用(注意那里的数字;它们告诉你关于调用堆栈),这意味着Prolog现在已经证明了alter([], [])为真,这意味着它已被证明alter([cool], [cool])是真的,等等。这只是尾递归的工作方式。最后,它输出您的查询成功:

alter([very, cool], [too, cool])

所以,就像你说的那样,这里真的没有打开内存地址。

  

看起来新的Y会取Z的尾部值,但由于Z只是对内存中某个点的引用,这些变量在返回之前如何赋值?

在"正常"在编程语言中,您可以使用某些值调用函数,并将一个值作为返回值返回。 Prolog不是一种普通的编程语言;你没有定义函数,你正在定义关系。关系比函数更少受约束:有时您的参数是输入,有时它们是输出。 Prolog中的变量不是"对内存中斑点的引用。"它们只是数据的名称;它们可以 ground free ,具体取决于它们是否已被弄清楚。

Prolog中的每个评估步骤,Prolog都在搜索自由变量的绑定。这称为统一,是Prolog中的基本执行模型。当您发出B = [he, is, too, cool] . 之类的查询时,您要求Prolog证明change(keith, X)为真,并为您提供值为X的值。 Prolog会看一下,然后回来change(keith, X)。但你也可以问它true, X = he,Prolog会查看它并说change(X, he)。这是使它成为一种关系而不是一种功能的一部分。你也可以说true, X = keith它会以change(X, Y)返回,而且多种结果是你知道你处理关系而不是函数的另一种方式。

所以在Prolog中,变量不是内存中的一个位置",它是名称和值之间的绑定,Prolog能够在评估的任何步骤建立绑定,而不仅仅是在计算中或计算过程中,但在成功计算的路上也是如此!

我敢打赌,如果你回顾一下你的书,你会发现它会详细介绍这一点。它是那里最好的Prolog书之一,它肯定会详细介绍这些东西。但我希望无论如何这有帮助!