[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 13:08:16 EDT 2012

On 08/25/2012 10:53 AM, Ryan Culpepper wrote:
> On 08/25/2012 12:19 PM, Neil Toronto wrote:
> I've reordered these a bit:
>> number
>> string
>> bytes
>> character
>> regexp
> In other words, "literal data". But did you check that the '#%datum'
> macro associated with them has the standard meaning? If not, they could
> expand into arbitrary expressions (possibly with side effects)!

A number can expand to an arbitrary expression? How?

And what do you mean by "the '#%datum' macro associated with them"? 
Applied to them?

>> symbol
> Do you mean identifier, as in "it's just a variable reference"? But it
> could be an identifier macro. Or it could be a variable that other parts
> of the code could concurrently mutate. For example, suppose 'match'
> expanded less cautiously than it actually does:
>    (match x [(cons a b) a])
>    =>
>    (if (pair? x) (unsafe-car x) (match-error ....))
> Now suppose that x is a module-level variable that some other thread
> mutates between the 'pair?' check and the 'unsafe-car'.

Right. Typed Racket would actually catch these at compile time, but 
mutation would still break my macros. *sigh*

> If you must do such things, the safest way in general is to fully
> local-expand the expression you want to analyze; that gives you
> something with a known grammar. Now it's feasible to identify literal
> data: it's any 'quote' expression. You don't have to worry about
> identifier macros, but the 'set!' danger remains for any variables that
> you don't completely control the scope of.
> In your specific case, it would also be safe to check whether the
> comparison expression is an identifier free-identifier=? to one of a
> fixed list of known (immutable) variables; if so, it's safe to duplicate.

I think I'll have to go that route.

Thanks for the explanations!

Neil ⊥

Posted on the dev mailing list.