2015-06-19 4 views
7

Perché questo lavoro:Julia macro splatting

function test_func(a, b) 
    a + b 
end 

test_func((1, 2)...) 

Ma questo non lo fa?

macro test_func(a, b) 
    a + b 
end 

@test_func((1, 2)...) 

È un bug in Julia?

risposta

10

Macro operano sulla sintassi di superficie , pertanto @test_func non visualizza il risultato dello splat. Invece, vede l'operazione di splat stessa! Come sempre, un ottimo modo per controllare questo è di citare e vedere esattamente ciò che sintassi della macro è in funzione il:

julia> :(@test_func((1,2)...)) 
:(@test_func (1,2)...) 

julia> Meta.show_sexpr(ans) 
(:macrocall, symbol("@test_func"), (:..., (:tuple, 1, 2))) 

Quindi la macro sta ricevendo un argomento (non due), ed è un Expr(:..., Expr(:tuple, 1, 2)). Si noti che la tupla (1,2) è passata alla macro, ma è nascosta all'interno dell'operazione di splat. Così si potrebbe scavare nel Expr e tipo-di-tipo-di implementare Splatting te stesso:

julia> macro test_func(as...) 
      if length(as) == 1 && isa(as[1], Expr) && as[1].head == :... && 
        isa(as[1].args[1], Expr) && as[1].args[1].head == :tuple 
       a, b = as[1].args[1].args 
      elseif length(as) == 2 
       a, b = as 
      else 
       error("unsupported syntax $as") 
      end 
      return esc(:($a + $b)) 
     end 

julia> @test_func((1,2)...) 
3 

Ma questo solo tipo-di-tipo-di supporti splatting. Guardate cosa succede se si tenta di operare su una variabile invece:

julia> @test_func(xs...) 
ERROR: unsupported syntax (:(xs...),) 

ora non c'è alcun modo per la macro per sapere quello che dovrebbe essere l'aggiunta insieme!