[plt-scheme] syntax and promises and possibly phases

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon May 19 14:09:57 EDT 2003

At Sun, 18 May 2003 14:00:41 -0400, "Neil W. Van Dyke" wrote:
> I now have to admit that I was trying to use a concrete example to ask a
> more general question about syntax extensions that cache values.
> So I'm also curious if there's a way to solve this problem using a
> hygienic macro, without using a table.  Intuition says there should be
> an easy way.
> (I asked on plt-scheme list before comp.lang.scheme, since the answer
> might be sensitive to the trickiness of evaluation phases, and MzScheme
> seems to know phase separation well.)

You're poking at the edges of the phase problem, where it's not yet
right in MzScheme, and where I think we need one more piece to make it

Here's one way to do what you want, at least for now. It exploits a
kind of hole in MzScheme:

  (define-syntax remember
    (syntax-rules ()
      [(_ expr)
       (let ([b #&#f])
           (unless (unbox b)
             (set-box! b (list expr)))
           (car (unbox b))))]))

  (define (f x) (remember x))

  (define (g x) (remember x))

Everytime you call `f', the result is the argument provided to `f' for
its very first call. Ditto for `g', but `g' is independent of `f'.

The `remember' macro exploits an as-yet-untamed phase: the time when
run-time values are generated for syntactic constants. If you evaluate
the expressions above directly, this generation happens when each
definition is compiled. If you compile the code to .zo, it happens at
`read' time for the compiled code.

If you put the code in a module, then every instance of the module
(independent of its phase) shares the same pair of mutable boxes for
`f' and `g'. That's the most obvious way that this is a hole in the
enforcement of phases.

Previously, I thought that we should close this hole by creating
immutable values for syntactic constants --- so #&#f would generate a
constant box containing #f (which begs the question of how the box can
be useful, but nevermind). Then, you wouldn't be able to mutate the
same box from different instantiations/phases of a module. `eq?'
comparisons remain a problem, though.

Maybe instead we should more explicitly tame the value-generation
phase. We could generate values for syntactic constants consistently at
the containing module's instantiation time, instead of at read and/or
compile time. Then, `remember' above would work reliably, and gensyms
would behave consistently with compilation.


Posted on the users mailing list.