0
votes

Take the following function definition as my example:

(define (foo)
  (bar)
  (define (bar)
    (display "bar")))

This would produce an error: ;Premature reference to reserved name: bar. On the contrary, the following two definitions are legitimate. Note that I'm using premature reference in both of them.

(define (foo)
  (bar))
(define (bar)
  (display "bar"))

(define (foo)
  (define (bar)
    (display "bar"))
  (bar))

My question is: why can't I prematurely reference a currently undefined function when using block structure? And why is bar a "reserved name"?

1
You can't, or at least shouldn't be able to, because internal defines may occur only at the beginning of the body of a define, lambda, let, let*, letrec etc (according to r5rs). - manualcrank
@manualcrank But why? Premature reference can make code more comprehensive, which I believe to be a great advantage. What are the drawbacks of allowing define to appear anywhere in the body of a containing define? - nalzok
Some schemes probably do allow your first definition, but will raise an error when bar is invoked before its definition. - manualcrank
For example Racket will allow you to define (define (foo) (bar) (define (bar) (display "bar")) (bar)). Notice, though, the extra (bar) after its definition; Racket insists on at least one expression after a sequence of internal definitions. Chez Scheme, OTOH, rejects both this and your original foo at compile time. - manualcrank

1 Answers

1
votes

You can reference it, but you can't use what's still undefined.

Racket lets you define

(define (foo) 
  (bar)                    ; here the future error
  (define (bar) 
      (display "bar")) 
  (bar))

but when you try to call (foo) it errors with the message

    bar: undefined;
cannot use before initialization

So, there is a certain timeline involved here, certain sequencing; some things are done before others, according to their textual position in the definition. Consider this further Racket REPL interaction:

> (define (foo) (baz) (define (bar) (display "bar")) (bar))
> (foo)
. . baz: undefined;
 cannot reference an identifier before its definition
> (define (baz) '())
> (foo)
bar

The REPL has its own timeline. Each Scheme implementation can handle this aspect of REPL in its own way, though.