I have a question about identifier binding:
In REPL, I typed: test.rkt> (define (test env) 1)
test.rkt> (test (λ (var) ⊥))
1
It is OK.
But in the test.rkt file: #lang racket
(define (test env) 1)
(test (λ (var) ⊥))
It complained ⊥: unbound identifier in module
Although the ⊥
in the body of the lambda is unbound identifier, but I doesn’t use it at all. Why it complained?
Actually, the REPL’s behavior is considered bad, but we need to support it for mutually recursive function.
E.g.,
test.rkt> (define (a) (b))
test.rkt> (define (b) (a))
If the REPL reports unbound identifier right away, (define (a) (b))
would result in an error.
Think about this way: In a module (file) the compiler checks for a wider range of errors than it can in the repl. In a module all identifier needs to be bound, hence the error that ⊥ is undefined. In the repl there are are fewer checks - in particular identifiers in the body of a lambda expression are allowed to be unbound. As Sorawee says, this allows the definition of mutually recursive functions in the repl.
That is, the question is not why you get an error in the module (file), but why you don’t get an error in the repl!
OK, It make sense. Thanks. @sorawee @soegaard2
Is it generally better to use a box
instead of set!
?
I prefer doing so
I don’t think there’s any consensus about it in the Racket community though
I think it’s good to make mutation a distinct concept from binding