Hi
I have taken the example from the Metaprogramming page on the docs (many of
you will know it well):
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?