0

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"?

nalzok
  • 14,965
  • 21
  • 72
  • 139
  • You can't, or at least shouldn't be able to, because internal `define`s may occur only at the beginning of the body of a `define`, `lambda`, `let`, `let*`, `letrec` etc (according to r5rs). – manualcrank Nov 20 '16 at 02:59
  • @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 Nov 20 '16 at 03:03
  • Some schemes probably do allow your first definition, but will raise an error when `bar` is invoked before its definition. – manualcrank Nov 20 '16 at 03:58
  • 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 Nov 20 '16 at 04:09

1 Answers1

1

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.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • `(define (foo) (bar)) (define (bar) (display "bar"))` In this code, it seems that the timeline is kind of chaotic: `(bar)` is referenced and called _before_ its definition. Could you explain why is it? – nalzok Nov 21 '16 at 06:49
  • you have two definitions there. the first defines `foo` as calling `(bar)` -- it doesn't call it yet, just is defined to do so, *when* and *if* called in the future. If `(foo)` were indeed called next, it would error with `undefined: bar` message. Instead, the second definition defines `bar`, so after that, if `(foo)` is called, no error will be caused. --- important note: some REPLs would still make it an error -- they do not define same name `bar` that `foo` sees, but another, *newer* `bar`. That is what I hinted at in the last sentence. – Will Ness Nov 21 '16 at 08:30
  • so `bar` *is* referenced before it is defined, but it is *not* called (used). – Will Ness Nov 21 '16 at 08:31