Thank you. You answer is very useful. > You have to be careful about duplicating inputs in expanded code.
I thought, that hygiene implies not only cl:gensym, but also once-only. Is there something like http://common-lisp.net/project/cl-utilities/doc/once-only.html in Racket? > A lot of the benefits you get from explicit optimization will also come from >using define-inline from racket/performance-hint. Do you think, that Racket will do pure calculations in compile-time? For example, if I write (+ x (* 2 3 4) (sin 20)) will it be optimized to (+ x 24.912945250727628) ? Or I have to use define-syntax to do it? Четверг, 11 июля 2013, 0:26 -04:00 от Carl Eastlund <c...@ccs.neu.edu>: >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 >> > -- Roman Klochkov
____________________ Racket Users list: http://lists.racket-lang.org/users