[racket] selectively local-expand sub-expressions

From: Carl Eastlund (carl.eastlund at gmail.com)
Date: Thu Jan 23 22:06:59 EST 2014

Scott,

What you're doing isn't possible -- isn't even meaningful -- in general.
You want to expand (MACRO-NAME (pred-a? z) (pred-b? z)) into (MACRO-NAME
(equal? z "hey") (equal? z "there")) for some arbitrary MACRO-NAME you
haven't listed.  That's not at all safe!  For instance, you did it with the
name or.  Well, what if we were in this context...

(define-syntax-rule (or e ...) (quote (e ...)))

Now you're not rewriting equals to equals with respect to the definitions
of pred-a? and pred-b?, you're changing the value of a quoted constant by
rewriting the arguments to or.  Unless you know the macros whose arguments
you're expanding, you don't know which positions in their arguments
represent expressions.  Some positions might be expressions, some might be
binding names, some might be quoted data, some might be other things like
match patterns that have a wholly different meaning.

There's a reason local-expand is as limited as it is.  Macro expansion is
very hard to do inside anything except a fully expanded context.  Usually
when we want to control expansion somewhere else, we either local expand
all the way down, or we delay the effect somehow.  For instance, you might
wrap the expression with let-syntax to rebind the names pred-a? and
pred-b?, shadowing them with macros that do the substitution you want when
expansion naturally reaches them.

Carl Eastlund


On Thu, Jan 23, 2014 at 8:06 PM, Scott Klarenbach <scott at pointyhat.ca>wrote:

> I'm trying use local-expand
>
> (
> http://docs.racket-lang.org/reference/stxtrans.html?q=local-expand&q=local-expand#%28def._%28%28quote._~23~25kernel%29._local-expand%29%29
> )
>
> to partially expand sub-expressions.  The only expressions I want to
> expand are known in advance, I'm just having trouble coming up with an
> elegant recursive algorithm for doing this.
>
> For example:
>
> (define (pred-a? x) (equal? x "hey"))
> (define (pred-b? y) (equal? y "there"))
> (define other-expr (lambda (z) (or (equal? z "you") (pred-a? z) (pred-b?
> z)))
>
> I'd like to expand other-expr like so that:
>
> (expand other-expr) >> (lambda (z) (or (equal? z "you") (equal? z
> "hey") (equal? z "there"))
>
> local-expand sort of works, but provides either too little expansion (#f
> stop-ids) whereby only the outer macro is expanded, or else it provides too
> much expansion (list of stop-ids), whereby "and" and "or" etc is expanded
> into let-values bindings.
>
> What I'd like is something in between.  Rather than a "stop-list", I want
> an "include-list".  I don't want or / and to expand to let-values, but I do
> want any of my special nested expressions (that might be 3 levels deep in
> an or clause) to expand inside the original or.
>
> I figure this is not possible using the built-in functions, and so set out
> trying to build a recursive function that would reconstruct the expression
> and selectively expand the inner procedures I wish by applying local-expand
> to the nested operands.
>
> My question is:
>
> 1.) Is there a simple library way to do this with local-expand that I'm
> missing?
> 2.) Does anyone have a hint or code example to do this manually using
> recursion?  It should be simple enough but I'm embarrassed to admit how
> long I've wrestled with it.
>
> Thanks.
>
> --
> Talk to you soon,
>
> Scott Klarenbach
>
> PointyHat Software Corp.
> www.pointyhat.ca
> p 604-568-4280
> e scott at pointyhat.ca
> 200-1575 W. Georgia
> Vancouver, BC V6G2V3
>
> _______________________________________
> To iterate is human; to recur, divine
>
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140123/aa0676d3/attachment.html>

Posted on the users mailing list.