我想将变量的值传递给julia中的宏?我尝试了以下但是它没有工作:
macro m(a,b)
@show a,b
ex = quote
$a = eval($b)
end
@show ex
esc(ex)
end
b = 1
@m a $b
输出:
(a, b) = (:a, :($(Expr(:$, :b))))
ex = quote # REPL[20], line 4:
a = eval($(Expr(:$, :b)))
end
ERROR: unsupported or misplaced expression $
答案 0 :(得分:2)
你非常接近! :)
宏也可以有类型注释,它们是在编译时工作的函数,但它们的输入只能是Expr
s,Symbol
s或常量值,即:Int
,宏在调用之前不评估它们的输入,就像调用之前的函数一样,宏在语法上工作。
julia> macro m(a::Symbol, b) # in ths method a should allways be a symbol
# use spaces and parens as needed to delimit and
# group args as needed, not commas in this case
@show a b # or use this: @show(a, b) notice comma here
ex = quote # there is no need to use eval here a macro
$a = $b # will compile and evaluate the returning
end # expression when invoked
@show ex
return esc(ex) # esc will use surrounding scope instead of gensyms
end
@m (macro with 1 method)
不要在宏的主体内部使用eval
,在这种情况下,它位于返回表达式的主体中(有时可能需要这样做,但这不是其中之一)。 / p>
julia> x = 2
2
老实说,我还不知道如何进行类似于@eval
或BenchmarkTools.@btime
工作的宏的插值(应该在手册中解释,我将不得不研究这些宏的代码),但是在这里为您的简单示例调用宏时,您不需要$
。
julia> @m y (x + 1) # parens for grouping, or @m(y, x + 1)
a = :y # :y is a symbol
b = :(x + 1)
ex = quote
#= REPL[17]:4 =#
y = x + 1
end
3
如果您不使用esc
,它将卫生地创建gensym
,在这种情况下,它会使用周围的范围变量。
julia> @m z rand(x, y)
a = :z
b = :(rand(x, y))
ex = quote
#= REPL[17]:4 =#
z = rand(x, y)
end
2×3 Array{Float64,2}:
0.817233 0.623775 0.277464
0.421573 0.443654 0.296359
gensym
看起来像这样:
julia> gensym(:foo)
Symbol("##foo#924")