Why do single-form modules behave differently?

37 views
Skip to first unread message

Sage Gerard

unread,
Jan 2, 2021, 11:26:48 PM1/2/21
to users\@racket-lang.org
Why does Racket handle modules with exactly one form differently?

I ran into a bug where modules in my module language won't expand if the
modules have exactly one form, so I'm just curious.

(Wild guess: It's Racket's way of checking for a shortcut to end expansion earlier)

~slg


Michael MacLeod

unread,
Jan 3, 2021, 12:19:48 AM1/3/21
to Sage Gerard, users\@racket-lang.org
There's an edge case of 'module' when only one form is provided which results in that form being partially expanded to determine if such expansion would lead to a #%plain-module-begin form. Otherwise (more than one form provided) they are wrapped in #%module-begin with no partial expansion occurring.

I think this might be causing the discrepancy you witnessed.


If a single form is provided, then it is partially expanded in a module-begin context. If the expansion leads to #%plain-module-begin, then the body of the #%plain-module-begin is the body of the module. If partial expansion leads to any other primitive form, then the form is wrapped with #%module-begin using the lexical context of the module body; this identifier must be bound by the initial module-path import, and its expansion must produce a #%plain-module-begin to supply the module body. Finally, if multiple forms are provided, they are wrapped with #%module-begin, as in the case where a single form does not expand to #%plain-module-begin.

(This response was adapted from one of my earlier replies to the mailing list. Search racket-users for "perplexed by macro-expansion behavior near #%module-begin" for more context).

Best,
Michael

--
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/OVvZ0OK4_PfyvXCWfuvzDWBM5-ellmDvNmWchVmsCwAJb_rbSZkCkyraakcGsEMSCl2BsLsWtMXFhQcXY75IKhYiYYGQQEI7lVXLgGBbTCc%3D%40sagegerard.com.

Sage Gerard

unread,
Jan 3, 2021, 1:24:10 AM1/3/21
to michael...@gmail.com, us...@racket-lang.org
I know about that. I asked why it was designed that way.


Sent from ProtonMail mobile



-------- Original Message --------

Michael MacLeod

unread,
Jan 3, 2021, 2:40:29 AM1/3/21
to Sage Gerard, us...@racket-lang.org
Oops, sorry about interpreting your question wrong. Unfortunately I don't know the answer to your actual question.

Ryan Culpepper

unread,
Jan 3, 2021, 12:14:25 PM1/3/21
to Michael MacLeod, Sage Gerard, Racket Users List
It's the consequence of two design goals:

1. The `module` form is separate from the `#%module-begin` syntax hook so that the module's initial language can pick the hook macro that controls the entire module body.

2. Racket's primitive syntax is designed so that it can be re-expanded. (The `expand` operation should be idempotent.) Some of Racket's tools (for example, debugging support) work by expanding code, instrumenting it, and then re-expanding, compiling, and running the result. But a `#%module-begin` hook macro can transform the module body in non-idempotent ways, so that hook macro should only be called once. So the answer to "have I already run the module's `#%module-begin` hook?" must be reflected in the fully-expanded syntax of the module.

Ryan


Sage Gerard

unread,
Jan 3, 2021, 5:20:21 PM1/3/21
to Racket Users
Fantastic, thank you

~slg


‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
Reply all
Reply to author
Forward
0 new messages