[racket] hygienic read-macros (was: module-level definitions vs. local definitions and how binding works)

From: Alexander D. Knauth (alexander at knauth.org)
Date: Mon Jul 28 23:45:13 EDT 2014

On Jul 28, 2014, at 10:15 PM, Roman Klochkov <kalimehtar at mail.ru> wrote:

> 
> 
> 
> Mon, 28 Jul 2014 13:51:12 -0400 от "Alexander D. Knauth" <alexander at knauth.org>:
> 
> On Jul 28, 2014, at 11:41 AM, Roman Klochkov <kalimehtar at mail.ru> wrote:
> 
> > I tried to make it with module
> .....
> 
> > (require 'm)
> > 
> > Works just fine
> 
> Yes because GENSYM was provided by ‘m, but if it’s a #lang then that doesn’t matter unless you specifically require experiment-with-hygenic-reader-extensions/lang/reader. And as I say below, I shouldn’t have to do that, and I shouldn’t have to provide GENSYM either.
> Read macros return source code. So there are no other way.

They can return syntax-objects, and it seems to work for lambda (if there’s no local variable conflicting), so I’m trying to understand why it works for lambda and not for GENSYM.  
By the way the language does not have to provide lambda in this case:
#lang afl s-exp "no-lambda.rkt"
(map #λ(+ % %2) '(1 2 3) '(1 2 3)) ; '(2 4 6)
where afl is a meta-language that adds #λ to a language, and no-lambda.rkt is this:
#lang racket/base
(provide (except-out (all-from-out racket/base) lambda))

So since “no-lambda.rkt” doesn’t have to provide lambda for #λ to work, why would you have to provide GENSYM?  That’s (part of) what I’m trying to figure out.  Why does one work and the other not work?  

> 
> 
> > I'm not very proficient with lang, but you should require module with `make-reader' to you last module.
> > 
> > I installed your package via `raco pkg install git://github.com/AlexKnauth/experiment-with-hygenic-reader-extensions', but
> > 
> > $ /usr/racket/bin/racket try-it.rkt
> > default-load-handler: cannot open module file
> > module path: experiment-with-hygenic-reader-extensions/lang/reader
> > path: /home/monk/.racket/6.0.1/pkgs/experiment-with-hygenic-reader-extensions/experiment-with-hygenic-reader-extensions/lang/reader.rkt
> > system error: No such file or directory; errno=2
> > 
> > Maybe something wrong.
> 
> Hmm, it doesn't do that for me. 
> But I’m just wondering, when you look at …/pkgs/experiment-with-hygenic-reader-extensions, does it have …extensions/langreader.rkt instead of …extensions/lang/reader.rkt ?
> Yes, …extensions/langreader.rkt
> 
> 
> > I think you should add (require (submod experiment-with-hygenic-reader-extensions/lang/reader reader)) to try-it. Or make another module with make-reader, which will be required by lang and result program.
> 
> Well another good thing about hygienic macros and syntax-objects is encapsulation so that a macro can use GENSYM without having to provide GENSYM, so that GENSYM does not have visible to the user of the macro. So you shouldn’t have to add a (require experiment-…/lang/reader) to try-it.rkt.
> Yes. Because macros in Scheme/Racket don't build code, they build syntax. But read-macros build source code (in the meaning of "program text"). Don't know why, maybe because syntax context, returned by read-syntax should be current context, not the context of language definition.

Well it should, for normal things.  However since I want the lambda produced by #λ to be the same no matter what module it’s in, I want to use the lexical context from the reader.rkt module, and I also want to figure out what works, what doesn’t, and why?  

It seems like you’re trying to tell me that “hygienic reader extensions” can’t work.  But if it’s working for lambda (if …), then why wouldn’t it work for GENSYM?  

> 
> 
> But for some reason that’s not always working for reader extensions. 
> 
> It seems to work when the binding is from racket/base and there’s no local binding conflicting with it (but module-level bindings conflicting with it are ok), but not when it’s from a different module other than racket/base?
> It always work, when the binding is from current module (if it doesn't require racket/base, then its bindings won't work also).
> 
> 
> I don’t know. 
> 
> > 
> > Mon, 28 Jul 2014 11:08:20 -0400 от "Alexander D. Knauth" <alexander at knauth.org>:
> >> Well that works fine when it’s in the same module (or namespace), but when I put it in a #lang, it breaks and I get this error:
> >> experiment-with-hygenic-reader-extensions/try-it.rkt:
> >> #lang experiment-with-hygenic-reader-extensions
> >> $
> >> ; g15667: unbound identifier in module in: g15667
> >> 
> >> That’s one problem with unhygienic reader extensions. 
> >> Since you used (datum->syntax #f ‘(GENSYM …)), it eventually took on the lexical context of try-it.rkt, where the GENSYM name isn’t there.
> >> 
> >> Though strangely, if I put some lexical context on GENSYM by using (datum->syntax #f `(,#'GENSYM …)), then it gives me this error:
> >> experiment-with-hygenic-reader-extensions-2/try-it.rkt:
> >> #lang experiment-with-hygenic-reader-extensions-2
> >> $
> >> ; require: namespace mismatch;
> >> ; reference to a module that is not available
> >> ; reference phase: 0
> >> ; referenced module: “…/experiment-with-hygenic-reader-extensions-2/lang/reader.rkt"
> >> ; referenced phase level: 0 in: g24
> >> 
> >> https://github.com/AlexKnauth/experiment-with-hygenic-reader-extensions
> >> 
> 
> > 
> > 
> > -- 
> > Roman Klochkov
> 
> 
> 
> -- 
> Roman Klochkov

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140728/a40f1fe3/attachment-0001.html>

Posted on the users mailing list.