0

Currently going through SICP, and near the end of the first chapter, they ask you to program a value for pi, with pi/4 = (2 * 4 * 4 * 6 * 6 * 8 * ...) / (3 * 3 * 5 * 5 * 7 * 7 *..)

I have the following functions defined:

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

and

(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

When I run this code in DrRacket, I get the following error: num-prod: Undefined; Cannot use before initialization, even though I initialize num-prod a couple of lines before I use it.

What am I doing wrong syntactically?

Ricardo Iglesias
  • 595
  • 2
  • 6
  • 16
  • Worked fine for me as soon as I added `(define inc add1)`. Are you using the REPL or the definitions area? – Brendan Cannell Apr 13 '17 at 23:30
  • I'm not really sure what the difference between the two is, but I'm using the top part of the editor... Here's what it looks like: [link](https://imgur.com/a/m2R0A). Side note, I did have the `(define (inc x) (+ x 1))` code, so I'm reasonably certain that wasn't part of the problem. – Ricardo Iglesias Apr 14 '17 at 00:40
  • 1
    Small breakthrough! I asked around and something that fixed the issue was using `#lang racket` as opposed to `#lang sicp`... I'm not really sure why that would change anything, but any insight would be welcome! – Ricardo Iglesias Apr 14 '17 at 04:21
  • it probably grouped all the internal defines into one `letrec`, causing the error. what is meant there instead is a `letrec` for the first 3 defines, then a `let` for the next two. just never use internal `define`s, it's a meaningless convenience syntax sugar anyway, the real thing is `let`/`letrec`. – Will Ness Oct 03 '20 at 10:13

2 Answers2

2

This is one of the top Google results for the question, so I thought I'd add some more detail:

In most Scheme implementations (such as R5RS), there is no guarantee of the order in which your definitions are parsed. In other words, they are not parsed sequentially. Yes, you defined num-prod a few lines before, but it's entirely possible that num is compiled first, hence the error.

In Racket, lambdas are compiled to letrec* operators instead of letrec, meaning that there is a guarantee of sequential parsing. That's why changing languages helped.

2

Since I am also currently going through SICP and ran into the same error, I thought I'd mention what I think is the intended solution, since the question is in the section before let and lambda.

This error is mentioned briefly in footnote 28 in the first chapter:

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 is being used inside another definition, so the program actually is intertwining definition and use, even though it looks like the definitions all come before the body.

Possible solutions (without let and lambda) are to avoid defining num and denom, replacing them with the product expression, or to define num as a function with an argument, and put num-prod as the argument in the body:

(define (num terms) (product terms 1 inc n)) 
(define (denom terms) (product terms 1 inc n)) 
(* 4 (/ (num num-prod) (denom denom-prod)))
  • a cleaner-looking solution is `(define (num n) (product num-prod 1 inc n))`, `(define (denom n) (product denom-prod 1 inc n))` and then `(* 4 (/ (num n) (denom n)))`. – Will Ness Oct 03 '20 at 19:30