[racket-dev] When is it safe to not rename a runtime value in a macro?
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)))
5))
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
>