我是Scheme的新手,这里我用点列表遇到了麻烦,这是一个例子:
(define (f x . y) (cons x y))
当我输入:(f 1 2 3)
时,结果为'(1 2 3)
。是的,它返回一个列表,此时
x => 1
和y => '(2 3)
。
我的问题是当f
采用不固定长度的args时,解释器怎么能知道这个?
答案 0 :(得分:4)
我是Scheme的新手,在这里我遇到了点缀列表的问题,这里是一个 例如:
(define (f x . y) (cons x y))
当我输入:(f 1 2 3)时,结果是'(1 2 3)。是的,它返回一个 列表,此时
x => 1 and y => '(2 3).
我的问题是,当f采取时,解释器怎么能知道这一点 不确定的args长度?
说f
采用不固定或任意数量的论点是不对的。它没有。它需要至少一个参数。如果您尝试拨打(f)
,则会收到错误消息。理解这里发生的事情的关键可能是理解Lisps中的虚线对符号。它包含在另一个Stack Overflow问题Dot notation in scheme中,但简短版本是每个列表都是由对构建的。一对可以写为(car . cdr)
。例如,(cons 1 2) => (1 . 2)
。像(1 2 3)
这样的列表实际上是一对cdr
是另一对cdr
是另一对,等等:(1 . (2 . (3 . ())))
。因为阅读起来很尴尬,我们通常会在写一对配对时删除除最后一个点之外的所有点,如果最后一个cdr
是()
,我们会省略点和{{1也是。所以
()
Noete虽然默认打印机不会以这种方式打印,但列表(1 . (2 . (3 . 4)) === (1 2 3 . 4)
(1 . (2 . (3 . ())) === (1 2 3)
也可以通过以下方式编写:
(1 2 3 4)
虽然它不会以这种方式打印,但你可以写出来并且系统会理解它。例如,
(1 . (2 3 4)) === (1 2 . (3 4)) === (1 2 3 . (4))
这可能是理解lambda-list表示法的关键。当我们为函数编写lambda列表时,它表示一个函数,并且该lambda列表会根据参数进行解构。因此,如果我们有以下lambda列表并使用它们来构造参数列表> '(1 2 . (3 4))
(1 2 3 4)
,我们得到结果绑定:
(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
最后一个有点整洁,因为这意味着如果它不是该语言的一部分,你可以这样做:
((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))
答案 1 :(得分:2)
在方案中,形式参数之前的dot
表示参数的值在里面
该过程将是一个列表,包含所有剩余参数。因此,当您在帖子中正确显示时,该过程中的y
是一个列表'(2 3)
。在f
中,x被视为普通参数。
(define (f x . y)
(display "y: ")
(display y) (newline))
(f 1 2 'this 'is 'a 'list)
y: (2 this is a list)
以下是Guile参考手册对此的评价:
(variable1 ... variablen.variablen + 1)
如果以空格分隔的时间段位于最后一个变量之前,则该过程采用n或>更多变量,其中n是句点之前的正式参数的数量。在此期间之前必须至少有一个参数。前n个实际参数将存储到新分配的前n个正式参数的位置和序列中 剩余的实际参数将转换为列表并存储到最后一个正式参数的位置。如果确实存在n个实际参数,则空列表为 存储到最后一个正式参数的位置。
答案 2 :(得分:0)
解释器知道f
有一个名为x
的参数,后跟参数列表y
。因此,当遇到f
的调用时,它会将第一个参数放入x
,将其余参数放入y
。
答案 3 :(得分:0)
(f x . y)
语法意味着define
的第一个参数是"不正确的" list(相当于你从(cons 'f (cons 'x 'y))
而不是(cons 'f (cons 'x (cons 'y nil)))
获得的内容。所以当调用函数时,每个东西都依次绑定。首先,x绑定到1,然后其余的列表中的列表被绑定到arument列表的尾部。因此,此时,是一个符号,y被绑定到(2 3)。