如何在Elixir中传递对宏中动态函数的引用?

时间:2017-05-22 03:15:51

标签: macros elixir

some_dynamic_atom = :"prefix_#{name}"
quote do
  Task.Supervisor.async_nolink(Tasks.Chain, &unquote(some_dynamic_atom)/0)
end

# Should become

Task.Supervisor.async_nolink(Tasks.Chain, &prefix_smth/0)

我需要在Elixir宏中创建一个动态函数,并将其名称传递给Task

我制作了一个动态函数,但上面的宏给出了一个错误:

invalid args for &, expected an expression in the format of &Mod.fun/arity, &local/arity or a capture containing at least one argument as &1, got: :prefix_smth / 0

一种可能的解决方案是使用fn -> unquote(some_dynamic_atom)() end,但我的基准测试显示,使用匿名包装会显着减慢执行速度。

1 个答案:

答案 0 :(得分:3)

如果你写&unquote(some_dynamic_atom)/0,那么你正在生成&:some_dynamic_atom/0,这不是你想要的。相反,你想要这个:&some_dynamic_atom/0。您可以使用Macro.var将原子转换为变量的AST:

&unquote(Macro.var(some_dynamic_atom, Elixir))/0
  

一种可能的解决方案是使用fn - > unquote(some_dynamic_atom)()结束,但是我的基准测试显示,使用匿名包装会明显减慢执行速度。

您的基准测试方式和内容是什么?如果some_dynamic_atom()什么也没做,而你只是测量包装器,那么包装器肯定会减速。但是在Task.Supervisor调用的实际代码中,它无关紧要。