我对Prolog还比较陌生,我尝试了以下代码:
| ?- append([1],2,R).
R = [1|2]
yes
我不知道符号
[1 | 2]
的含义。我试图搜索相关信息,但非常艰难,没有找到任何内容。我猜这类似于Lisp中由(cons 1 2)
生成的(1 . 2)
。能否有人解释或提供相关说明?如果有用的话,我正在使用GNU-prolog版本1.3.0。
我对Prolog还比较陌生,我尝试了以下代码:
| ?- append([1],2,R).
R = [1|2]
yes
[1 | 2]
的含义。我试图搜索相关信息,但非常艰难,没有找到任何内容。我猜这类似于Lisp中由(cons 1 2)
生成的(1 . 2)
。能否有人解释或提供相关说明?[H|T]
列表符号[H|T]
是通过头和尾定义列表的谓词'.'(H,T)
的语法糖。例如,列表[1,2,3]
也可以写成'.'(1,'.'(2,'.'(3,[])))。
(在Prolog提示符下尝试执行X = '.'(1,'.'(2,'.'(3,[]))).
)X
是列表[X|T]
的car
,T
是列表[X|T]
的cdr
。
append/3
通常与列表参数一起使用,所以要将一个称为atom
的原子附加到列表L
并使结果为R
,可以这样做:append(L, [atom], R).
append([1], [2], R).
产出:R = [1,2]
。
在使用append/3
为rev/2
定义实现时,Clocksin&Mellish的《Prolog编程》,第五版,在p.157中指出:
按照惯例,列表的尾部始终是一个列表。
如果给定一个列表L
,可以通过与[H|T]
形式相一致来检索头(car)和尾(cdr):
L = [H|T]
例如:
| ?- L = [1,2,3,4], L = [H|T].
H = 1
L = [1,2,3,4]
T = [2,3,4]
yes
| ?-
| ?- L = [1,2,3,4], L = [A,B,C|T].
A = 1
B = 2
C = 3
L = [1,2,3,4]
T = [4]
yes
如果您尝试执行过多的操作,它将失败:
| ?- L = [1,2,3], L = [A,B,C,D|T].
no
[H|T]
形式在列表处理谓词中非常方便,特别是递归的情况下。
my_list_process_predicate([H|T], [Result|Results]) :-
% Do some stuff here, determing "Result" from "H" perhaps
my_list_processing_predicate(T, Results). % Get the rest of the results
% from the rest of the list
[H|T]
的形式字面上写出列表 [1,2,3]
,那么有以下等价表达方式:[1,2,3|[]]
[1,2|[3]]
[1,2|[3|[]]]
[1|[2,3]]
[1|[2,3|[]]]
[1|[2|[3]]]
[1|[2|[3|[]]]]
当T
是原子时,列表形式为[H|T]
如果有一个列表[X|T]
,表示X
是列表的头部,T
是尾部(通常也是一个列表)。虽然 Prolog 可以构造这样的列表,其中 T
是原子,但它似乎不常用,至少不像 Lisp 中那样。但是,是的,[1|2]
确实像 Lisp 中的 (1 . 2)
。Lisp 有一些内置函数,可以操作 (a . b)
形式的键值对等列表。Prolog 没有利用我所知道的 [a|b]
结构的任何内置函数。他们可能没有更多的优势,只是使用 [a,b]
。我还搜索了有关 [a|b]
(或 [a1,...,an|b]
)形式的参考文献,并在 Clocksin&Mellish 的第53页找到了一个例子,将 [white|Q]
与 [P|horse]
统一:
…可以使用列表符号创建类似于列表但并不以空列表结尾的结构。其中一个这样的结构,
[white|horse]
,表示具有头部white
和尾部horse
的结构。常量horse
既不是列表也不是空列表,…在将这样的结构用于列表的尾部时应谨慎处理。
有趣的是,大多数其他处理列表的内置 Prolog 谓词实际上会在给定 [a1,...,an|b]
形式时失败。例如,在 GNU Prolog 中:
| ?- X = [1,2,3|4], length(X, L).
no
| ?- X = [1,2,3,4], length(X, L).
L = 4
X = [1,2,3,4]
yes
SWI Prolog 抛出异常:
?- X = [1,2,3|4], length(X, L).
ERROR: length/2: Type error: `list' expected, found `4'
maplist
可以处理这样一个列表的所有元素,但会忽略尾部原子。只要第一个列表没有原子作为其尾部,append/3
就可以工作。X=[1|2]
),而内置的 append/3
处理它(可能是由于其简单的设计)。它可以用作有效的数据形式,[a1,...,an|b]
,并且可以与类似的形式统一。但大多数内置程序似乎没有正确地处理它。它也不作为通用的二元函数(尝试统一 X=3|4
会失败)。[a1,...,an|b]
(其中 b
是一个原子)是一个有效的 Prolog 数据结构,但它作为列表的行为必须小心处理,因为大多数谓词假定列表的尾部是一个列表,并且“最终”尾部是空列表 []
。因此,如果需要,它可以被合法地使用,但要小心(如 C&M 所指出的)。