2017-12-26 15 views
1

Ich möchte den Wert einer Variablen an ein Makro in Julia übergeben? Ich habe versucht, die folgenden, aber es hat nicht funktioniert:Wie übergibt man Variablenwerte an ein Makro in Julia?

macro m(a,b) 
    @show a,b 
    ex = quote 
    $a = eval($b) 
    end 
    @show ex 
    esc(ex) 
end 

b = 1 
@m a $b 

Ausgang:

(a, b) = (:a, :($(Expr(:$, :b)))) 
ex = quote # REPL[20], line 4: 
    a = eval($(Expr(:$, :b))) 
end 
ERROR: unsupported or misplaced expression $ 

Antwort

2

Sie waren ganz in der Nähe! :)

Makros können auch Typenannotationen haben, sie sind Funktionen, die bei der Kompilierung arbeiten, aber ihre Eingänge können nur Expr s, Symbol s oder konstante Werte sein, das heißt: Int, Makros auswerten nicht ihre Eingaben, bevor sie Wie Makros vor dem Aufruf aufgerufen werden, arbeiten Makros an der Syntax.

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) 

in diesem Fall nicht in dem Körper es des zurückgegebenen Ausdrucks Verwenden Sie eval im Innern des Körpers eines Makros, (es gibt Fälle, wenn dies notwendig sein könnte, aber das ist nicht einer von ihnen).

julia> x = 2 
2 

Ehrlich gesagt weiß ich noch nicht, wie Einschübe zu Makros wie @eval oder [email protected] Arbeit ähnlich zu machen (sollten im Handbuch erklärt werden, werde ich den Code dieser Makros studieren müssen), aber Sie don‘ t brauchen $ beim Aufruf des Makros hier für Ihr einfaches Beispiel.

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 

Wenn Sie nicht esc verwenden es gensym s hygienisch schaffen, in diesem Fall ist es die umgebenden Umfang Variablen verwendet stattdessen.

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 s sieht wie folgt aus:

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

Danke für die Erwähnung '@ eval' und' BenchmarkTools @ btime'.. Ich würde gerne Ähnliches machen, habe aber ihren Code noch nicht verstanden. – Phuoc

+0

Überprüfen Sie auch [MacroTools.jl] (https://github.com/MikeInnes/MacroTools.jl) – SalchiPapa

Verwandte Themen