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

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Thu Sep 5 08:45:01 EDT 2013

4. Use syntax-parse with attributes that do both expansions at the same
time. The automata library does this:
https://github.com/plt/racket/blob/master/pkgs/unstable-pkgs/unstable-lib/automata/re-compile.rkt




On Wed, Sep 4, 2013 at 3:40 PM, Carl Eastlund <cce at ccs.neu.edu> wrote:

> 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>
>>
>
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
>
>


-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130905/1fd4ea9a/attachment-0001.html>

Posted on the users mailing list.