如何将变量值传递给julia中的宏?

时间:2017-12-26 10:45:53

标签: macros julia

我想将变量的值传递给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 $

1 个答案:

答案 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

老实说,我还不知道如何进行类似于@evalBenchmarkTools.@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")