如何在此方案片段中进行闭包?

时间:2016-10-21 19:29:53

标签: scheme closures

我在解密这段代码时遇到了一些麻烦。

(define (stream n f)
    (define (next m)
        (cons m (lambda () (next (f m)))))
    (next n))
(define even (stream 0 (lambda (n) (+ n 2))))

我知道'even'被定义为使用'stream'函数的变量,该函数包含参数0和'(lambda(n)(+ n 2))'。在'stream'中,不会'(下n)'无限期地用n + 2的汽车创建cons节点?然而,当我返回'even'时,它是(0。#< Closure>)的缺点。有人可以这么好解释为什么会这样吗?谢谢!

1 个答案:

答案 0 :(得分:0)

每次评估(lambda ...)时,它都会成为一个闭包。这意味着f是免费的,可用于两个过程next以及它创建的匿名过程。 mnext中的绑定变量,也被捕获为匿名过程中的自由变量。如果语言是动态绑定的,那么如果在cdr中调用结果过程,则它们都不会存在,因为绑定将不再存在,但由于我们有闭包,因此即使在创建它们的过程结束后,该变量也存在。

stream过程返回的对引用了(lambda (n) (+ n 2))通过名称f进行评估时创建的闭包,即使调用已完成。因此,如果您这样做:

((cdr even))            ; ==> 
(#<closure>)            ; ==> 
(cons 2 #<new-closure>) ; ==> Here

重要的是要知道next的评估与一个新的闭包成为一对,这个闭包有一个新的自由变量m,这次是2。每次调用cdr时,它都会创建一个带有新闭包的新对。如果每次迭代都不会有不同的结果,那么它是相同的。

它自己的lambda并没有在它的身体中运行代码。因此,您只需获得一步和结果(cons 2 #<new-closure>),而不是无限递归。您需要再次调用此cdr ni命令才能再获得一步。等等,如果我这样做:

(define (test a)
  (define (helper b)
    (+ a b))

  helper) ; return the helper that has a as closure variable

由于我们实际上没有使用该名称,因此可能只有匿名lambda而不是define +结果变量。无论如何,你会得到一些可以部分应用的东西:

((test 5) 2)  ; ==> 7

(define ten-adder (test 10))
(ten-adder 2) ; ==> 12
(ten-adder 5) ; ==> 15