[racket] Understanding local-expand with definition contexts

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Mon Jan 5 11:32:41 EST 2015

I think it's more a question of what a definition context is supposed
to be, rather than how `syntax-local-bind-syntaxes` works.

When you create a new definition context, the context's bindings are
visible only to expressions that are also in that context. The `test`
form here creates a new definition context in much the same way as
`(let () ...)`:

 (let ()
   (let () (define x 1))
   x)

In other words, the final `x` really is out of the scope of the
definition of `x`.

At Mon, 05 Jan 2015 16:26:30 +0000, Spencer Florence wrote:
> Progress is a new error! I don't think I understand how
> syntax-local-bind-syntaxes is supposed to work. I extended the previous
> program:
> 
> #lang racket
> (require (for-syntax syntax/parse))
> (define-syntax (test stx)
>   (syntax-parse stx
>     [(_ e)
>      (define ctx
>        (if (list? (syntax-local-context))
>            (cons (gensym) (syntax-local-context))
>            (list (gensym))))
>      (define def-ctx (syntax-local-make-definition-context))
>      (define expd (local-expand #'e ctx (list #'define-values) def-ctx))
>      (define ids (syntax-parse expd [(def (id) _) (list #'id)]))
>      (syntax-local-bind-syntaxes ids #f def-ctx)
>      (internal-definition-context-seal def-ctx)
>      expd]))
> (let ()
>   (test (define x 1))
>   x)
> 
> And now I receive the error:  `x: unbound identifier in module in: x`
> Looking at the docs for `syntax-local-make-definition-context` it seems
> like I need to provide it with the parent definition-context, but I'm not
> sure how to get a hold of that.
> 
> --spf
> 
> On Mon Jan 05 2015 at 10:00:53 AM Matthew Flatt <mflatt at cs.utah.edu> wrote:
> 
> > The error message is intended for "end users" and turns out to be
> > misleading for the implementor of an internal-definition context. The
> > documentation for `define-values` has essentially the same problem: it
> > describes how `define-values` should work in an internal-definition
> > context, but it doesn't say how the form interacts with `local-expand`.
> >
> > A `define-values` form will only expand in a module or top-level
> > context. To implement an internal-definition context, you must expand
> > only far enough to see `define-values` form; in other words, supply
> > `#'define-values` in the stop list. Then, a partially expanded
> > `define-values` form must be recognized and handled explicitly, with
> > tools like `syntax-local-bind-syntaxes` or re-writing to
> > `letrec-values`, as appropriate for the definition context.
> >
> > At Mon, 05 Jan 2015 14:49:03 +0000, Spencer Florence wrote:
> > > Hey all,
> > >
> > > I'm trying to use 'local-expand', however it seems to think its never in
> > a
> > > definition context. For example:
> > >
> > > (require (for-syntax syntax/parse))
> > > (define-syntax (test stx)
> > >   (syntax-parse stx
> > >     [(_ e)
> > >      (define ctx
> > >        (if (list? (syntax-local-context))
> > >            (cons (gensym) (syntax-local-context))
> > >            (list (gensym))))
> > >      (local-expand
> > >       #'e ctx null
> > >       ;; result is the same with this uncommented
> > >       #;(syntax-local-make-definition-context))]))
> > > (let ()
> > >   (test (define x 1))
> > >   x)
> > >
> > > errors with a "define-values: not in a definition context in:
> > > (define-values (x) 1)"
> > >
> > > Can anyone provide any insight into what is going on?
> > >
> > > --spf
> > > ____________________
> > >   Racket Users list:
> > >   http://lists.racket-lang.org/users
> >

Posted on the users mailing list.