Prolog中列表连接程序的声明性解释
我有一个非常简单的问题:编写一个Prolog程序,实现append Prolog函数,将两个字符串连接起来,并以以下方式工作:Prolog中列表连接程序的声明性解释,prolog,declarative,Prolog,Declarative,我有一个非常简单的问题:编写一个Prolog程序,实现append Prolog函数,将两个字符串连接起来,并以以下方式工作: myappend1([],L,L). myappend1([X|L1],L2,[X|L3]) :- myappend1(L1,L2,L3). myappend2([],L,L). myappend2(L1,L2,L3) :- L1=[X|T], % Dimostra questo predicato AND
myappend1([],L,L).
myappend1([X|L1],L2,[X|L3]) :- myappend1(L1,L2,L3).
myappend2([],L,L).
myappend2(L1,L2,L3) :- L1=[X|T], % Dimostra questo predicato AND
L3=[X|L4], % Dimostra questo predicato AND
myappend2(T,L2,L4). % Dimostra questa funzione
myappend1([],L,L).
myappend1([X|L1],L2,[X|L3]) :- myappend1(L1,L2,L3).
myappend2([],L,L).
myappend2(L1,L2,L3) :- L1=[X|T], % Dimostra questo predicato AND
L3=[X|L4], % Dimostra questo predicato AND
myappend2(T,L2,L4). % Dimostra questa funzione
我认为我可以用声明的方式阅读它,如下所示:
事实表明:如果第一个列表(L1)是空的,而第二个列表(L2)不是空的,那么L1*L2的串联是L2,这是真的
如果事实不是真的,则意味着第一个列表不是空的,因此第一个列表和第二个列表的连接不是真的,即第二个列表
因此,让我调用第一个列表L1、第二个列表L2和第三个列表L3,如果L3是L1和L2的串联,则规则响应TRUE,否则为false
我认为这个规则的声明意义是:如果规则的主体是真的,那么规则的主体是真的
- 在head中,从L1列表和L3列表中提取第一个X元素(并尝试统一,如果继续匹配,则表示第三个列表不是第一个和第二个列表的串联)
- 在body中,调用第一个列表上的函数(不含X元素)、第二个列表和L3列表(表示连接)
myappend1([],L,L).
myappend1([X|L1],L2,[X|L3]) :- myappend1(L1,L2,L3).
myappend2([],L,L).
myappend2(L1,L2,L3) :- L1=[X|T], % Dimostra questo predicato AND
L3=[X|L4], % Dimostra questo predicato AND
myappend2(T,L2,L4). % Dimostra questa funzione
与前面的解决方案一样,事实只是说:如果第一个列表(L1)是空的,而第二个列表(L2)不是空的,L1*L2的串联是L2,这是真的
如果事实不是真的,则意味着第一个列表不是空的,因此第一个列表和第二个列表的连接不是真的,即第二个列表
如果事实不是真的,Prolog调用规则,此规则意味着:如果规则体为真,则规则头为真
在这种情况下,我可以这样读:
如果满足以下条件,则L1和L2的串联为L3为真:
- L1的当前第一个X元素与在第一个子列表、L2和第三个子列表上调用的连接列表和myappend2的当前第一个元素相一致。这是真的
对我来说,用声明的方式进行推理是非常困难的:(就像上次一样,您添加了代码中没有的限制。不要为此感到难过,Prolog非常不同,需要时间来适应它 让我们开始吧
append([], L, L).
你说:
如果第一个列表(L1)为空,而第二个列表(L2)不为空,则L1*L2的串联确实为L2
事实上,这条规则并没有说明L2是否为空——或者甚至是一个列表!——或者不是。它只是说附加到其他内容上的空列表就是其他内容。注意:
?- append([], foo, X).
X = foo.
这里的声明性阅读是“附加到L的空列表是L。”
如果事实不是真的,则意味着第一个列表不是空的,因此第一个列表和第二个列表的连接不是真的,即第二个列表
是的,这是正确的,但是Prolog并没有深入到身体中去。它只是说“第一个列表不是空的,所以这个规则不匹配;继续。”
下一条规则:
myappend1([X|L1], L2, [X|L3]) :- myappend1(L1,L2,L3).
你的评论对我来说太复杂了。我想说,这条规则说:“如果列表L1到L2的我的附录1是L3,那么列表[X后接L1]到L2的我的附录1就是列表[X后接L3”。”然而,这一解读的结果与你描述的完全一样
因此,您对第一个版本中发生的事情的理解是正确的
机械地说,第二个解决方案与第一个解决方案完全相同。唯一的区别是,我们将统一从条款的开头移到了正文中。在我看来,这个版本显然较差,因为它所做的只是为读者创造额外的工作
到目前为止,我认为你面临的问题是,你的声明性推理与Prolog的计算引擎密切相关。像我提供的那样,更纯粹的声明性阅读更简单,看起来更像Prolog所说的内容(与如何评估无关)
你需要练习来区分这些概念,但我认为这会帮助你变得更好(显然这是你关心的事情)。与此同时,像你困惑时那样来这里寻求帮助没有什么错。:)
如果我能提供更多帮助,请告诉我!就像上次一样,您正在添加代码中没有的限制。不要为此感到难过,Prolog非常不同,需要时间才能习惯 让我们开始吧
append([], L, L).
你说:
如果第一个列表(L1)为空,而第二个列表(L2)不为空,则L1*L2的串联确实为L2
事实上,这条规则并没有说明L2是否为空——或者甚至是一个列表!——或者不是。它只是说附加到其他内容上的空列表就是其他内容。注意:
?- append([], foo, X).
X = foo.
这里的声明性阅读是“附加到L的空列表是L。”
如果事实不是真的,那就意味着