在Scheme中,我如何理解"(定义(f x.y)(cons x y))"

时间:2014-06-18 13:09:13

标签: functional-programming scheme lisp

我是Scheme的新手,这里我用点列表遇到了麻烦,这是一个例子:

(define (f x . y) (cons x y))

当我输入:(f 1 2 3)时,结果为'(1 2 3)。是的,它返回一个列表,此时

x => 1y => '(2 3)

我的问题是当f采用不固定长度的args时,解释器怎么能知道这个?

4 个答案:

答案 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)。