方案中的lambda函数和内存

mor*_*org 3 lisp lambda scheme racket

如果我写的话,我不明白为什么

(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)))
Run Code Online (Sandbox Code Playgroud)

然后调用(il2)2次我打印:1然后2(这是我想要的结果)但是如果我不放(lambda()并应用(il2)2次我获得然后1换句话说为什么关联如果函数lambda()的一部分使它保留我们之前应用函数时所做的内存?

Ósc*_*pez 5

这就是发生的事情.首先,当你写这篇文章时,你必须明白:

(define (iter-list lst)
  (let ((cur lst))
    (lambda ()
      ...)))
Run Code Online (Sandbox Code Playgroud)

它被转换为这种等效形式:

(define iter-list
  (lambda (lst)
    (let ((cur lst))
      (lambda ()
        ...))))
Run Code Online (Sandbox Code Playgroud)

所以你看,另一个lambda在那里.现在,最外层 lambda将定义一个局部变量,cur它将"记住"列表的值,然后返回最里面的 lambda作为结果,最里面的lambda"捕获","封闭" cur上面定义的变量在闭包内.换句话说:iter-list是一个函数,它返回一个函数作为结果,但在这之前它将"记住"该cur值.这就是你这样称呼它的原因:

(define il2 (iter-list '(1 2))) ; iter-list returns a function
(il2)                           ; here we're calling the returned function
Run Code Online (Sandbox Code Playgroud)

将其与此处的情况进行比较:

(define (iter-list lst)
  (let ((cur lst))
    ...))
Run Code Online (Sandbox Code Playgroud)

以上相当于:

(define iter-list
  (lambda (lst)
    (let ((cur lst))
      ...)))
Run Code Online (Sandbox Code Playgroud)

在上面,iter-list只是一个函数,它将在调用时返回一个值(不是像以前那样的另一个函数!),这个函数不会"记住"任何东西并在被调用后立即返回.总结一下:第一个示例创建一个闭包并记住值,因为它返回一个函数,而第二个示例只返回一个数字,并像这样被调用:

(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
Run Code Online (Sandbox Code Playgroud)