I am working on a library where, amongst other things, some default modules are called for Elixir’s built-in types like Tuples and Lists.
I do this in a manner similar to how Protocols are internally defined, namely to iterate over a list of {guard, modulename}
and inside this function I can delegate to that other module’s implementation:
defmodule FunLand do
defmodule Builtin do
def __builtin__ do
[is_tuple: FunLand.Builtin.Tuple,
is_atom: FunLand.Builtin.Atom,
is_list: FunLand.Builtin.List,
is_map: FunLand.Builtin.Map,
is_bitstring: FunLand.Builtin.BitString,
is_integer: FunLand.Builtin.Integer,
is_float: FunLand.Builtin.Float,
is_function: FunLand.Builtin.Function,
is_pid: FunLand.Builtin.PID,
is_port: FunLand.Builtin.Port,
is_reference: FunLand.Builtin.Reference]
end
end
end
# Inside one of the Behaviour-defining modules:
for {guard, module} <- FunLand.Builtin.__builtin__ do
def map(mappable, function) when unquote(guard)(mappable) do
unquote(module).map(mappable, function)
end
end
This works, but I am getting a lot of warnings, because not all of the modules inside FunLand.Builtin.__builtin__
will actually define all of the functions that are delegated to them. Things like
warning: function FunLand.Builtin.Atom.map/2 is undefined or private
These warnings are thrown during macro expansion, i.e. after the modules are compiled.
Because I use behaviours, it is impossible to check inside my behaviour-defining modules if the other module defines a certain function (doing things like Enum.member?(ModuleName.__info__(:functions), {:map, 2})
) because this will result in a deadlock of modules waiting for each other’s compilation.
So, I think that the best approach here, is to silence the warning. How can this be done?