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

From: Abdulaziz Ghuloum (aghuloum at cs.indiana.edu)
Date: Sat Oct 11 13:03:27 EDT 2008

On Oct 11, 2008, at 7:17 AM, Matthew Flatt wrote:

> 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.

I would, yes (sorry for jumping in).

> 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'.

This is a problem because the identifiers introduced by that macro
(or by sig^) will (1) not bind to identifiers that were introduced
in the same macro step, and (2) bind identifiers that were *not*
introduced by the macro step.  So, it does exactly the opposite of
what hygienic macros do.

So, this works because the "a" introduced by sig^ is unmarked, and
the "a" passed to use-unit@ is also unmarked.

  (define-syntax use-unit@
    (syntax-rules ()
      [(_ id)
       (let ()
         (define-values/invoke-unit unit@ (import) (export sig^))
         (printf " ~a\n" id))]))

  (use-unit@ a)


Aziz,,,


Side Note: Ikarus has an internal module form that was borrowed
from Chez and is described in Oscar Waddel's dissertation.  My
implementation had a similar problem.

This example, similar to the one on top using sigs has a macro
that expands to an import and a reference.  It didn't work at
first but now it now correctly and produces a=12.

(let ()
   (module M (a)
     (define a 12))
   (define-syntax f
     (syntax-rules ()
       [(_)
        (let ()
          (import M)
          (printf "a=~s\n" a))]))
   (f))

The counter example is the following where you have a macro
that expands to an import wrapping an expression that contains
module identifiers.  This doesn't work now (and it shouldn't
because import should be hygienic) but it used to work in the
broken implementation of Ikarus.  This is essentially how the
use-unit@ macros works (above) and how it will break once the
signatures are fixed.

(let ()
   (module M (a)
     (define a 12))
   (define-syntax f
     (syntax-rules ()
       [(_ id)
        (let ()
          (import M)
          (printf "a=~s\n" id))]))
   (f a))




Posted on the users mailing list.