[racket] Macro + function automation
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 <cce at 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 < kalimehtar at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130711/7d9f9d6c/attachment-0001.html>