【问题标题】:How to pass a reference to a dynamic function in macro in Elixir?如何在 Elixir 的宏中传递对动态函数的引用?
【发布时间】:2017-05-22 03:15:50
【问题描述】:
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,但我的基准测试表明,使用匿名包装器会显着减慢执行速度。

【问题讨论】:

  • &__MODULE__.unquote(some_dynamic_atom)/0 工作 FWIW。不知道为什么它会在没有模块的情况下引发该错误。

标签: macros elixir


【解决方案1】:

如果你写&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)() end,但我的基准测试表明,使用匿名包装器会显着减慢执行速度。

您是如何进行基准测试的?如果some_dynamic_atom() 什么都不做,而您只测量包装器,那么包装器肯定会变慢。但在由 Task.Supervisor 调用的实际代码中,这无关紧要。

【讨论】:

    猜你喜欢
    • 2016-09-03
    • 2020-07-17
    • 2016-01-08
    • 2018-06-01
    • 1970-01-01
    • 2016-09-05
    • 1970-01-01
    • 1970-01-01
    • 2016-03-24
    相关资源
    最近更新 更多