2017-12-26 31 views
1

私は変数の値を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 $ 

答えて

2

あなたは非常に接近していました!

マクロがあまりにも型注釈を持つことができます:)、彼らはコンパイル時に働く機能ですが、それらの入力だけExpr秒、Symbol秒または定数値、すなわちことができます: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を使用しないでください(そこにこれが必要になることができた例はあるが、これはその一つではありません)。正直なところ、私は @evalまたは [email protected]仕事のようなマクロに似て補間を作る方法をまだ知らない(マニュアルで説明されなければならない、私はこれらのマクロのコードを勉強する必要があります)

julia> x = 2 
2 

、しかし、あなたはドン」あなたの簡単な例のためにここでマクロを呼び出すときは、$が必要です。

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 Sを作成します。このような

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の表情: `@ eval`と` BenchmarkToolsに言及するため

julia> gensym(:foo) 
Symbol("##foo#924") 
+1

感謝@ btime'。私は似たようなことをしたいが、まだ彼らのコードを理解していない。 – Phuoc

+0

[MacroTools.jl](https://github.com/MikeInnes/MacroTools.jl)も必ずチェックしてください。 – SalchiPapa

関連する問題