【问题标题】:Scheme/Racket - Undefined Function; Cannot use before initialization方案/球拍 - 未定义的功能;初始化前不能使用
【发布时间】:2017-09-10 05:10:08
【问题描述】:

目前正在通过 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 初始化了几行。

我在语法上做错了什么?

【问题讨论】:

  • 添加(define inc add1) 后对我来说效果很好。您使用的是 REPL 还是定义区域?
  • 我不太确定两者之间的区别是什么,但我正在使用编辑器的顶部...这是它的样子:link。旁注,我确实有 (define (inc x) (+ x 1)) 代码,所以我有理由确定这不是问题的一部分。
  • 小突破!我四处询问,解决问题的方法是使用#lang racket 而不是#lang sicp...我不确定为什么这会改变任何事情,但欢迎任何见解!
  • 它可能将所有内部定义归为一个letrec,从而导致错误。这意味着前 3 个定义是 letrec,接下来的两个定义是 let。只是永远不要使用内部defines,反正这是一个没有意义的方便语法糖,真正的东西是let/letrec

标签: syntax scheme racket sicp


【解决方案1】:

这是该问题的最佳 Google 搜索结果之一,所以我想添加更多细节:

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

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

【讨论】:

    【解决方案2】:

    由于我目前也在通过 SICP 并遇到同样的错误,我想我会提到我认为的预期解决方案,因为问题在 letlambda 之前的部分。

    第一章脚注28中简要提到了这个错误:

    嵌入定义必须位于过程主体的首位。管理层不 负责运行将定义和定义交织在一起的程序的后果 使用。

    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)))
    

    【讨论】:

    • 一个看起来更干净的解决方案是(define (num n) (product num-prod 1 inc n))(define (denom n) (product denom-prod 1 inc n)),然后是(* 4 (/ (num n) (denom n)))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 2014-04-30
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    相关资源
    最近更新 更多