Scheme/Racket - 未定义函数;初始化前不能使用

Scheme/Racket - Undefined Function; Cannot use before initialization

目前正在学习 SICP,在第一章快结束时,他们要求您为 pi 编写一个值,其中 pi/4 = (2 * 4 * 4 * 6 * 6 * 8 * ...) / (3 * 3 * 5 * 5 * 7 * 7 *..)

我定义了以下函数:

;Term and Next are both functions, a and b are the range of the product
(define (product term a next b) 
  (if (> a b) 1
      (* (term a) (product term (next a) next b))))

(define (pi-approx n)
  (define (square x) (* x x))

  (define (num-prod ind) (* (* 2 ind) (* 2 (+ ind 1)))) ; calculates the product in the numerator for a certain term
  (define (denom-prod ind) (square (+ (* ind 2 ) 1))) ;Denominator product at index ind

  (define num (product num-prod 1 inc n))
  (define denom (product denom-prod 1 inc n))

  (* 4 (/ num denom))) ;;Resulting value

当我在 DrRacket 中 运行 这段代码时,出现以下错误: num-prod: Undefined; Cannot use before initialization,即使我在使用前几行初始化了 num-prod。

我在语法上做错了什么?

这是该问题的前 Google 个结果之一,所以我想添加更多细节:

在大多数 Scheme 实现中(例如 R5RS),无法保证定义的解析顺序。换句话说,它们不是按顺序解析的。是的,您之前定义了 num-prod 几行,但是 num 完全有可能首先编译,因此出现错误。

在 Racket 中,lambda 被编译为 letrec* 运算符而不是 letrec,这意味着 顺序解析的保证。这就是为什么改变语言有帮助。

因为我目前也在通过 SICP 和 运行 进入同样的错误,我想我会提到我认为是预期的解决方案,因为问题在 [=11= 之前的部分] 和 lambda.

这个错误在第一章脚注28中有简要提及:

Embedded definitions must come first in a procedure body. The management is not responsible for the consequences of running programs that intertwine definition and use.

num-prod 正在另一个定义中使用,因此该程序实际上是将定义和使用交织在一起,即使看起来定义都在主体之前。

可能的解决方案(没有 letlambda)是避免定义 numdenom,将它们替换为 product 表达式,或者将 num 定义为带参数的函数,并将 num-prod 作为函数体中的参数:

(define (num terms) (product terms 1 inc n)) 
(define (denom terms) (product terms 1 inc n)) 
(* 4 (/ (num num-prod) (denom denom-prod)))