I have the following design pattern: I have an elixir module, that responds to growing/changing amount of functions/0
, called Defaults
. I have also CustomConfig
module, that is basically the struct, deriving defaults and assumed to be instantiated like:
%CustomConfig{ foo: "bar" }
where initialized properties are overwritten, others are taken from Defaults
and those, not having a function with the same name in Defaults
are rejected. So far, so good.
To implement this behaviour independent on content (the list of functions in Defaults
,) I use a macro (in other module, since one can not use macro, defined in the same module, within struct declaration):
defmacro define_struct_with_defaults do
quote do
defstruct Map.to_list(
quote do: unquote(Enum.reduce(Dict.keys(
Defaults.__info__(:functions)), %{}, fn(k, acc) ->
Map.put(acc, :"#{k}", apply(Defaults, :"#{k}", []))
end)))
end
end
While this works fine, I am pretty sure, that there should be more straightforward/elegant/less-cumbersome way to achieve this functionality.
So my question would be: how one could declare defstruct
from the Map
without dancing this paso doble around map-reduce?