[racket] Macro design question: best way to interpret an expression multiple ways

From: Carl Eastlund (cce at ccs.neu.edu)
Date: Wed Sep 4 17:40:51 EDT 2013

I see three options, off the top of my head:

1. Expand into a lambda that takes the different functions, such as >>> and
&&&, as arguments; then apply that function in one place to the /pre
variants and in another place to the /bot variants.

2. Expand into one expression, and make &&& and >>> into parameter values;
set them differently on two different calls.

3. If &&& and >>> need to be macros themselves for some reason, then you
may really have two different interpretations here that must be expanded
separately.  Sometimes you just have to do work twice.  Although you may be
able to save yourself some of that with judicious local-expansion... but
that's probably more trouble than it's worth.  Also, unless "interp" is
likely to be nested, simply expanding twice is unlikely to cause a
significant problem.  Sometimes it's okay to have a single, limited source
of macro duplication.

Carl Eastlund


On Wed, Sep 4, 2013 at 5:31 PM, Neil Toronto <neil.toronto at gmail.com> wrote:

> I have two libraries of combinators meant to be used as targets for a
> language semantics. I'm implementing the semantics using macros; e.g.
>
>    #'(interp (+ 4 5))  =>  #'(((const 4) . &&& . (const 5)) . >>> . add)
>
> where `interp' is a macro and `=>' means macro expansion.
>
> Here's the tricky part. I have to interpret the language using *both*
> combinator libraries, not just one; e.g. I need #'(interp (+ 4 5)) to
> expand to both of these:
>
>   #'(((const/bot 4) . &&&/bot . (const/bot 5)) . >>>/bot . add/bot)
>   #'(((const/pre 4) . &&&/pre . (const/pre 5)) . >>>/pre . add/pre)
>
> I could have #'(interp (+ 4 5)) expand to something like
>
>   #'(list (interp/bot (+ 4 5)) (interp/pre (+ 4 5)))
>
> But expanding twice is terrible manners when the expression contains
> macros.
>
> (Originally, I had super-combinators that did the job of both */bot and
> */pre combinators. These super-combinators were complicated and messy,
> especially when used in recursion, which is why I'm moving the "interpret
> the language two ways" job into the macro system and hoping it's nicer. It
> should also generate faster code, and possibly allow type checking on one
> of the interpretations.)
>
> The best idea I've had so far is to have (interp e) expand to uses of
> generic `&&&' and `>>>' combinators, apply `local-expand', and do a syntax
> tree search-and-replace that does #'&&& => #'&&&/bot, etc. Is there another
> way, though, that doesn't run afoul of macro security?
>
> Neil ⊥
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/**users <http://lists.racket-lang.org/users>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130904/e4d64110/attachment.html>

Posted on the users mailing list.