Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Julia macro splatting

Tags:

julia

Why does this work:

function test_func(a, b)
  a + b
end

test_func((1, 2)...)

But this does not?

macro test_func(a, b)
  a + b
end

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

Is it a bug in Julia?

like image 715
bramtayl Avatar asked Jun 19 '15 23:06

bramtayl


1 Answers

Macros operate on surface syntax, so @test_func isn't seeing the result of the splat. Instead, it sees the splat operation itself! As always, a great way to inspect this is to quote it and see exactly what syntax the macro is operating on:

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

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

So the macro is only receiving one argument (not two), and it's an Expr(:..., Expr(:tuple, 1, 2)). Notice that the tuple (1,2) is getting passed to your macro, but it's just hidden away inside the splat operation. So you could dig into the Expr and kind-of-sort-of implement splatting yourself:

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

But this only kind-of-sort-of supports splatting. Look what happens if you try to operate on a variable instead:

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

There's now no way for the macro to know what it should be adding together!

like image 162
mbauman Avatar answered Dec 06 '22 03:12

mbauman