Scott, I see what you're doing now. You're not actually trying to use macro expansion at all; you're just using local-expand to substitute the definition of pred? where it occurs, so that you can make its macro definition also serve as its DSL definition. That's sensible, but local-expand is still doing more than you want it to. That's why I put in all the expansion caveats -- not because you necessarily meant to do full expansion, but because local-expand is pretty explicitly built for full expansion, and always tries to push as far as it can. Any time the caveats about expansion don't apply, local-expand is probably a bigger gun than you need.
Where local-expand is going to bite you is when the definition of pred? uses a macro at its top level. For instance: (define-syntax-rule (pred? x) (or (< x 3) (> x 7))) Here, local-expand is going to expand the use of (or ...), and any macro that (or ...) produces at its top level, until you reach a core form as the main expression, or something you've put in an explicit stop list. That's not what you want, as I understand it -- you only want to expand pred?. So what to do when you want to apply one macro, but not perform general expansion? Extract its transformer using syntax-local-value, and apply it to the expression. You probably also want to apply a syntax mark before and after transformation, just to simulate the base level of hygiene the macro may be relying on. It might not be necessary for simple definitions, but it can't hurt. I wrote up some code that does this, along with a test showing that it won't expand "or" too far. It's also reasonably hygienic -- it won't be confused if someone defines a different macro named "pred?", for example. I don't know if that's a concern, but again, it can't hurt. Anyway, you can find what I wrote here: https://gist.github.com/carl-eastlund/8626893 Carl Eastlund On Fri, Jan 24, 2014 at 1:30 PM, Scott Klarenbach <sc...@pointyhat.ca>wrote: > Just an update, I was able to make this work. > > #lang racket > (require (for-syntax racket/syntax syntax/stx)) > > (define-syntax-rule (pred? x) (> 3 x)) > > (define-for-syntax (recursive-expand stx) > (let loop ([l (syntax->list stx)]) > (cond [(stx-null? l) l] > [(stx-pair? (stx-car l)) > (cons (loop (stx-car l)) (loop (stx-cdr l)))] > [(equal? 'pred? (syntax->datum (stx-car l))) > (local-expand (cons (stx-car l) (loop (stx-cdr l))) 'expression #f)] > ;; this works > [else > (cons (stx-car l) (loop (stx-cdr l)))]))) > > (define-syntax (test stx) > (syntax-case stx () > [(_ x) > (with-syntax ([expanded (recursive-expand #'x)]) > #''expanded)])) > > (module+ test > (require rackunit) > (check-equal? (test (or (< 10 x) (pred? y))) > '(or (< 10 x) (> 3 y)))) > > The code I couldn't figure out last night was: > (local-expand (cons (stx-car l) (loop (stx-cdr l))) 'expression #f)] > > Thanks. > > -- > Talk to you soon, > > Scott Klarenbach > > PointyHat Software Corp. > www.pointyhat.ca > p 604-568-4280 > e sc...@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