[plt-scheme] define-values/invoke-unit in an internal definition context

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sat Oct 11 07:17:09 EDT 2008

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


Posted on the users mailing list.