[plt-scheme] module-based language and defining primitives?
At Thu, 8 Feb 2007 15:01:04 -0800 (PST), Danny Yoo wrote:
> ;; In Pretty Big
> (require (planet "simply-scheme.ss" ("dyoo" "simply-scheme.plt")))
>
> (define (accumulate combiner null-value term a next b)
> (if (> a b)
> null-value
> (combiner (term a)
> (accumulate combiner null-value term (next a) next b))))
>
> (accumulate + 0 (lambda (x) x) 1 add1 10)
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>
> Somehow, the inner definition of accumulate is being bound to the one
> that's built into Simply Scheme; that is, I'm seeing let vs letrec
> behavior on definitions.
If Simply Scheme is a module-based language in DrScheme, I think you
can tell DrScheme to use `namespace-require/copy' instead of `require',
which avoids this kind of confusion.
The problem is that the reference to `accumulate' is expanded/compiled
before the definition of `accumulate' is executed. Consequently, the
reference to `accumulate' is is expanded/compiled as a reference to the
module import, not to a top-level variable.
This is a general problem with the top level. Syntax definitions
interact badly with `define' in the same way and for the same reason:
> (define-syntax plus (syntax-rules () [(_ x y) '(+ x y)]))
> (plus 1 2)
(+ 1 2)
> (define plus (lambda (x) (plus x 3)))
> (plus 10)
(+ x 3)
`namespace-require/copy' avoids the problem by copying non-syntax
exports into definitions, which can then be changed with later
`define's in the traditional way.
Eli has pointed out that we could partly avoid the problem by having
`(define x v)' expand to something like
(begin
(real-define x #f)
(set! x v))
This would work due to a lot of ugly, special-case handling for
top-level `begin' that all our tools have to implement.
I've resisted the change because it doesn't solve the problem when an
expression refers to a later definition --- the expressions will still
be expanded/compiled before the `real-define' is evaluated --- so I
worry that solving the problem for the self-referential case just hides
the true problem even deeper.
Complaints about the self-referential case have become increasingly
common, though, and maybe it makes sense to hide the problem a little
deeper. I'm sure I won't run out of opportunities to point out that the
top level is hopeless. :)
Matthew