0
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.

1
  • &__MODULE__.unquote(some_dynamic_atom)/0 works FWIW. Not sure why it throws that error without module. Commented May 22, 2017 at 5:06

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.