> (version)
"8.8"
> (require (for-syntax racket/base))
> (define-syntax-rule (make-module n (l ...) i b)
(module n racket/base
(require l ...)
(provide i)
(define i b)))
> (make-module t () x 1)
string:1:20: ?: literal data is not allowed;
no #%datum syntax transformer is bound
at: 1
[,bt for context]
> (make-module t (racket/base) x 1)
Anyway, the macro can be expanded successfully at last, but I don't want to import the library twice. What should I do? Or is this documented?
1 Like
I think the problem is how #%datum
is introduced.
When #%datum
is introduced it gets the lexical information from the
syntax object (that needs to wrapped in #%datum
).
In the form (make-module t () x 1)
the 1
will become (#%datum . 1)
but the #%datum
has lexical information from outside the t
module.
So you get the "no #%datum syntax transformer is bound" error.
How to solve the problem depends on where you want b
to get its context.
One option:
(define-syntax (make-module stx)
(syntax-case stx ()
[(_make-module n (l ...) i b)
(with-syntax ([b (datum->syntax #'stx (syntax->datum #'b))])
(syntax/loc stx
(module n racket/base
(require l ...)
(provide i)
(define i b))))]))
1 Like
Thanks for your kind explanation, sir!
But there still remains a question. Why does the error just disappear when we explicitly import the library in the t
module?
It boils down to how (require module-path)
works.
(require module-path)
Imports all exported bindings from the named module,
using the export name for the local identifiers.
The lexical context of the module-path form determines the
context of the introduced identifiers, a ...
So in (make-module t (racket/base) x 1)
the racket/base
and 1
have the same lexical context. When inserted in (require l ...)
the imported binding for #%datum
will have the same context as 1
.
And when the implicit #%datum
is added, it will now be bound.
Thank you very much, sir!
But according to the documentation,
The module-path form must be as for require, and it supplies the initial bindings for the body forms. That is, it is treated like a (require module-path) prefix before the forms, except that the bindings introduced by module-path can be shadowed by definitions and requires in the module body forms.
Is this case an exception?
In
(module n racket/base ...)
the context of the racket/base is "inside the module n".
Likewise, in:
(module n racket/base
(require racket/base)
...)
the context of racket/base
is also inside module n
, so this is fully redundant.
However, in your example (make-module t (racket/base) x 1)
the context of
racket/base
is "from outside the module n", so the bindings of (require racket/base)
will get that context.
Oh, I see. Sorry for bothering you!