[racket] hygienic read-macros (was: module-level definitions vs. local definitions and how binding works)
I tried to make it with module
(module m racket
(define-syntax (make-reader stx)
(syntax-case stx ()
[(_ NAME BODY ...)
(with-syntax ([GENSYM (datum->syntax stx (gensym))])
#'(begin
(define-syntax (GENSYM stx)
(syntax-case stx ()
[(_ in src line col pos) BODY ...]))
(provide GENSYM)
(define NAME
(case-lambda
[(ch in)
(datum->syntax #f '(GENSYM in #f #f #f #f))]
[(ch in src line col pos)
(datum->syntax #f '(GENSYM in src line col pos))]))))]))
(make-reader read-dollar
#'(lambda (x) x))
(current-readtable
(make-readtable (current-readtable)
#\$ 'terminating-macro read-dollar)))
(require 'm)
Works just fine
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.
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.
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
>
>On Jul 28, 2014, at 3:49 AM, Roman Klochkov < kalimehtar at mail.ru > wrote:
>
>>
>> You may use such macro for making hygienic read-macros
>>
>> (define-syntax (make-reader stx)
>> (syntax-case stx ()
>> [(_ NAME BODY ...)
>> (with-syntax ([GENSYM (datum->syntax stx (gensym))])
>> #'(begin
>> (define-syntax (GENSYM stx)
>> (syntax-case stx ()
>> [(_ in src line col pos) BODY ...]))
>> (provide GENSYM)
>> (define NAME
>> (case-lambda
>> [(ch in)
>> (datum->syntax #f '(GENSYM in #f #f #f #f))]
>> [(ch in src line col pos)
>> (datum->syntax #f '(GENSYM in src line col pos))]))))]))
>>
>> Usage example:
>> (make-reader read-dollar
>> #'(lambda (x) x))
>>
>> (current-readtable
>> (make-readtable (current-readtable)
>> #\$ 'terminating-macro read-dollar))
>>
>> Test:
>>> $
>> #<procedure>
>>> (let ([lambda 1]) $)
>> #<procedure>
>>
>> All works just fine
>>
>> Sun, 27 Jul 2014 20:10:48 -0400 от "Alexander D. Knauth" < alexander at knauth.org >:
>>> It seems like “hygienic reader extensions” still work when a module-level definition conflicts with it, but it seems like if it’s a local binding the local binding overrides the one in the reader extension.
>>>
>>> For example:
>>> #lang rackjure
>>> ;; this works:
>>> (define lambda "module-level-whatever")
>>> #λ(void %1) ; #<procedure>
>>> ;; this doesn't work
>>> (let ([lambda "local-whatever"]
>>> [%1 void]
>>> [define-syntax void]
>>> [% void])
>>> #λ(void %1)) ; application: not a procedure;
>>> ; ; expected a procedure that can be applied to arguments
>>> ; ; given: "local-whatever"
>>> ; ; arguments…:
>>>
>>> Why does it work at the module-level and not within a let?
>>>
>>> Is this a bug, or should reader extensions not be used this way, or what?
>>>
>>> What’s going on here?
>>>
>>>
>>> ____________________
>>> Racket Users list:
>>> http://lists.racket-lang.org/users
>>>
>>
>>
>> --
>> Roman Klochkov
>
--
Roman Klochkov