嵌套let和lambda在Scheme中的排序

发布于 2024-10-30 13:25:12 字数 350 浏览 0 评论 0原文

Scheme 中的两个函数之间有什么区别,一个是这样定义的,

(define doSomething
    (lambda (x)
          (let (f (100))
               (f x))))

另一个是这样定义的?

(define doSomething
          (let (f (100))
            (lambda (x) 
               (f x)))) 

换句话说,如果 lambda 位于 let 或者之后?

What is the difference between two functions in Scheme, one defined like this—

(define doSomething
    (lambda (x)
          (let (f (100))
               (f x))))

and the other like this?—

(define doSomething
          (let (f (100))
            (lambda (x) 
               (f x)))) 

In other words, what does it matter if the lambda is before the let or after it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一身仙ぐ女味 2024-11-06 13:25:12

你的代码不会运行。 :-)

我会假设你的意思是这些:

(lambda (x)
  (let ((f 100))
    (+ f x)))

并且

(let ((f 100))
  (lambda (x)
    (+ f x)))

在这两种情况下,你都会返回传入的参数加上 100。

然而,主要的区别(忽略关于 let 的技术细节只是lambda 的语法糖)是在第二个版本中,f 是一个自由变量。假设我们这样做:

(let ((f 100))
  (list (lambda (x)
          (+ f x))
        (lambda (x)
          (set! f x))))

这会返回一个包含两个 lambda 的列表:第一个与之前的一样,第二个允许您更改 f 的值。两个 lambda 访问相同的 f,因此运行 setter影响稍后对第一个 lambda 的调用。

Your code won't run. :-)

I will presume that you mean these instead:

(lambda (x)
  (let ((f 100))
    (+ f x)))

and

(let ((f 100))
  (lambda (x)
    (+ f x)))

In both cases, you'll get back the passed-in argument plus 100.

However, the main difference (ignoring technicalities about how let is just syntactic sugar over lambda) is that in the second version, f is a free variable. Say we do this:

(let ((f 100))
  (list (lambda (x)
          (+ f x))
        (lambda (x)
          (set! f x))))

This returns a list with two lambdas: the first of which is just like the ones previously, and the second one which allows you to change the value of f. Both lambdas access the same f, so running the setter will affect later calls to the first lambda.

心病无药医 2024-11-06 13:25:12

正如克里斯指出的那样,代码不会运行。因此,我将使用一个新示例来解释 let over lambda 习惯用法。

当您用 let 包围 lambda 形式时,如下所示:

 (let ((x 0))
   (lambda ()
     ; body
     ))

lambda 主体内的代码能够访问(包括修改)< code>x,即使在 let 结束并返回新函数之后也是如此。这是创建“闭包”的一个示例,一开始很难理解。

本质上,这意味着您可以创建具有某种“内部状态”的函数。您可以使用它来做一些事情,例如制作“累加器生成器”或制作计算它们被调用次数的函数,甚至模拟“对象”(内部状态+方法)。下面是一些人为的示例:

一个 double 函数,用于计算它被调用的次数:

(define double
  (let ((count 0)) ; closed over variable
    (lambda (x)
      (if (eq? x 'count)
          count
          (begin 
            (set! count (+ count 1)) ; incr the count variable introduced by let
            (+ x x))))))

> (double 1)
2
> (double 1)
2
> (double 1)
2
> (double 'count) ; ask the double function how many times it's been called
3
> 

这个示例确实是 Paul Graham 提供的 (http://www.paulgraham.com/accgen.html)

(define make-accumulator
  (lambda ()
    (let ((x 0))
      (lambda (i)
        (set! x (+ x i)) ; incr x by i
        x))))

> (define acc (make-accumulator))
> (acc 1)
1
> (acc 1)
2
> (acc 1)
3
> (acc 1)
4
> 

每次<使用 1 调用 code>acc 时,它返回的值不同。

有关“对象”的示例,请搜索“对象和闭包”或阅读 SICP 的相关部分:http://mitpress.mit.edu/sicp/full-text/book/book-ZH-20.html#%_sec_3.1

As Chris points out, the code isn't going to run. So I'm going to use a new example to explain the let over lambda idiom.

When you surround a lambda form with a let like this:

 (let ((x 0))
   (lambda ()
     ; body
     ))

The code inside the body of the lambda is able to access (including modify) x, even after the let ends and returns the new function. This is one example of creating a "closure" which is tricky to understand at first.

Essentially this means that you can create a function with a kind of "internal state". You can use this to do things like make "accumulator generators" or make functions that count the number of times they've been called, or even simulate "objects" (internal state + methods). Here's some contrived examples:

A double function that counts the number of times it's been called:

(define double
  (let ((count 0)) ; closed over variable
    (lambda (x)
      (if (eq? x 'count)
          count
          (begin 
            (set! count (+ count 1)) ; incr the count variable introduced by let
            (+ x x))))))

> (double 1)
2
> (double 1)
2
> (double 1)
2
> (double 'count) ; ask the double function how many times it's been called
3
> 

This example is really courtesy Paul Graham (http://www.paulgraham.com/accgen.html)

(define make-accumulator
  (lambda ()
    (let ((x 0))
      (lambda (i)
        (set! x (+ x i)) ; incr x by i
        x))))

> (define acc (make-accumulator))
> (acc 1)
1
> (acc 1)
2
> (acc 1)
3
> (acc 1)
4
> 

Each time acc is called with 1 the value it returns is different.

For examples of "objects" search for "objects and closures" or just read the relevant sections of SICP: http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-20.html#%_sec_3.1

冰葑 2024-11-06 13:25:12

另外两张(优秀的)海报围绕但没有明确提及的一点是:在没有 set! 的情况下,两者之间没有区别,因此可能没有理由使用您的第二种形式。

One point that the other two (excellent) posters circle around but don't explicitly mention is this: in the absence of set!, there's no difference between the two, and therefore probably no reason to use your second form.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文