Julia cogeneration with global function
julia 0.5.1
I want to create a function inside a quote that can be used after using the specified macro. Here is an example of what I mean
macro wat()
quote
type Foo end
global bar() = begin end
global function bar2()
end
type Baaz end
end
end
@wat
Foo()
Baaz()
bar()
bar2()
Now when I run this, the last line is out of order because bar2 is undefined. I don't understand why, since in my understanding bar () and bar2 () should be equal and bar is just syntactic sugar for bar2. But they don't seem to be equal and I don't understand why it works and the other doesn't.
Second, is there a way to define bar and bar2 inside this quote without the global keyword and still available after the macro is executed?
The motivation for the bar2 notation is that I can specify the return type with this syntax.
global bar3()::Void = begin end
Syntax not allowed.
source to share
In the returned expressions of Julia macros, local variable names are replaced with unique symbols:
julia> macro foo()
quote
x = 1
global y = 2
end
end
@foo (macro with 1 method)
julia> macroexpand(:(@foo))
quote # REPL[1], line 4:
#1#x = 1
global y = 2
end
This feature is called macrosagy and allows you to avoid accidental collisions with variables on the call site.
To avoid this behavior, use esc
:
julia> macro bar()
quote
x = 1
end |> esc
end
@bar (macro with 1 method)
julia> macroexpand(:(@bar))
quote # REPL[1], line 3:
x = 1
end
It is often not necessary to avoid the entire returned expression, but only its individual parts:
julia> macro myshow(expr)
quote
x = $(esc(expr))
println($(string(expr)), " = ", x)
x
end
end
@myshow (macro with 1 method)
julia> x = pi/2
1.5707963267948966
julia> macroexpand(:(@myshow sin(x)))
quote # REPL[1], line 3:
#1#x = sin(x) # REPL[1], line 4:
(Main.println)("sin(x)", " = ", #1#x) # REPL[1], line 5:
#1#x
end
julia> @myshow sin(x)
sin(x) = 1.0
1.0
julia> x
1.5707963267948966
For more details, I recommend reading the corresponding section in the manual.
source to share