参数的不同处理:lambdas与Scheme中的定义

时间:2017-05-20 18:28:24

标签: lambda scheme r5rs chicken-scheme

我有两个结构,我希望它们在功能上是相同的,但它们不是,我无法弄清楚原因。

使用define

(define (x2 . b)
  (display b)
  (newline))

(x2 3 4 5) => (3 4 5)

使用lambda

((lambda (. b) 
   (display b) 
   (newline)) 
   3 4 5) => Error: invalid use of `.'

R5RS中,definitionslambdas都接受。为了使它们的行为相同,我可以像这样构造lambda:

((lambda b
   (display b)
   (newline))
   3 4 5) => (3 4 5)

这是报告的形式参数定义中列出的有效结构之一。但是如果我尝试将它与define一起使用,则会导致参数编号不匹配错误。

(define (x2 b)
  (display b)
  (newline))

(x2 3 4 5) => Error: bad argument count

我认为(define (x y) y)只是(define x (lambda (y) y))的语法糖。似乎只有在大多数情况下才是这样。任何人都可以解释不同行为的理由吗?

2 个答案:

答案 0 :(得分:2)

这些表达式表示具有固定arity的匿名过程:

(define (x y) y)
(define (x y z) z)

他们相当于:

(define x (lambda (y) y))
(define x (lambda (y z) z))

但是采用这个过程,使用可变数量的参数:

(define (x . y) y)

它只相当于:

(define x (lambda y y))

继续这些示例,此过程只有一个必需参数,其他参数是可变参数:

(define (x y . z) z)

它的等效形式是:

(define x (lambda (y . z) z))

因此,隐式/显式使用lambda来定义具有可变数量参数的过程的语法略有不同,这就是在这种情况下使用点符号。

此外,'( . b)之类的语法无效,因为在这种情况下,点表示法表示不正确列表,即最后一个元素不是空列表的列表。另一方面,这是有效的:'(a . b)。这解释了为什么表达式(lambda ( . x) x)无效;并且假设(lambda (x) x)表示具有单个强制参数的匿名过程,我们留下(lambda x x)来表示只有可变数量的参数且没有强制参数的匿名过程。

据我所知,事情是这样的唯一理由是按照惯例,并且可能因为它更容易解析。

答案 1 :(得分:2)

(. arguments)语法无效。点表示一对中两个部分之间的分隔,此处没有第一部分。我确实在这里看到你的意思是arguments,它根本不应该是一个列表。

看起来像这样的定义:

(define (name . arguments)
  ..)

与:

相同
(define name 
  (lambda arguments
    ..))

一个带有一个参数的例子:

(define (name arg1 . arguments)
  ..)

变为

(define name 
  (lambda (arg1 . arguments)
    ..))

原因很简单:(cdr '(name . arguments)) ; ==> arguments(cdr '(name arg1 . arguments)) ; ==> '(arg1 . arguments)