[racket] Macro + function automation

From: Roman Klochkov (kalimehtar at mail.ru)
Date: Thu Jul 11 01:49:05 EDT 2013

 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>

Posted on the users mailing list.