球拍中的Lambda解释

时间:2014-09-06 01:51:52

标签: lambda racket

我试图理解在球拍中使用lambda,我仍然不清楚。我知道他们是无名(匿名)功能,但为什么这么好?我需要从其他函数访问我的函数,所以我怎么称呼它们?请解释下面的小程序,为什么使用lambda更好?谢谢。

; why is this better than below???
(define test
  (lambda (x)
    (lambda (y)
      (+ x y))))

(define add27
  (test 27))

; what's wrong with this???
(define (addTest x)
  (+ x 27))

> (add27 2)
29
> (addTest 2)
29

1 个答案:

答案 0 :(得分:13)

在Racket(以及其他函数式编程语言)中lambda非常有用,当你想要将一个内联的一次性函数作为参数传递而不首先定义它时。例如,假设我们想要对数字列表进行平方。我们可以走很长的路,首先定义square函数,然后使用map

(define (square x)
  (* x x))

(map square '(1 2 3 4 5))
=> '(1 4 9 16 25)

...或者我们可以简单地传递lambda,如下所示:

(map (lambda (x) (* x x))
     '(1 2 3 4 5))

=> '(1 4 9 16 25)

正如您所看到的,存在我们不需要来引用函数名称的情况。当然,如果由lambda表示的过程将在几个部分中重用,或者如果它是递归的,那么为它命名是有意义的(因此它不再是匿名的):

(define square
  (lambda (x) (* x x)))

以上内容相当于开头square的第一个定义。事实上,第一个定义只是定义函数的语法糖,但最后所有函数都是lambdas

现在让我们看看你的例子。这里我们以略微不同的方式使用lambda,并举例说明它们有用的原因 - 我们不仅定义了一个函数,还返回了一个函数:

(define test
  (lambda (x)
    (lambda (y)
      (+ x y))))

如果我们这样写它可能会更清楚一点(由于上述原因,它是等效的):

(define (test x)
  (lambda (y)
    (+ x y)))

甚至更短 - 在Racket中我们也可以将此语法用于相同的目的:

(define ((test x) y)
  (+ x y))

这不是一个更好的(或更糟糕的)方式来定义一个函数 - 这是另一回事!我们正在定义一个名为test的过程,它接收参数x并作为结果返回一个新的匿名函数,该函数又将作为参数y接收。现在,在这些方面:

(define add27
  (test 27))

...我们正在调用test x27,它返回匿名函数,我们名称该函数{{1} }。还记得作为参数add27收到的lambda吗?现在y已被命名为lambda - 这是currying的示例。想一想:add27是一个函数,用于生成向给定参数test添加固定值x的函数,这解释了为什么会这样做:

y

另一方面,此函数将始终将(add27 2) => 29 添加到其参数中,无法更改它:

27

你看到了区别吗? (define (addTest x) (+ x 27)) (addTest 2) => 29 允许我们生成添加任意值的新函数,而test始终添加固定值addTest。如果你想添加say 27怎么办?使用100这很简单:

test

但是(define add100 (test 100)) 无法更改,我们需要编写一个新函数:

addTest

我希望这能澄清事情,随时在评论中询问有关我答案的任何其他问题。