[racket-dev] define-require-syntax issue

From: Dan Liebgold (dan.liebgold at gmail.com)
Date: Wed Oct 22 14:55:36 EDT 2014

That makes sense.

It turns out I need replace-context *and* quasisyntax/loc (and back to
absolute paths):

(define-require-syntax (gamelib stx)
  (syntax-case stx ()
((_ name)
 (replace-context stx (quasisyntax/loc stx (file #,(format
"~a/some/path/~a.dc" (current-directory)  (syntax->datum #'name))))))
))

Without the ..syntax/loc form if I name the wrong file at my usage point
the error location is the define-require-syntax declaration. Adding the
/loc gets the correct usage location. Hrm.  Hygiene is deep magic.

Thanks,
Dan


On Wed, Oct 22, 2014 at 11:09 AM, Jay McCarthy <jay.mccarthy at gmail.com>
wrote:

> If you have (require X) then the identifiers imported from X get the
> lexical context of X. (Slight note: In something like (rename-in X [A
> B]) then they get the context of A.)
>
> If a macro made X, then the lexical context is equivalent to #f,
> because every macro application gets a fresh lexical context. (This
> part of how "hygiene" is implemented.)
>
> So, since you macro produced an argument to require, the imports got
> this empty lexical context.
>
> If you had produced a single identifier, then you could've produced it
> with (datum->syntax stx 'symbol) and that would make it so the symbol
> would have stx's context, rather than the default which is basically
> #f.
>
> In the case of a file or submodule etc, when we construct a syntax
> object with "syntax" (or quasisyntax or syntax/loc etc) there's no way
> to specify what lexical context we want. (The "/loc" variants just
> copy the source location, not the context.) Instead, we have to
> construct the object and then go back and change the lexical context
> using something like replace-context.
>
> Thus, the (file abc) that you produce now has the right stuff. It is
> possible that you could've just replace the context of "file" or of
> "abc" and got the same effect, but I'm not sure (it depends on how
> "file" is implemented.)
>
> Jay
>
>
>
>
> On Wed, Oct 22, 2014 at 2:03 PM, Dan Liebgold <dan.liebgold at gmail.com>
> wrote:
> > So, yeah... that appears to work!
> >
> > I use replace-context to give the resulting require syntax output the
> > context of the original argument. Here's what the change looks like,
> with my
> > old way commented (unrelated note: path is actually relative):
> >
> > (define-require-syntax (gamelib stx)
> >   (syntax-case stx ()
> > ((_ name)
> > ;;(quasisyntax/loc stx (file #,(format "../some/path/~a.dc"
> (syntax->datum
> > #'name)))))
> > (replace-context stx #`(file #,(format "../some/path/~a.dc"
> (syntax->datum
> > #'name)))))
> > ))
> >
> > I thought the quasisyntax/loc would be enough, but I guess
> replace-context's
> > increased thoroughness is necessary.
> >
> > So, is the problem that the identifiers imported by the require usage get
> > the lexical context of the 'define-require-syntax' declaration (where I
> use
> > #' maybe)?  I'm don't follow what exactly goes wrong with the imported
> > identifiers.
> >
> > Thanks,
> > Dan
> >
> >
> > On Wed, Oct 22, 2014 at 4:58 AM, Jay McCarthy <jay.mccarthy at gmail.com>
> > wrote:
> >>
> >> #lang racket/base
> >>
> >> ;; This module has a binding and an effect, so we can see that it was
> >> ;; required even when we can't get to it.
> >> (module example racket/base
> >>   (define x 1)
> >>   (printf "I'm running here\n")
> >>   (provide x))
> >>
> >> ;; If you comment this in, you'll see the "normal" way to require it.
> >>
> >> #;
> >> (let ()
> >>   (local-require (prefix-in no-macro: (submod "." example)))
> >>   (printf "NM x is ~a\n" no-macro:x)
> >>   (void))
> >>
> >> ;; Here is the "obvious" macro of tihs form
> >> (require racket/require-syntax)
> >> (define-require-syntax macro1
> >>   (syntax-rules ()
> >>     [(_) (submod "." example)]))
> >>
> >> ;; If you comment this in, you'll see that the effect is run, meaning
> >> ;; that it really does require the right thing. Also notice that since
> >> ;; I'm using submodules, the problem ISN'T that `example1` is some how
> >> ;; no the right binding for the module. In your example of an absolute
> >> ;; path, it's even more clear that the path isn't wrong.
> >>
> >> #;
> >> (let ()
> >>   (local-require (prefix-in macro1: (macro1)))
> >>   ;; If you comment this in, you'll see that it is unbound.
> >>   #;
> >>   (printf "M1 x is ~a\n" macro1:x)
> >>   (void))
> >>
> >> ;; Here is a more complicated version of the above macro. There's
> >> ;; really only one meaningful difference and that's that we explicitly
> >> ;; give the require syntax output the context of the CALL to
> >> ;; macro2. If macro2 had an argument, it may make more sense to use
> >> ;; that lexical context, because that argument probably came from the
> >> ;; ultimate user of this require syntax (in case macro2 is used by
> >> ;; another macro2)
> >> (require (for-syntax racket/base
> >>                      syntax/strip-context))
> >> (define-require-syntax macro2
> >>   (λ (stx)
> >>     (syntax-case stx ()
> >>       [(_)
> >>        (replace-context stx (syntax (submod "." example)))])))
> >>
> >> ;; You may want to comment this out while looking at the other ones so
> >> ;; you can be sure that this isn't the reason something is working.
> >>
> >> (let ()
> >>   (local-require (prefix-in macro2: (macro2)))
> >>   (printf "M2 x is ~a\n" macro2:x)
> >>   (void))
> >>
> >> On Tue, Oct 21, 2014 at 9:26 PM, Dan Liebgold <dan.liebgold at gmail.com>
> >> wrote:
> >> > If I do a (require (file <some absolute path>)) in a module, the
> >> > provided
> >> > stuff gets imported properly.
> >> >
> >> > If I do a special require form that uses define-require-syntax to
> >> > generate
> >> > an identical (file <...>) the specified module gets evaluated -- but
> >> > (seemingly) nothing gets imported.
> >> >
> >> > Is there something special the define-require-syntax transformer needs
> >> > to do
> >> > besides generate a syntax object?
> >> >
> >> > samth mentioned on irc that it is probably a hygiene issue...
> something
> >> > about generating the right marks on the (file ...) form.
> >> >
> >> > --
> >> > Dan Liebgold    [dan.liebgold at gmail.com]
> >> >
> >> > _________________________
> >> >   Racket Developers list:
> >> >   http://lists.racket-lang.org/dev
> >> >
> >>
> >>
> >>
> >> --
> >> Jay McCarthy
> >> http://jeapostrophe.github.io
> >>
> >>            "Wherefore, be not weary in well-doing,
> >>       for ye are laying the foundation of a great work.
> >> And out of small things proceedeth that which is great."
> >>                           - D&C 64:33
> >
> >
> >
> >
> > --
> > Dan Liebgold    [dan.liebgold at gmail.com]
>
>
>
> --
> Jay McCarthy
> http://jeapostrophe.github.io
>
>            "Wherefore, be not weary in well-doing,
>       for ye are laying the foundation of a great work.
> And out of small things proceedeth that which is great."
>                           - D&C 64:33
>



-- 
Dan Liebgold    [dan.liebgold at gmail.com]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/dev/archive/attachments/20141022/54b2f2ce/attachment-0001.html>

Posted on the dev mailing list.