关于SWI Prolog中列表的规则匹配

关于SWI Prolog中列表的规则匹配,prolog,Prolog,最近我开始学习Prolog,作为练习,我尝试实现一个谓词倒数第二个/2,给出列表中不会回溯的倒数第二个元素 当一个人使用cuts时,这个问题很小,但我尝试以与不使用cuts的last/2谓词的SWI Prolog实现类似的方式实现谓词: penultimate([X1, X2 | Rest], Elem) :- penultimate_([X1, X2 | Rest], X1, X2, Elem). penultimate_([], X1, _, X1). penultimate_([_]

最近我开始学习Prolog,作为练习,我尝试实现一个谓词
倒数第二个/2
,给出列表中不会回溯的倒数第二个元素

当一个人使用cuts时,这个问题很小,但我尝试以与不使用cuts的
last/2
谓词的SWI Prolog实现类似的方式实现谓词:

penultimate([X1, X2 | Rest], Elem) :-
  penultimate_([X1, X2 | Rest], X1, X2, Elem).

penultimate_([], X1, _, X1).
penultimate_([_], _, X2, X2).
penultimate_([X1, X2 | Rest], _, _, Penultimate) :-
  penultimate_(Rest, X1, X2, Penultimate).
当列表的长度为偶数时,此代码按预期工作,但当使用奇数长度的列表馈送时,我得到以下结果:

?- penultimate([1,2,3], X).
X = 2 ;
false.
我能想到的唯一原因是,SWI Prolog匹配系统将我程序中的规则视为与一个元素列表进行匹配的可能性,即使规则头中的列表至少需要2个元素。这是正确的吗?

试试:

penultimate([X1, X2 | Rest], Penultimate) :-
    penultimate(Rest, X1, X2, Penultimate).

penultimate([], Penultimate, _, Penultimate).
penultimate([X3| Rest], _, X2, Penultimate) :-
    penultimate([X2, X3| Rest], Penultimate).
电话样本:

| ?- penultimate([1,2,3,4,5], P).

P = 4

yes
| ?- penultimate([1,2,3,4], P).  

P = 3

yes
| ?- penultimate([1,2,3], P).  

P = 2

yes
| ?- penultimate([1,2], P).  

P = 1

yes
| ?- penultimate([1], P).  

no
大多数Prolog系统上的索引可以区分空列表(原子)或非空列表(复合术语),但通常不会在列表中执行深度索引。

尝试:

penultimate([X1, X2 | Rest], Penultimate) :-
    penultimate(Rest, X1, X2, Penultimate).

penultimate([], Penultimate, _, Penultimate).
penultimate([X3| Rest], _, X2, Penultimate) :-
    penultimate([X2, X3| Rest], Penultimate).
电话样本:

| ?- penultimate([1,2,3,4,5], P).

P = 4

yes
| ?- penultimate([1,2,3,4], P).  

P = 3

yes
| ?- penultimate([1,2,3], P).  

P = 2

yes
| ?- penultimate([1,2], P).  

P = 1

yes
| ?- penultimate([1], P).  

no
大多数Prolog系统上的索引可以区分空列表(原子)或非空列表(复合术语),但通常不会在列表中执行深度索引