2015-06-19 129 views
7

爲什麼這個工作:朱莉婭宏觀潑灑

function test_func(a, b) 
    a + b 
end 

test_func((1, 2)...) 

但是,這不?

macro test_func(a, b) 
    a + b 
end 

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

這是Julia的錯誤嗎?

回答

10

宏操作曲面語法,所以@test_func沒有看到圖示的結果。相反,它會看到圖示操作本身!與往常一樣,檢查一個很好的辦法就是引用一下,看看到底是什麼語法宏的工作:

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

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

所以宏只接受一個參數(而不是兩個),它是一個Expr(:..., Expr(:tuple, 1, 2))。注意元組(1,2)傳遞給你的宏,但它只是隱藏在splat操作中。所以,你可以深入到Expr和親切-的排序-的實施潑灑自己:

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 

但這僅支持一種-的排序-的潑濺。看看如果你嘗試在一個變量上操作,會發生什麼:

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

現在沒有辦法讓宏知道它應該加在一起了!