It's common to have constants as Module Attributes in Elixir. I've tried to pass module attributes as arguments to different macros from different libraries (that usually define a new module):
defmodule X do
@data_types [:x, :y, :z]
@another_constant "some-constant-value"
defenum DataType, :type, @data_types
end
Here's another example of passing module attributes as an argument to a Macro
But almost always get an error along the same lines:
** (Protocol.UndefinedError) protocol Enumerable not implemented for {:@, [line: 26], [{:types, [line: 26], nil}]}
So I usually end up repeating the values:
defmodule X do
@data_types [:x, :y, :z]
@another_constant "some-constant-value"
defenum DataType, :type, [:x, :y, :z]
end
I know repeating them most of the time isn't usually a big deal, but I would really like to know how would I be able to pass the value of a module attribute to a macro.
This is especially apparent in macros that define new modules (like Amnesia
and EctoEnum
).
So far I've tried a bunch of things, including:
- Expanding the value using the
Macro
module - Evaluating the value using
Code
module - Fetching the value using
Module.get_attribute/2
- Trying different variations of quote/unquote calls
But nothing has worked. I have a feeling the macro needs to be written in a way that it can read them. If so, how should the macro be written for it to work?