[plt-scheme] define-values/invoke-unit in an internal definition context
Well, it's not a bug in the implementation. (Also, I now see that this
code behaves the same way in older versions; I should have tried that
in the first place.)
Here's a slightly simplified version with the same problem:
#lang scheme/base
(require scheme/unit)
(define-signature sig^ (a))
(define unit@
(unit
(import)
(export sig^)
(define a 0)))
(define-syntax use-unit@
(syntax-rules ()
[(_)
(let ()
(define-values/invoke-unit unit@ (import) (export sig^))
(printf " ~a\n" a))]))
(use-unit@)
You might think that since `sig^' and `a' are introduced by the macro,
the former effectively binds the latter. That would make sense if the
elements of a signature were symbols, in which case they could take on
the lexical context of the use of a signature.
But signature elements are instead identifiers that already have their
own lexical context. The `sig^' above acts more like a reference, and
it pulls the original identifiers of the signature (i.e., without
further "marking") into the expansion to create new bindings. The
content of `sig^' consists of identifiers not introduced by the macro,
so it fails to bind `a'.
In other words, the above example is analogous to
(define-syntax-rule (ex id)
(let ([id 5]) a))
(ex a)
which doesn't bind the `a' introduced by the macro.
The only solution I see is to introduce `a' non-hygienically:
(define-syntax (use-unit@ stx)
(syntax-case stx ()
[(_)
(with-syntax ([a (syntax-local-introduce #'a)])
#'(let ()
(define-values/invoke-unit unit@ (import) (export sig^))
(printf " ~a\n" a)))]))
I'd be happier with a solution that made the original code work, but I
don't yet see how to do that.
Matthew
At Thu, 9 Oct 2008 08:03:54 -0500, Matthew Flatt wrote:
> Looks like a macro-expander bug to me. A few weeks ago, I adjusted the
> way that identifier bindings are determined in internal-definition
> contexts, and that change appears to be interacting badly with the
> `unit' macros in this case. I'll have to investigate more.
>
> Matthew
>
> At Thu, 9 Oct 2008 08:08:24 +0100, "Noel Welsh" wrote:
> > I'm trying to abstract over both macros and normal values, but having
> > a problem that define-values/invoke-unit doesn't seem to work in a
> > local definition context. A simple example is below. Reading the
> > code is perhaps easier than explaining in words what I'm doing, so I
> > won't go into detail here. Can anyone tell me how to get it working?
> >
> > Thanks,
> > Noel
> >
> >
> > #lang scheme/base
> >
> > (require (for-syntax scheme/base)
> > scheme/unit
> > (planet schematics/schemeunit:3))
> >
> > (define-signature sig^ (a b c))
> >
> > (define unit@
> > (unit
> > (import)
> > (export sig^)
> >
> > (define a 0)
> > (define b 1)
> > (define c 2)))
> >
> > (define-syntax macro1
> > (syntax-rules ()
> > [(_) (display "hello")]))
> >
> > (define-syntax macro2
> > (syntax-rules ()
> > [(_) (display "o hai")]))
> >
> > ;; Here we abstract over macros and the unit
> > (define-syntax use-unit@
> > (syntax-rules ()
> > [(_ macro)
> > ((lambda (unit)
> > (define-values/invoke-unit unit (import) (export sig^))
> > (macro) (printf " ~a ~a ~a\n" a b c)))]))
> >
> > '((use-unit@ macro1) unit@)
> > ((use-unit@ macro2) unit@)
> > _________________________________________________
> > For list-related administrative tasks:
> > http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> _________________________________________________
> For list-related administrative tasks:
> http://list.cs.brown.edu/mailman/listinfo/plt-scheme