评估为 lambda 的函数不能用于在范围内定义新函数
Function evaluating to lambda cannot be used to define new function within scope
在 scheme 中,您可以定义 return lambda 表达式的函数,并使用它们来定义新函数。比如你可以这样写代码
(define (pow-iter base exp r)
(if (= exp 1)
r
(pow-iter base (- exp 1) (* base r))))
(define (pow exp)
(lambda (base)
(pow-iter base exp base)))
(define cubic (pow 3))
(cubic 2)
我们这里有一个函数 pow
,它将指数作为参数并求值为一个 lambda 函数,该函数求值为给定底数的 n 次方。
但是,如果我们把它放在这样的范围内:
(define (do-cubic x)
(define (pow-iter base exp r)
(if (= exp 1)
r
(pow-iter base (- exp 1) (* base r))))
(define (pow exp)
(lambda (base)
(pow-iter base exp base)))
(define cubic (pow 3))
(cubic x))
(do-cubic 2)
我收到一个错误
pow: undefined; cannot use before initialization
为什么会出现这个错误,有什么办法可以在不改变程序逻辑的情况下解决这个问题吗?
这个程序引发了同样的错误:
#lang r5rs
(let ()
(define (foo x) (lambda (y) (+ 42 x)))
(define bar (foo 1))
(bar 2))
Output:
foo: undefined;
cannot use before initialization
出现错误的原因是 "internal definitions" 被重写为 letrec
表达式,所有绑定在计算初始值时都有效,因此允许相互递归定义。
(letrec ((foo (lambda (x) (lambda (y) (+ 42 x))))
(bar (foo 1)))
(bar 2))
在 R5RS 中,初始化表达式按 未指定 顺序求值。这意味着在上面的第一个代码片段中,(define bar (foo 1))
可以在 (define (foo x) ...)
之前计算。换句话说,在初始化 foo
之前需要 foo
的值。
在 Racket (#lang racket
) 中,内部定义使用 letrec*
-语义(即初始化表达式按照它们在代码中出现的顺序求值。因此程序运行没有错误。
另请注意,#lang racket
中的 letrec
对应于 letrec*
在 "R5RS" 中的作用。
有关 letrec
与 letrec*
的更多信息,请参阅 http://www.cs.indiana.edu/~dyb/pubs/letrec-reloaded.pdf
的介绍
在 scheme 中,您可以定义 return lambda 表达式的函数,并使用它们来定义新函数。比如你可以这样写代码
(define (pow-iter base exp r)
(if (= exp 1)
r
(pow-iter base (- exp 1) (* base r))))
(define (pow exp)
(lambda (base)
(pow-iter base exp base)))
(define cubic (pow 3))
(cubic 2)
我们这里有一个函数 pow
,它将指数作为参数并求值为一个 lambda 函数,该函数求值为给定底数的 n 次方。
但是,如果我们把它放在这样的范围内:
(define (do-cubic x)
(define (pow-iter base exp r)
(if (= exp 1)
r
(pow-iter base (- exp 1) (* base r))))
(define (pow exp)
(lambda (base)
(pow-iter base exp base)))
(define cubic (pow 3))
(cubic x))
(do-cubic 2)
我收到一个错误
pow: undefined; cannot use before initialization
为什么会出现这个错误,有什么办法可以在不改变程序逻辑的情况下解决这个问题吗?
这个程序引发了同样的错误:
#lang r5rs
(let ()
(define (foo x) (lambda (y) (+ 42 x)))
(define bar (foo 1))
(bar 2))
Output:
foo: undefined;
cannot use before initialization
出现错误的原因是 "internal definitions" 被重写为 letrec
表达式,所有绑定在计算初始值时都有效,因此允许相互递归定义。
(letrec ((foo (lambda (x) (lambda (y) (+ 42 x))))
(bar (foo 1)))
(bar 2))
在 R5RS 中,初始化表达式按 未指定 顺序求值。这意味着在上面的第一个代码片段中,(define bar (foo 1))
可以在 (define (foo x) ...)
之前计算。换句话说,在初始化 foo
之前需要 foo
的值。
在 Racket (#lang racket
) 中,内部定义使用 letrec*
-语义(即初始化表达式按照它们在代码中出现的顺序求值。因此程序运行没有错误。
另请注意,#lang racket
中的 letrec
对应于 letrec*
在 "R5RS" 中的作用。
有关 letrec
与 letrec*
的更多信息,请参阅 http://www.cs.indiana.edu/~dyb/pubs/letrec-reloaded.pdf