问题描述
我对 prolog 很陌生,我尝试了以下操作:
I'm quite new to prolog, and I tried the following:
| ?- append([1],2,R).
R = [1|2]
yes
我不知道符号是什么[1 |2]
的意思.试图搜索这个很痛苦,我找不到任何东西.我想这类似于 (cons 1 2)
导致的 lisp (1 . 2)
.有人可以解释/参考有关此的解释吗?
I have no idea what the notation [1 | 2]
means. Trying to search this was painful, and I couldn't find any thing. I guess this is something like the lisp (1 . 2)
resulted from (cons 1 2)
. Can someone explain/reference to explanations about this?
如果这对任何人都很重要,我使用的是 GNU-prolog 1.3.0 版
If it matters to anyone, I'm using GNU-prolog version 1.3.0
推荐答案
[H|T]
列表符号[H|T]
是'.'(H,T)
的语法糖,它是通过头和尾定义列表的谓词.例如,列表 [1,2,3]
也可以写成 '.'(1,'.'(2,'.'(3,[]))).
(try, X = '.'(1,'.'(2,'.'(3,[]))).
在序言提示符处).
The list notation [H|T]
is a syntactic sugar for '.'(H,T)
which is the predicate defining the list by head and tail. For example, the list [1,2,3]
could also be written '.'(1,'.'(2,'.'(3,[]))).
(try, X = '.'(1,'.'(2,'.'(3,[]))).
at the prolog prompt).
既然您似乎熟悉 Lisp,那么在这些术语中,X
是列表 [X|T]
和 car
的 car
code>T 是列表[X|T]
的cdr
.
Since you seem familiar with Lisp, then in those terms, X
is the car
of the list [X|T]
and T
is the cdr
of the list [X|T]
.
append/3
通常与列表参数一起使用,因此将原子(称为 atom
)附加到列表 L
并且结果为R
,你会这样做:
append/3
is typically used with list arguments, so to append an atom (called atom
) to a list L
and result being R
, you'd do it like this:
append(L, [atom], R).
或者更具体地说:
append([1], [2], R).
产量:R = [1,2]
.
在使用 append/3
定义 rev/2
的实现时,Clocksin &Mellish,Prolog 中的编程,第五版,第 157 页,在这种情况下:
In using append/3
to define an implementation for rev/2
, Clocksin & Mellish, Programming in Prolog, Fifth Edition, on p.157 state, in that context:
按照惯例,列表的尾部总是一个列表.
如果给你一个列表,L
,你可以通过将它与 [H|T]
统一来检索头(车)和尾(cdr)形式:
If you're given a list, L
, you can retrieve the head (car) and tail (cdr) by unifying it with the [H|T]
form:
L = [H|T]
例如:
| ?- L = [1,2,3,4], L = [H|T].
H = 1
L = [1,2,3,4]
T = [2,3,4]
yes
| ?-
您还可以根据需要制作尽可能多的元素:
You can also pull off as may elements as you wish:
| ?- L = [1,2,3,4], L = [A,B,C|T].
A = 1
B = 2
C = 3
L = [1,2,3,4]
T = [4]
yes
如果你尝试做太多,它就会失败:
It will fail if you try to do too many:
| ?- L = [1,2,3], L = [A,B,C,D|T].
no
[H|T]
形式在列表处理谓词中很方便,尤其是递归谓词:
The [H|T]
form is handy in list processing predicates, particularly recursive ones:
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
如果你要写一个列表,比如 [1,2,3]
字面上的 [H|T]
形式,你会得到以下等价物:
If you were to write a list, say, [1,2,3]
literally in the [H|T]
form, you'd have any of the following equivalents:
[1,2,3|[]]
[1,2|[3]]
[1,2|[3|[]]]
[1|[2,3]]
[1|[2,3|[]]]
[1|[2|[3]]]
[1|[2|[3|[]]]]
当T
是一个原子时的列表形式[H|T]
The list form [H|T]
when T
is an atom
如果你有一个列表[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]
统一的示例:
If you have a list [X|T]
, means X
is the head of the list, and T
is the tail (usually a list itself). Although Prolog lets you construct such a list in which T
is an atom, it doesn't seem commonly used, at least not as it is in Lisp. But, yes, [1|2]
is indeed like (1 . 2)
in Lisp. Lisp has some built-in functions which operate on lists of (a . b)
as key-value pairs, etc. Prolog doesn't have any built-ins that take advantage of the [a|b]
structure that I'm aware of. They may have no more advantage over just using [a,b]
. I also have searched for references to the [a|b]
(or [a1,...,an|b]
) form and found one in Clocksin & Mellish, p.53, in reference to an example unifying [white|Q]
with [P|horse]
:
...可以使用列表符号来创建结构类似于列表,但不以空列表终止.一这样的结构,[white|horse]
,表示具有头部的结构white
和尾巴horse
.常量 horse
既不是列表也不是空列表,和...这样的结构应该小心对待在列表尾部使用时.
有趣的是,当给定 [a1,...,an|b]
形式时,大多数处理列表的其他内置 Prolog 谓词实际上会失败.例如,在 GNU Prolog 中:
The interesting thing is that most of the other built-in Prolog predicates that process a list will actually fail when given the [a1,...,an|b]
form. For example, in 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 抛出异常:
SWI Prolog throws an exception:
?- X = [1,2,3|4], length(X, L).
ERROR: length/2: Type error: `list' expected, found `4'
其他谓词也会出现类似的结果.maplist
将处理此类列表的所有元素,但会忽略尾原子.append/3
只要第一个列表的尾部没有原子就可以工作.
Similar results occur with other predicates. maplist
will work on all of the elements of such a list but will ignore the tail atom. append/3
will work as long as the first list does not have an atom as its tail.
关于原子作为列表尾部的问题是一个很好的问题.似乎 Prolog 允许它(例如,您可以统一 X=[1|2].
),并且 append/3
内置处理它(可能是无意中由于它的简单设计).I 可以用作数据的有效形式,[a1,...,an|b]
并且可以与看起来像它的形式统一.但是大多数内置插件似乎没有有意识地正确处理它.它也没有充当通用的 2 参数函子(尝试统一 X=3|4.
会失败).
The question about atom as tail in a list is a very good one. It seems Prolog allows it (you can unify X=[1|2].
for example), and the append/3
built-in handles it (perhaps inadvertently due to its simple design). I can be used as a valid form for data, [a1,...,an|b]
and can be unified with forms that look like it. But most of the built-ins don't seem to consciously handle it properly. It also isn't acting as a generic 2-argument functor (attempt to unify X=3|4.
would fail).
所以,形式 [a1,...,an|b]
(其中 b
是一个原子)是一个有效的 Prolog 数据结构,但它的行为如下必须小心处理列表,因为大多数谓词假定列表的尾部是列表,而最终"尾部是空列表,[]
.因此,如果需要,它可以合法使用,但要谨慎使用(如 C&M 所示).
So, the form [a1,...,an|b]
(where b
is an atom) is a valid Prolog data structure, but it's behavior as a list must be handled carefully since most predicates assume that the tail of a list is a list, and that the "final" tail is the empty list, []
. So it can be legitimately used if desired, but with caution (as C&M indicate).
这篇关于附加列表和原子的序言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!