我在解密这段代码时遇到了一些麻烦。
(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>)的缺点。有人可以这么好解释为什么会这样吗?谢谢!
答案 0 :(得分:0)
每次评估(lambda ...)
时,它都会成为一个闭包。这意味着f
是免费的,可用于两个过程next
以及它创建的匿名过程。 m
是next
中的绑定变量,也被捕获为匿名过程中的自由变量。如果语言是动态绑定的,那么如果在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