我是prolog的新手,我基本上试图写一个如果给定项目是给定列表中的最后一项,则评估为true的子句。这就是我所拥有的:
last(X,[Y|X]).
last(X,[Y|Z]) :- last(X,Z).
我认为这可以解决问题,但是当我问prolog时:
?- last(c,[a,b,c]).
Prolog返回false。我尝试了以下查询,看看Prolog认为应该符合我对last的定义:
?- last(c,X).
X = [_G530|c] ;
X = [_G530, _G533|c] ;
X = [_G530, _G533, _G536|c]
所以,我不确定的是为什么“|”符号仍然在列表中?
更新:last([c],[a,b,c])产生所需的行为。但是,我不确定为什么我的第一个论点必须是一个列表?
答案 0 :(得分:7)
你可能想要这个:
last(X,[X]).
last(X,[_|Z]) :- last(X,Z).
|
表示“尾巴”或“列表的其余部分”。
使用?- last(c,X).
Prolog生成列表(根据您的第一个定义),其中c为最后一项。
当您查询?- last(c,[a,b,c]).
时,它会返回false,因为您没有为只有一个项目[X]
或[X|[]]
的列表定义案例。因此,当列表短于两个项目时,它会失败。
但是,last([c],[a,b,c])
成功,因为你得到[b|_29]
或任何表示尾部可能是任何列表的东西。所以'_29'可以是'[c]',满足第一个定义,如last([c],[b|[c]]).
请记住,Prolog中的非空列表实际上是第一个列表项(头)和其余列表(尾部) )。通常写为[head | tail]。
答案 1 :(得分:3)
为什么不从语法角度来看待事物。那么列表中的最后一个元素是什么?
last(X, Xs) :-
phrase( ( ..., [X] ), Xs).
... --> [] | [_], ... . % any sequence
答案 2 :(得分:2)
答案 3 :(得分:1)
因为列表的尾部本身就是一个列表。
Prolog中的列表可以看作是[H | T]
,其中H
是第一个元素(头部),而T
(尾部)是列表所有其他元素。
当你分解它时,你的列表[a, b, c]
实际上是[a | [b | [c | [] ] ] ]
(最后一个尾部总是一个空列表):
List: [a, b, c] Head: a Tail: [b, c]
List: [b, c] Head: b Tail: [c]
List: [c] Head: c Tail: []
所以当你到达问题是last(c, [b, c])
时,它会分解为last(c, [b|[c]])
,这就是第一个子句无法实例化的原因,因为X
可以不是c
和[c]
。这就是为什么当你问last([c],[a,b,c])
时 的工作原因。
version proposed by alpha有效,因为它考虑了这一点:
% A list ends with an element if contains exactly that element.
last(X,[X]).
% A list ends with an element if its tail ends with that element.
% (Since we don't care about the head, we use an underscore).
last(X,[_|T]) :- last(X,T).