Prolog:满足目标的变量实例化
当阅读Mellish的Clocksin在Prolog(2003)中的编程时,出现了一个问题 假设我们使用列表从一个句子映射到另一个句子Prolog:满足目标的变量实例化,prolog,variable-assignment,Prolog,Variable Assignment,当阅读Mellish的Clocksin在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
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只是内存中某个点的引用,那么在返回之前这些变量是如何赋值的呢?这种混淆的另一个原因是,我无法清楚地说明alter谓词中尾部的头部X中的值是如何“构建”的,因为它在哪里保留了change谓词中的新值 阅读此跟踪时,您带来了许多程序性想法(“行李”)。让我们试着用序言的眼光来阅读:
Call: (7) alter([keith, is, very, cool], _G2676) ? creep
序言只是在这里重申你的目标。您可以忽略生成的变量\u 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
的头部替换为alter/2
的主体。快速序言解剖课:
alter([H|T], [X|Y]) :- change(H, X), alter(T, Y).
------------------- --------------------------
"the head" "the body"
因此,Prolog说,“为了证明alter([keith,is,very,cool],B)
我必须用[keith,is,very,cool]
证明alter([H | T],[X | Y])
来证明alter([H | T],[X | Y])
(Prolog以合理的方式管理这些变量名)。因此,现在Prolog用change(H,X)替换活动查询(T,Y)
。除了,[H | T]
=[keith |[is,very,cool]]
和B
=[X | Y]
。因此,在跟踪中打印的内容是:
Call: (8) change(keith, _G2756) ? creep
现在,Prolog必须查看它的change/2
的第一个子句,找到change(keith,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无法将keith
与is
统一起来,因此它失败并转到第二个子句。它无法将is
与very
统一起来,因此它转到第三个子句并将is
与自身统一起来:
Exit: (9) change(is, is) ? creep
这个过程重复进行,处理very/too和cool/cool,然后Prolog运行完列表的组成部分,然后输入基本的alter/2
:
Call: (11) alter([], _G2766) ? creep
Exit: (11) alter([], []) ? creep
如果您正在注意,您应该注意到,带有匿名变量的查询行以Call:
开头,表示Prolog正在更改问题,当Prolog回答问题时,该行以Exit:
开头。行的开头可以告诉您有关Prolog exe的其他信息执行模型:重试:
和失败:
。但是这里没有这些模型,因为您的查询在第一次尝试时实际上是有效的
从这里开始,您只需退出,因为一切都已成功统一,Prolog基本完成。但这就是“构建”的地方:
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
这里发生的事情是,alter([],[])
被证明是正确的,因此它返回到外部调用(注意那里的数字;它们告诉您关于调用堆栈的情况),这意味着Prolog现在已经证明alter([cool],[cool])
是正确的,这意味着它已经证明了alter([very,cool],[tool,cool]))
为true,依此类推。这只是尾部递归的工作方式。最后它输出您的查询成功:
B = [he, is, too, cool] .
所以,正如你所说,这里实际上没有内存地址被打开
看起来新的Y会取Z的尾部的值,但是既然Z只是内存中某个点的引用,那么在返回之前这些变量是如何赋值的呢
以“正常”的方式在编程语言中,您使用一些值调用函数,然后返回一个值作为返回值。Prolog不是一种普通的编程语言;您不是在定义函数,而是在定义关系。关系比函数约束少:有时参数是输入,有时是输出。Prolog中的变量它们不是“记忆中的点的引用”。它们只是数据的名称;它们可以是地面的,也可以是自由的,这取决于它们是否被发现
Prolog中的每一步求值,Prolog都在搜索自由变量的绑定。这称为统一,是Prolog中的基本执行模型。当您发出类似change(keith,X)
的查询时,您要求Prolog证明change(keith,X)
是真的,并为您提供使其成为真的值X。Prolog将查看该值并返回true,X=he
。但您也可以要求它更改(X,he)
并且Prolog将查看它并说,为真,X=keith
。这是使其成为关系而不是函数的一部分。您也可以说更改(