Sujet : Re: infix via code walker hook.
De : 643-408-1753 (at) *nospam* kylheku.com (Kaz Kylheku)
Groupes : comp.lang.lispDate : 02. Apr 2025, 04:26:20
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <20250401201007.528@kylheku.com>
References : 1
User-Agent : slrn/pre1.0.4-9 (Linux)
On 2025-03-31, Kaz Kylheku <
643-408-1753@kylheku.com> wrote:
(defmacro ifx (:env env . body)
(let ((*expand-hook* (fun infix-expand-hook)))
(expand ^(progn ,*body) env)))
Doh! I just though of expander-let which can do this nicely.
And ... it turns out I already developed it! expander-let
appeared in TXR 287, in June 2023. (Current is 299).
Thus:
(defmacro ifx (. body)
^(expander-let ((*expand-hook* (fun infix-expand-hook)))
,*body))
That is way better. The expander encounters the expander-let and does
the binding for us, wraps the body in a (progn ...) and naturally
recurses over it. Then the expander-let disappears.
The explicit expand call causes a wasteful double expansion; whatever it
produces will be recursed into by the expander again.
Arguably, this design is wrong because, the binding for expand hooks
should ideally be in the macro environment, not in the dynamic
environment. If a closure is ever produced that captures a macro
environment, and does form expansion when called, it may not have the
correct value of *expand-hook* that was in effect. Also, categorically,
local expander hooks are kind of generalized macrolets, and therefore
belong in the same space.
There is the obvious workaround in that the scope around the closure can
just copy the then-visible dynamic value of *expand-hook* into a lexical
variable, and capture that. It's an ugly ritual to have to remember,
and to have to carry out for correctness, though.
-- TXR Programming Language: http://nongnu.org/txrCygnal: Cygwin Native Application Library: http://kylheku.com/cygnalMastodon: @Kazinator@mstdn.ca