[plt-scheme] module-based language and defining primitives?

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Thu Feb 8 19:40:43 EST 2007

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



Posted on the users mailing list.