29

我正在学习计划。我知道如何同时使用 lambda 和 let 表达式。

但是,我正在努力弄清楚使用 lambda 的意义何在。你不能用 let 做所有你可以用 lambda 做的事情吗?

看一个 lambda 表达式比 let 更好的选择的例子会特别有帮助。

另一件事 - 是否也存在 let 比 lambda 更有用的情况?如果是这样,这样的例子也很好。

编辑:我也对对比定义和 lambda 感兴趣,因为它们似乎执行类似的任务。


更新:

感谢大家的帮助。阅读您的答案后,我对 lambda/let/define 进行了更多研究,现在更好地理解了它。

我遇到了一个很酷的 lambda 用法的一个很好的例子——从过程中返回匿名函数。例如,operateTwice下面的过程返回一个匿名函数,该函数基于传入过程的参数:

(define operateTwice
  (lambda (op1 op2)
    (lambda (x y)
      (op2 (op1 x y) y))))

((operateTwice * +) 2 3) ;equivalent to: (+ (* 2 3) 3), or in standard notation 2*3+3

输出:

9
4

6 回答 6

48

Alet是一个lambda

例如

(let ((x 1))
  body)

可以翻译成

((lambda (x) body) 1)

此外,在 Scheme 中,所有的控制和环境结构都可以用 lambda 表达式和 lambda 的应用来表示。

因此,lambda严格来说,它比 Scheme 中的许多有趣的结构更强大,let并构成了它的基础。

关于defineand lambda,顶层define添加了对顶层环境的绑定。

当你写

(define (f x)
  body)

你真的在说

(define f (lambda (x) body))

嵌套定义被翻译成letrec,也可以使用 lambdas 重写。

因此,同样,许多 Scheme 构造都可以使用 翻译成某种东西lambda,因此你理解lambda好真的很值得。

于 2010-05-31T11:15:19.967 回答
16

如果您lambda想创建一个函数以将其用作另一个函数的参数(例如map),则使用该函数,但您实际上并不想命名该函数。

例如,如果您想将 42 添加到列表中的每个数字,您可以执行以下操作:

(define (add42 x) (+ x 42))
(map add42 (list 1 2 3 4))

但是,如果您不想为只使用一次的函数命名,您可以这样做:

(map (lambda (x) (+ x 42)) (list 1 2 3 4))
于 2010-05-31T11:14:43.433 回答
5

Let 实际上只是 Lambda 表达式的简写。以下两个表达式是等价的:

(let ((alpha 7)) (* 5 alpha))

((lambda (alpha) (* 5 alpha)) 7)

Lambda 遵循语言的哲学,即一切都应该看起来像一个数学函数。但在实践中,如果变量太多,让我们更容易弄清楚发生了什么。想象一下在 Lambda 块之后定义了其值的 10 个变量,并且您尝试将每个变量与变量名称进行匹配,让变量的值放在它们的名称旁边,这对程序员来说很方便,但不太符合函数式编程哲学。

Lambda 可用于从高阶函数返回函数,但 let 不能这样做。例如:

(define (plus-list x)
  (cond ((number? x)
         (lambda (y) (+ (sum-n x) y)))
        ((list? x)
         (lambda (y) (+ (sum-list x) y)))
        (else (lambda (x) x))
        ))

> ((plus-list 3) 4)
10
> ((plus-list '(1 3 5)) 5)
14
> ((plus-list 'a) 5)
5

Lambda 还可以用于将函数传递给函数:

>(map (lambda (x) (+ 1 x)) '(-1 2 -3))
(0 3 -2)
于 2011-12-17T17:06:19.643 回答
3

lambda 创建新的匿名函数,当然每次使用它们时都会对其进行评估。

let 为值创建临时名称,并设置一次以在 let 表单定义的范围内使用。

他们真的是非常不同的野兽。

一些例子 :

(λ (x) (* 5 x))

(让 ([x 2]) (* 5 x)) 10 (让 ([f (lambda (x) (* 5 x))]) (f 2)) 10

第一种形式创建一个乘以 5 的函数

第二种形式将 2 分配给 x 并将其乘以 5 得到 10

第三,我们使用 1 的函数(乘以 5)并使用 2 作为参数调用它,结果也为 10

于 2010-05-31T11:12:00.057 回答
3

在 Scheme 中,过程(或函数)是第一类对象,如列表、数字或字符串。要创建一个列表文字,您可以使用名为 的原语list

> (define marks (list 33 40 56))
> marks
> (33 40 56)

就像这样,要创建一个过程,您可以使用lambda原语(或特殊形式):

> (define add-marks (lambda (m) (apply + m)))
> (add-marks marks)
> 129

由于过程是抽象的主要形式,Scheme 提供了一种快捷方式define使绑定新过程变得容易:

> (define (add-marks m) (apply + m))

除此之外,过程就像所有其他第一类对象一样。它们可以作为参数传递给其他过程,并且一个过程可以评估以产生(或返回)另一个过程。

于 2010-05-31T11:35:40.360 回答
1

你可以这样想……你创建了一个使用另一个函数的函数,但你想让事情变得更加模块化,所以你所做的就是调用第二个函数作为第一个函数的参数,这样你就有可能每当您觉得需要其他功能时更改第二个...希望这是有道理的

于 2010-05-31T11:24:49.620 回答