Redefining a call expression inside a macro

Edit: In the category of “never mind…” :blush:, the example below does not accurately replicate the problem.
My apologies to those who took time to consider it.

Consider

macro x(expr)
    dump(expr)
    println("------")
    dump(expr.args[1])
    println("======")

    expr.args[1] = :z
end
julia> @x y()
Expr
  head: Symbol call
  args: Array{Any}((1,))
    1: Symbol y
  typ: Any
------
Symbol y
======
UndefVarError: z not defined

Why is expr evaluated when expr.args[1] = :z?

In a macro the return expression is evaluated. So the last line of code expr.args[1] = :z is the return value of the macro, and therefore :z is the expression that is evaluated.

Indeed. In Jupyter the following works.

z()="hello world"

macro x(expr)
    dump(expr)
    println("------")
    dump(expr.args[1])
    println("======")

    expr.args[1] = :z
end
julia> @x y()
Expr
  head: Symbol call
  args: Array{Any}((1,))
    1: Symbol y
  typ: Any
------
Symbol y
======
Out[1]:
z (generic function with 1 method)

But…

Module MyModule
    z()="hello world"

    macro x(expr)
        dump(expr)
        println("------")
        dump(expr.args[1])
        println("======")

        expr.args[1] = :z
    end

    export @x, z
end
julia> using MyModule

julia>   @x y()
UndefVarError: MyModule.z not defined

When I try out both examples, I get the same result for both and no error.

julia> using MyModule

julia> @x y()
Expr
  head: Symbol call
  args: Array{Any}((1,))
    1: Symbol y
  typ: Any
------
Symbol y
======
z (generic function with 1 method)

When I run that, I don’t get the same UndefVarError you got, I get same result as first example.

Hmm…
Thank you for looking into this.
To be continued tomorrow…

Just a sanity check. This

looks like a complicated way to write

macro x(expr)
    return :z 
end

Did you mean

macro x(expr)
    expr.args[1] = :z
    return expr
end

?

2 Likes

@chakravala and @GunnarFarneback, thank you for trying to help out. Unfortunately my “Minimum Working Example” did not accurately recreate the problem. My apology.
Based on your feedback I dug deeper and the actual problem was not where I thought it was. There was another statement (not in the MWE) that evaluated expr.args[1] before returning it. Therefore the evaluation occurred in the wrong context. Problem solved.