Re: [julia-users] Is it necessary to manually protect global variables from getting clobbered inside a macro?

81 views
Skip to first unread message

Yichao Yu

unread,
Nov 29, 2015, 8:01:30 PM11/29/15
to Julia Users
On Sun, Nov 29, 2015 at 6:35 PM, Ray Toal <ray....@gmail.com> wrote:
> Hi
>
> I have taken the example from the Metaprogramming page on the docs (many of
> you will know it well):

Please finish reading the metaprogramming doc and especially about the
esc function.

>
> macro time(ex)
> return quote
> local t0 = time()
> local val = $ex
> local t1 = time()
> println("elapsed time: ", t1-t0, " seconds")
> val
> end
> end
>
>
> Julia's hygienic behavior works fine in the sense that my global t0 is not
> changed by the assigment to the local t0 within the macro:
>
> julia> t0 = 1
>
> 1
>
>
> julia> @time 1 + 100
>
> elapsed time: 4.0531158447265625e-6 seconds
>
> 101
>
>
> julia> t0
>
> 1
>
>
> HOWEVER, if I use t0 in the expression passed to the macro, the the
> evaluation of my expression gets whacked by the macro:
>
> julia> t0 = 1
>
> 1
>
>
> julia> @time t0 + 100
>
> elapsed time: 4.0531158447265625e-6 seconds
>
> 1.448839743035454e9
>
>
> julia> t0
>
> 1
>
>
> Now my global t0 was not changed (hygiene to the rescue) but I expected to
> get the result 101, not 1.448839743035454e9. When I check the output of
> macroexpand, sure enough the value t0 that I thought was global was replaced
> with the gensymmed value.
>
> So I take it this behavior is expected in Julia. In fact the docs even say:
> "the expressions that are passed into a macro as arguments are often
> expected to evaluate in the context of the surrounding code, interacting
> with and modifying the existing variables." But, but... How am I supposed to
> know that the inside of the macro is using a variable called t0, and that
> I'm not allowed to use t0 on the outside? What if someone changes the inside
> of the macro later and uses a variable that I have currently passed to
> @time?
>
> As I am new to Julia, there is something I likely don't understand here, but
> having a value of one of my variables mixed up with a local inside of a
> macro seems strange. Is this a known situation in Julia that I just was
> unable to find searching the forums? (I am familiar with the behavior in the
> docs that state: "A variable is considered local if it is assigned to (and
> not declared global), declared local, or used as a function argument name.
> Otherwise, it is considered global. Local variables are then renamed to be
> unique (using the gensym() function, which generates new symbols), and
> global variables are resolved within the macro definition environment" and I
> thought I understood it).
>
> If this is a known issue in Julia, how do I work around the fact that I
> might want to call @time with an expression involving variables and I don't
> want my expression's result to be wrong just because it happens to share
> variables with those in the macro body?
>
>
>

Isaiah Norton

unread,
Nov 29, 2015, 9:01:59 PM11/29/15
to julia...@googlegroups.com
how do I work around the fact that I might want to call @time with an expression involving variables and I don't want my expression's result to be wrong just because it happens to share variables with those in the macro body?

Use `esc` in the macro definition. See the example regarding `time` in the hygiene section:

Regarding your question on StackOverflow

The only thing that matters is that non-local variables are not gensym'd  (i.e. variables that are not assigned, not declared local, and not used as an argument name in a function definition). Then the normal lookup rules apply, so in your example, `@g` expands to `f(x) + 5`, and `f` resolves to the local definition (use macroexpand to see that). The wording of that section could probably be improved.

Isaiah Norton

unread,
Nov 29, 2015, 11:10:37 PM11/29/15
to julia...@googlegroups.com
Actually, I misunderstood the problem. This looks like an open issue:
Reply all
Reply to author
Forward
0 new messages