理解差异列表(Prolog)
我很难理解差异列表,尤其是在这个谓词中:理解差异列表(Prolog),prolog,palindrome,difference-lists,Prolog,Palindrome,Difference Lists,我很难理解差异列表,尤其是在这个谓词中: palindrome(A, A). palindrome([_|A], A). palindrome([C|A], D) :- palindrome(A, B), B=[C|D]. 有人能帮我跟踪发生的事情吗 palindrome(A, A). palindrome([_|A], A). palindrome([C|A], D) :- palindrome(A, B), B=[C|D]. 将该谓词的参数视为差异列表,第一个子句
palindrome(A, A).
palindrome([_|A], A).
palindrome([C|A], D) :-
palindrome(A, B),
B=[C|D].
有人能帮我跟踪发生的事情吗
palindrome(A, A).
palindrome([_|A], A).
palindrome([C|A], D) :-
palindrome(A, B),
B=[C|D].
将该谓词的参数视为差异列表,第一个子句说,从a
到a
的列表(即空列表)是回文
第二句说,一个元素列表是回文,不管这个元素是什么
不要惊慌!差异列表只是带有显式结尾“指针”的列表。 一个普通的列表,比如说
[1,2,3]
,是它的开始和结束之间的差异;正常列表的结尾总是空列表,[]
。也就是说,对于一个列表[1,2,3]
,我们应该将这个谓词称为回文([1,2,3])
——也就是说,检查差异列表[1,2,3]-[]
是否是回文
从操作的角度来看,差异列表只不过是一个(可能是开放式的)具有显式维护的“结束指针”的列表,例如:a-Z
,其中a=[1,2,3 | Z]
和Z=[]
。实际上,[1,2,3 |[]]
与[1,2,3]
是一样的。但是当Z
尚未实例化时,列表A
仍然是开放式的-它的“结束指针”Z
可以实例化为任何对象(当然,只有一次,没有回溯)
如果我们稍后将Z
实例化为一个开放式列表,比如说,Z=[4 | W]
,我们将得到一个新的扩展差异列表a-W
,其中a=[1,2,3,4 | W]
。旧的一个将成为A-Z=[1,2,3,4 | W]-[4 | W]
,即仍然表示一个开放式列表的前缀[1,2,3]
。一旦关闭,例如使用W=[5]
,所有对数变量仍然表示其相应的差异列表(即A-Z
,A-W
…),但A
不再是开放式的,因此不能再扩展
不使用-
functor,通常只使用diff列表定义的两部分作为谓词的单独参数。当我们总是把它们当作一对中的两部分来使用/对待时,它们就在概念上形成了一对。是一样的
继续。第三句说,要使
[C|A]-D
成为回文,A-B
必须是回文,B
必须是[C|D]
<代码>A、D、B是列表,C
是列表的一个元素。这可能令人困惑;让我们改用V
。此外,使用Z
和Y
代替D
和B
,提醒我们列表的“结尾”:
palindrome([V|A], Z):- palindrome(A, Y), Y=[V|Z].
V ................. V ----
^ ^ ^
| | |
| | Z
A Y = [V|Z]
事实上,当
…
核心是回文时,在其周围放置两个V
s会给我们带来另一个回文。下面是一个总结,希望能从前面的讨论中提炼出最好的内容,并添加一个小但重要的简化
首先,应该在当前问题的上下文中理解原始问题,可以将其表述为定义一个Prolog谓词,该谓词将检查列表是否是回文,或者更一般地说是生成回文。我们希望探索使用差异列表的实现,因此我们可以从以下方面开始:
% List is a palindrome if List - [] is a palindrome:
palindrome( List ) :- palindrome(List, []).
(如其他地方所解释的,如果列表是两个列表的串联
前面和后面,然后前面可以被视为是不同的
在List和Back之间,也就是说,Front可以被视为等价于(List-Back)
为了定义回文/2,我们从两个“基本情况”开始,一个空列表和一个单例:
% The empty list (L-L) is a palindrome:
palindrome(L, L).
% A singleton list, ([X|L] - L), is a palindrome:
palindrome([X|L], L).
现在让我们谈谈一般情况
如果一个包含多个元素的列表是回文,那么
将看起来像这样:E。。。E
在哪里。。。是一个(可能是空的)回文
加上一个尾巴,尾巴,我们的清单一定是这样的:E。。。尾翼
将这个常规列表写成[E|Rest],我们现在可以看到原始列表([E|Rest]-Tail)是回文,如果(Rest-[E|Tail])是回文,
或者根据我们的谓词回文/2:
很容易看出,这与原来的公式是等价的
就这样!例如,现在我们可以为回文生成模板:
?- palindrome( X ).
X = [] ;
X = [_G1247] ;
X = [_G1247, _G1247] ;
X = [_G1247, _G1253, _G1247] ;
X = [_G1247, _G1253, _G1253, _G1247]
....
第一条似乎是错的,它的意思是identity@CapelliC:不是标识,而是空列表。@false我不懂。。。难道
A
不会与任何东西统一,而不仅仅是空列表吗?这怎么不是一种普遍的身份关系?@错,我想可能有一些沟通错误?我相信卡佩里克的话是在指出,正如这里所写的,第一条定义了身份。你是说,理想情况下,在回文正确实现的不同上下文中,这个子句应该是空列表吗?@aBathologist:OP的程序就是DCG的扩展。见我的第一条评论。因此,它必须用作回文(A,[])。您的“端点”指向哪里:?-短语(n,[A],[b])。
带有n,[b]-->[A]
?@false我们不应该这样称呼它。[a] -[b]不是一个差异列表。OP的回文
是常规的Prolog谓词,而不是DCG规则,对吗?如果您不接受该示例,请相应地将其扩展到可以使用短语/2
调用的内容。您的解释基于一个非常具体的属性,该属性不适用于每个DCG或差异列表;因此,这并不能解释它们的本质。而且:我不同意你所说的[a]-[b]不是一个不同的列表。在所有这些差异出现在DCG中之后,DCG使用差异列表。@false我不准备以任何程度的严格性来为我的类比辩护。这对我很有帮助。如果DCG规则接受[a]-[b],那么我可以认为它们比diff列表更大<代码>回文([a],[b])将失败,我认为这没有问题。我当然可能是
?- palindrome( X ).
X = [] ;
X = [_G1247] ;
X = [_G1247, _G1247] ;
X = [_G1247, _G1253, _G1247] ;
X = [_G1247, _G1253, _G1253, _G1247]
....