SWI-Prolog中sort/4按三元子列表第3元素排序报错原因是什么
问题根源
你对sort/4第一个参数的理解存在偏差:SWI-Prolog的sort/4第一个参数指的是复合项的参数位置(从1开始计数),和列表的元素索引完全是两个概念。
Prolog里的列表本质是基于.函子的递归复合项,结构为.(头元素, 尾列表),不管长度是多少,列表作为复合项都只有2个参数,根本不存在第3个参数,这就是你调用sort(3, @<, X, Y)时抛出“参数3不存在”错误的核心原因。
你测试的三元子列表调用sort(2, @<, X, Y)能成功,也是因为取的是列表的第2个复合项参数(即尾列表)比较,只是你可能误以为它是按子列表的第二个元素排序,实际结果并不符合这个预期。
为什么二元子列表的测试没有报错?
你测试的二元子列表按参数2排序的调用虽然能运行,但实际执行逻辑和你以为的“按列表第二个元素排序”完全不一样:调用sort(2, ...)时取的是每个列表的尾部分,不是列表的第二个元素。只是你的测试用例刚好巧合让尾部分的排序结果和你预期的结果一致,才让你误以为这个调用是正确的。
按子列表第N个元素排序的正确写法
如果需要按子列表的指定位置元素排序,更稳妥的实现方式是先给每个子列表添加对应位置的排序键,用keysort/2排序后再剥离键即可,比如按三元子列表的第三个元素排序可以这么写:
X = [[1,2,3], [4,1,5], [3,5,2]], maplist(=(Elem, [_,_,Elem]), X, KeyedList), keysort(KeyedList, SortedKeyed), maplist(=(_, Elem), SortedKeyed, Y).
内容的提问来源于stack exchange,提问作者Fobia7
相关产品推荐
相关产品推荐

