简体   繁体   中英

How to pass a reference to a dynamic function in macro in 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)

I need to create a dynamic function in Elixir macro and pass its name to the Task

I made a dynamic function, however the macro above gives me an error:

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

One possible solution is to use fn -> unquote(some_dynamic_atom)() end , but my benchmarks show, that using an anonymous wrapper noticeably slows down the execution.

If you write &unquote(some_dynamic_atom)/0 , you are generating &:some_dynamic_atom/0 , which is not what you want. Instead you want this: &some_dynamic_atom/0 . You can convert the atom to the AST of a variable using Macro.var :

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

One possible solution is to use fn -> unquote(some_dynamic_atom)() end, but my benchmarks show, that using an anonymous wrapper noticeably slows down the execution.

How and what are you benchmarking? If some_dynamic_atom() does nothing and you are measuring just the wrapper then the wrapper will definitely slow down. But in actual code that is invoked by the Task.Supervisor it won't matter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM