在Racket中,可以在另一个过程中定义过程和常量,例如:
(define (a a-list)
(define something 10)
(display a-list)
(cond
[(empty? a-list) (display "done")]
[else
(display a-list) (newline)
(a (rest a-list))]))
打印列表然后取走第一个元素,然后再次打印列表,依此类推,直到列表为空。
在示例过程中,无论出于何种原因,值something
都被定义为10
。当程序递归时,Racket是否再次定义该值,或者它是否足够智能注意到该定义不会改变?
它也可能在先前调用的过程的堆栈空间上,如果这没有被优化,并且每个递归步骤会消耗更多的内存,具体取决于something
定义的内容。例如,让我们在列表中说出一百万个数字,但从不改变数字。显然,如果该定义中的内容依赖于作为参数给出的列表,则不能简单地进行优化。
如果没有优化,最好不要在递归函数中包含太多define
个形式,或者只消耗少量空间的形式?将它们放在程序之外会使它们可以从其他程序访问,即使只有一个程序使用它们。
答案 0 :(得分:1)
每次调用过程时,define
表达式都会被评估。考虑这个例子:
(define (test1)
(define x (begin (display "Hello from test1 ") 10))
x)
(test1)
=> Hello from test1 10
(test1)
=> Hello from test1 10
(test1)
=> Hello from test1 10
如果您希望过程中的值只被评估一次(当创建过程本身时),您可以将它放在过程之外的范围内,它仍然可以访问,因为{{1}在其词法环境中定义closure:
lambda