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
,但我的基准测试显示,使用匿名包装会显着减慢执行速度。
答案 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调用的实际代码中,它无关紧要。