Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scope of expressions and variables in Julia macro in modules

For some reason, I had to put quote...end block in the macro and ex is generated programmatically. This code works.

macro addsum_out()
  quote
    ex = :(x+y)
    sum(eval(ex))
  end
end

x = [1 1 1]
y = [2 2 2]

z2 = @addsum_out

When the macro is put inside a module, it no longer works:

module MyModule

export @addsum

macro addsum()
  quote
    ex = :(x+y)
    sum(eval(ex))
  end
end

end

using MyModule
x = [1 1 1]
y = [2 2 2]    
z = @addsum

It says:

ERROR: LoadError: UndefVarError: x not defined

I think I should put esc somewhere, to evaluate the expression ex in the main scope outside the module. What should I handle this?

like image 232
Chang Avatar asked Feb 17 '17 13:02

Chang


People also ask

What is the scope of a variable?

In simple terms, scope of a variable is its lifetime in the program. This means that the scope of a variable is the block of code in the entire program where the variable is declared, used, and can be modified.

What is metaprogramming in Julia?

Meta-programming is when you write Julia code to process and modify Julia code. With the meta-programming tools, you can write Julia code that modifies other parts of your source files, and even control if and when the modified code runs. In Julia, the execution of raw source code takes place in two stages.

What are macros in Julia?

Answer: Macros are sort of functions which take as input unevaluated expressions. ( Expr ) and return as output. another expression, whose code is then regularly evaluated at runtime. This post isn't a. substitute for reading the section about macros in the Julia.

What is quote in Julia?

This is referred to as quoting. The : character, followed by paired parentheses around a single statement of Julia code, produces an Expr object based on the enclosed code. Here is an example of the short form used to quote an arithmetic expression: julia> ex = :(a+b*c+1) :(a + b * c + 1) julia> typeof(ex) Expr.


1 Answers

The problem here is that a macro (inside a module) referencing x will look for x in that module, e.g. MyModule.x

This is part of macro hygiene.

To prevent macro hygiene from happening, you need to esc(x) -- that means it will use whatever x is in-scope at the call-site.

Your complete solution might look like:

macro addsum_out()
  quote
    esc(x) + esc(y)
  end
end

or more concisely:

macro addsum_out()
  :(  esc(x) + esc(y)  )
end

Note that this is slightly different from doing esc( :(x+y) ) which would be a escaping the + function also. i.e. the module containing this macro might contain an overload for +, and if you want to use this then don't escape the +, otherwise do!

There is a little discussion about this subject in a guide I put together:
https://github.com/p-i-/MetaGuideJulia/wiki#example-swap-macro-to-illustrate-esc

like image 55
P i Avatar answered Sep 21 '22 18:09

P i