[racket-dev] When is it safe to not rename a runtime value in a macro?

From: Neil Toronto (neil.toronto at gmail.com)
Date: Sat Aug 25 22:07:05 EDT 2012

Investigated a bit today. I wrote a function that optimizes kernel 
syntax, making these kinds of replacements:

   (let-values ([(x:id)  y:id]) body)
   (let-syntaxes+values ([(x)  (make-rename-transformer #'y)]) () body)

and then fully expanding the code again. It also does simple beta 
reduction, by changing ((lambda (x ...) body ...) e ...) into a 
`let-values'. I've managed to shave 1/4 the runtime off simple things 
like this:

   (let ([y 4])
     ((lambda (x)
        (let ([z y])
          (+ x z)))

It doesn't correctly handle variables that get mutated, but having it 
search their lexical scope for `set!' should do it. I think.

It hasn't been too bad so far.

Neil ⊥

On 08/25/2012 11:03 AM, Matthias Felleisen wrote:
> It's the wrong way to go. Let's investigate more before we jump to conclusions.
> On Aug 25, 2012, at 12:54 PM, Neil Toronto wrote:
>> Then I suppose the obvious thing to do is move the optimizations up to the macro level? :)
>> It's also for debugging, by the way. Having to mentally or manually substitute bindings to understand fully expanded code annoys me and wastes time.
>> Neil ⊥
>> On 08/25/2012 10:24 AM, Robby Findler wrote:
>>> This is definitely a macro writer bill of rights situation. Too bad
>>> that TR's optimizer cannot take advantage of all these kinds of things
>>> that are already happening in the optimizer one level down.
>>> Robby
>>> On Sat, Aug 25, 2012 at 11:19 AM, Neil Toronto <neil.toronto at gmail.com> wrote:
>>>> A lot of macros start by renaming some syntax that's assumed to eventually
>>>> represent a runtime value, like the `or' macro does:
>>>>> (syntax->datum (expand-syntax #'(or #t #f)))
>>>> '(let-values (((or-part) '#t)) (if or-part or-part '#f))
>>>> But it's not always a good thing, particularly when the output will be
>>>> processed by another macro, and parts will be tested using an `identifier=?'
>>>> function. For example, my `inline-sort' takes `<' as an argument. So
>>>>    (inline-sort < a b)
>>>> expands to
>>>>    (let ([lt? <] [temp1 a] [temp2 b])
>>>>      (if (lt? temp1 temp2) (values temp1 temp2) (values temp2 temp1)))
>>>> Well, it did at first. When I discovered that Typed Racket's optimizer would
>>>> never detect that `lt?' is actually `<' and replace it with `unsafe-fl<', I
>>>> altered the macro to detect when the `<' is an identifier, and not rename it
>>>> with a `let'.
>>>> I know that I should assert my rights under the Macro Bill. But I like to
>>>> program defensively. So what's safe to not rename? I think the following
>>>> are:
>>>> symbol
>>>> number
>>>> string
>>>> bytes
>>>> null
>>>> character
>>>> regexp
>>>> prefab struct key
>>>> Also, should I ever have to intern syntax that's one of these kinds of
>>>> things?
>>>> Neil ⊥
>>>> _________________________
>>>>   Racket Developers list:
>>>>   http://lists.racket-lang.org/dev
>> _________________________
>> Racket Developers list:
>> http://lists.racket-lang.org/dev

Posted on the dev mailing list.