Namespaces and modules

66 views
Skip to first unread message

Dominik Pantůček

unread,
Nov 12, 2020, 5:35:17 PM11/12/20
to Racket Users
Hello Racketeers,

it seemed to me that writing a data format for my project by simply
introducing a new syntax forms and then just eval'uating the file (maybe
eval-syntax) was a great idea. I've done things like that many times but
my initial bindings were always in a separate file. Like:

==== sandbox.rkt
#lang racket/base
(provide #%app #%datum test)
(define (test) (displayln 'test))
====

Then a simple example looks like:

(parameterize ((current-namespace (make-base-empty-namespace)))
(namespace-require "sandbox.rkt")
(eval '(test)))

Easy and works without a flaw.

If I however try to achieve the same goal using module form within my
module, it always fails:

(module sandbox racket/base
(provide #%app #%datum test)
(define (test) (displayln 'test)))
(parameterize ((current-namespace (make-base-empty-namespace)))
(namespace-require ''sandbox)
(eval '(test)))

It fails with:

require: unknown module
module name: 'm

Of course, without double-quoting, it yields:

standard-module-name-resolver: collection not found
for module path: m
collection: "m"
...

Which is expected. And require'ing the module doesn't change a thing (of
course, (require 'm) require's it in the surrounding module).

After going through the modules and namespaces documentation back and
forth I feel like I am overlooking something.

Roughly the goal is to define a bunch of structs in the encapsulating
module, provide syntax to the evaluation namespace, evaluate the file
with data and get the result.

Any hint would be very appreciated.


Cheers,
Dominik

Matthew Flatt

unread,
Nov 12, 2020, 5:45:42 PM11/12/20
to Dominik Pantůček, Racket Users
At Thu, 12 Nov 2020 23:35:11 +0100, Dominik Pantůček wrote:
> If I however try to achieve the same goal using module form within my
> module, it always fails:
>
> (module sandbox racket/base
> (provide #%app #%datum test)
> (define (test) (displayln 'test)))
> (parameterize ((current-namespace (make-base-empty-namespace)))
> (namespace-require ''sandbox)
> (eval '(test)))

Using ''sandbox as an argument to `namespace-require` to refer to a
local module is something like passing 'x to `eval` to try to refer to
a local variable `x`. The `namespace-require` procedure doesn't know
where it's being called from, so it doesn't work.

Try `quote-module-path`, which expands at compile time to effectively
embed its context:

#lang racket/base
(require syntax/location)

(module sandbox racket/base
(provide #%app #%datum test)
(define (test) (displayln 'test)))

(parameterize ((current-namespace (make-base-empty-namespace)))
(namespace-require (quote-module-path sandbox))
(eval '(test)))

Dominik Pantůček

unread,
Nov 15, 2020, 3:38:05 AM11/15/20
to racket...@googlegroups.com

>
> Using ''sandbox as an argument to `namespace-require` to refer to a
> local module is something like passing 'x to `eval` to try to refer to
> a local variable `x`. The `namespace-require` procedure doesn't know
> where it's being called from, so it doesn't work.
>
> Try `quote-module-path`, which expands at compile time to effectively
> embed its context:
>
> #lang racket/base
> (require syntax/location)
>
> (module sandbox racket/base
> (provide #%app #%datum test)
> (define (test) (displayln 'test)))
>
> (parameterize ((current-namespace (make-base-empty-namespace)))
> (namespace-require (quote-module-path sandbox))
> (eval '(test)))
>

This is exactly what I was looking for! Thank you. It's a pity I didn't
ask in the past :)

However, now I see a problem with creating executables with raco exe.

MWE follows.

==== test-submod.rkt
#lang racket

(require syntax/location)

(module my-dsl racket/base

(provide #%app my-proc)

(define (my-proc)
(displayln "my-dsl/my-proc")))

(define (parse sexp)
(parameterize ((current-namespace (make-base-empty-namespace)))
(namespace-require (quote-module-path my-dsl))
(eval sexp)))


(parse '(my-proc))
====

And then:

$ ../racket-lang/racket/racket/bin/racket --version
Welcome to Racket v7.9.0.4 [cs].
$ ../racket-lang/racket/racket/bin/racket test-submod.rkt
my-dsl/my-proc
$ ../racket-lang/racket/racket/bin/raco exe test-submod.rkt
$ ./test-submod
require: unknown module
module name: (submod '#%mzc:test-submod my-dsl)
context...:
.../TD4/test-submod.rkt:12:0: parse
body of '#%mzc:test-submod
$

When parsed, compiled and run using racket binary, it works as expected.
When parsed and compiled using raco exe, it succeeds without any error
and the resulting binary give aforementioned error.

Any idea where did I get it wrong?


Dominik

Philip McGrath

unread,
Nov 15, 2020, 1:10:07 PM11/15/20
to Dominik Pantůček, racket...@googlegroups.com
I think you’ll need `define-runtime-module-path` or `define-runtime-module-path-index` to alert the executable builder to the dynamic dependency. 

--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/d357eb72-0647-d542-5148-852b9e62c2a2%40trustica.cz.
--
-Philip
Reply all
Reply to author
Forward
0 new messages