prolog - 关于 SWI Prolog 中列表的规则匹配
问题描述
最近我开始学习 Prolog,作为一个练习,我尝试实现一个谓词penultimate/2
,给出一个不会回溯的列表的倒数第二个元素。
这个问题在使用削减时是微不足道的,但我尝试以与 SWI-Prolog 实现last/2
不使用削减的谓词类似的方式实现谓词:
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 系统上的索引可以区分空列表(原子)或非空列表(复合术语),但通常不会在列表中执行深度索引。
推荐阅读
- javascript - 如何隐藏画布元素?
- javascript - HTML 模板未在屏幕上呈现
- r - R - 平滑散点图曲线和对角轴
- linux - 我正在尝试在 bash 中使用 mlocate 和 for 循环来搜索大量文件
- ruby - ruby:无法理解内存地址
- hive - 无法删除指向不再存在的 Azure 存储帐户的 Hive 表
- android - 为什么我的交错网格布局不平衡?
- javascript - 反应状态未设置为仅对象中的一个键
- firebase - 使用 Microsoft 域名服务器、Google Domains 和 Firebase 托管
- python - Python列表转换或范围?(或者可能是 Discord py 特定问题)