ked*_*bug 3 lisp scheme functional-programming
我是Scheme的新手,在这里我遇到了虚线列表的问题,这是一个例子:
(define (f x . y) (cons x y))
当我输入时: (f 1 2 3)结果是'(1 2 3)。是的,它返回一个列表,此时
x => 1和y => '(2 3)。
我的问题是,当f采用不固定长度的 args时,解释器如何知道这一点?
我是Scheme的新手,在这里我遇到了虚线列表的问题,这是一个例子:
Run Code Online (Sandbox Code Playgroud)(define (f x . y) (cons x y))当我输入: (f 1 2 3) 结果是 '(1 2 3)。是的,它返回一个列表,此时
Run Code Online (Sandbox Code Playgroud)x => 1 and y => '(2 3).我的问题是,当 f 取不固定长度的 args 时,解释器怎么会知道这一点?
说它f需要一个不固定或任意数量的参数是不太正确的。它没有。它至少需要一个参数。如果你尝试调用(f),你会得到一个错误。理解这里发生了什么的关键可能是理解 Lisps 中的点对符号。它在另一个 Stack Overflow 问题(方案中的点符号)中有所涉及,但简短的版本是每个列表都是由成对构建的。一对可以写成(car . cdr)。例如,(cons 1 2) => (1 . 2)。一个列表 like(1 2 3)实际上是一对,其cdr另一对cdr是另一对,等等: (1 . (2 . (3 . ())))。因为读起来很尴尬,所以当我们写成对链时,我们通常会删除最后一个点以外的所有点,如果最后一个点cdr是(),我们也省略了点和()。所以
(1 . (2 . (3 . 4)) === (1 2 3 . 4)
(1 . (2 . (3 . ())) === (1 2 3)
Run Code Online (Sandbox Code Playgroud)
请注意,虽然默认打印机不会以这种方式打印,但(1 2 3 4)也可以通过以下方式编写列表:
(1 . (2 3 4)) === (1 2 . (3 4)) === (1 2 3 . (4))
Run Code Online (Sandbox Code Playgroud)
虽然它不会那样打印,但您可以编写它,系统会理解它。例如,
> '(1 2 . (3 4))
(1 2 3 4)
Run Code Online (Sandbox Code Playgroud)
这可能是理解 lambda-list 符号的关键。当我们为函数编写 lambda 列表时,它代表一个函数,并且该 lambda 列表会根据参数进行解构。因此,如果我们有以下 lambda 列表并使用它们来解构参数列表(1 2 3),我们将得到结果绑定:
lambda-list x y z
-------------------------------------
(x y z) 1 2 3
(x y . z) 1 2 (3)
(x . y) 1 (2 3) n/a
x (1 2 3) n/a n/a
Run Code Online (Sandbox Code Playgroud)
最后一种情况可能令人惊讶,但您可以测试所有这些实际上是否按预期工作:
((lambda (x y z) (list x y z)) '(1 2 3)) => (1 2 3)
((lambda (x y . z) (list x y z)) '(1 2 3)) => (1 2 (3))
((lambda (x . y) (list x y)) '(1 2 3)) => (1 (2 3))
((lambda x (list x)) '(1 2 3)) => ((1 2 3))
Run Code Online (Sandbox Code Playgroud)
最后一个有点简洁,因为这意味着如果它不是语言的一部分,你可以这样做:
(define (list . elements) elements)
Run Code Online (Sandbox Code Playgroud)