lambda函数与scheme中的内存

lambda函数与scheme中的内存,scheme,lisp,racket,lambda,Scheme,Lisp,Racket,Lambda,我不明白为什么我要写信 (define (iter-list lst) (let ((cur lst)) (lambda () (if (null? cur) '<<end>> (let ((v (car cur))) (set! cur (cdr cur)) v))))) (define il2 (iter-list '(1 2))) (定义(iter清单

我不明白为什么我要写信

(define (iter-list lst)
  (let ((cur lst))
    (lambda ()
      (if (null? cur)
          '<<end>>
          (let ((v (car cur)))
            (set! cur (cdr cur))
            v)))))

(define il2 (iter-list '(1 2)))
(定义(iter清单lst)
(让((当前和当前)
(lambda()
(如果(空?cur)
'
(让((v(car cur)))
(设置!cur(cdr cur))
v) )))
(定义il2(国际热核实验堆清单(1-2)))
打电话(il2)2次,我已经打印了:1次,然后2次 (这就是我想要的结果) 但是如果我不把(lambda()和应用(il2)2次,我得到1
换句话说,为什么将if部分与函数lambda()关联会使它保留我们以前应用函数时所做的操作的内存?

当您将if包装在lambda中(并像那样返回它)时,cur let(在if的作用域内)会附加到lambda。这称为闭包


现在,如果你读一点关于闭包的内容,你会发现它们可以用来保持状态(就像你在这里做的那样)。这对于创建不断递增的计数器或对象系统非常有用(闭包可以用作一种由内而外的对象).

这就是正在发生的事情。首先,当你写这篇文章时,重要的是你要明白:

(define (iter-list lst)
  (let ((cur lst))
    (lambda ()
      ...)))
它被转换为这种等价形式:

(define iter-list
  (lambda (lst)
    (let ((cur lst))
      (lambda ()
        ...))))
您可以看到,另一个
lambda
首先存在。现在,最外层的
lambda
将定义一个局部变量,
cur
,它将“记住”列表的值,然后返回最内层的lambda作为结果,最内层的
lambda
将“捕获”、“封闭”上面在a中定义的
cur
变量。换句话说:
iter list
是一个返回函数结果的函数,但在执行此操作之前,它将“记住”cur值。这就是为什么您这样称呼它:

(define il2 (iter-list '(1 2))) ; iter-list returns a function
(il2)                           ; here we're calling the returned function
(define il2 (iter-list '(1 2))) ; iter-list returns a number
(il2)                           ; this won't work: il2 is just a number!
il2                             ; this works, and returns 1
将其与此处发生的情况进行比较:

(define (iter-list lst)
  (let ((cur lst))
    ...))
上述内容相当于:

(define iter-list
  (lambda (lst)
    (let ((cur lst))
      ...)))
在上面的例子中,
iter list
只是一个函数,调用时会返回一个值(不是像以前那样的另一个函数!),这个函数不“记住”总之,第一个示例创建一个闭包并记住值,因为它返回一个函数,而第二个示例只返回一个数字,并按如下方式调用:

(define il2 (iter-list '(1 2))) ; iter-list returns a function
(il2)                           ; here we're calling the returned function
(define il2 (iter-list '(1 2))) ; iter-list returns a number
(il2)                           ; this won't work: il2 is just a number!
il2                             ; this works, and returns 1

请注意,在原始代码中,您将
lst
重命名为
cur
。您实际上不需要这样做。内部lambda(即将关闭的)可以直接捕获
lst
参数。因此,这将产生相同的结果:

(define (iter-list lst)
  (lambda ()
     ...))   ; your code, replace 'cur' with 'lst'
以下是捕获变量的其他闭包生成函数的一些示例:

(define (always n)
  (lambda () n))

(define (n-adder n)
  (lambda (m) (+ n m)))

(define (count-from n)
  (lambda ()
    (let ((result n))
      (set! n (+ n 1))
      result)))