Roman, Bear in mind that by expanding (square x) to (square x x), that means if someone writes
(square (perform-expensive-computation)) then you will expand it to: (* (perform-expensive-computation) (perform-expensive-computation)) You have to be careful about duplicating inputs in expanded code. A lot of the optimizations you are performing manually will be done by the Racket optimizer anyway; more if you use Typed Racket with optimizations on, and you can always use the Optimization Coach to find more. A lot of the benefits you get from explicit optimization will also come from using define-inline from racket/performance-hint. If you still prefer to manually expand these things, then I suggest something like the following: (require (for-syntax syntax/parse)) (define-syntax (square stx) (define/syntax-parse body #'(* x x)) (syntax-parse stx #:literals [square expt] [(square (square e:expr)) #'(expt e 4)] [(square (expt e:expr n:number)) (define/syntax-parse 2n (* 2 (syntax-e #'n))) #'(expt e '2n)] [(square (expt e:expr n:expr)) #'(expt e (* n 2))] [(square e:expr) #'(let ([x e]) body)] [square #'(lambda (x) body)])) Note that syntax-parse lets you check for numeric inputs in the pattern, and define/syntax-parse lets you bind pattern variables. There isn't a problem with "x" here, because the name is not used as a pattern variable, it's a variable name introduced by the macro everywhere it occurs. If you're unfamiliar with syntax-parse, I encourage you to learn it, but you can always use syntax-case and replace define/syntax-parse with define/with-syntax from the racket/syntax module. On Thu, Jul 11, 2013 at 12:09 AM, Roman Klochkov <kalimeh...@mail.ru> wrote: > I like to make syntax-optimized functions. > > (define-syntax (square stx) > (syntax-case stx (square expt) > [(square (square expr)) #'(expt expr 4)] > [(square (expt expr n)) (if (number? (syntax-e #'n)) > #`(expt expr #,(* > (syntax-e #'n) 2)) > #'(expt expr (* n 2)))] > [(square x) #'(* x x)] > [square #'(lambda (x) (* x x))])) > > So I can write (square (expt x 5)) and have evaluate (expt x 10) and I > can write (map square '(1 2 3)) and it is also works. > > But I dislike to repeate the body of the function in last two cases. > > I tryed > > (define-syntax (square stx) > (let ([body #'(* x x)]) > (syntax-case stx (square expt) > ... > ... > [(square x) body] > [square #'(lambda (x) #`body)])) > > but hygiene prevents me from that: x: unbound identifier in module in: x > How can I bind template body with some variable? Or how to rewrite the > syntax to evade duplication? > > -- > Roman Klochkov > > ____________________ > Racket Users list: > http://lists.racket-lang.org/users > >
____________________ Racket Users list: http://lists.racket-lang.org/users