I’m having a weird matching problem. I’m handling complex numbers using the ComplexNum library. This library defines two types of complex number, ComplexNum.Cartesian
and ComplexNum.Polar
, but I only use the Cartesian variety. So I have following set up (showing only the relevant bits):
defmodule TopLevel
alias ComplexNum.Cartesian, as: Complex
defmodule SubModule
defp convert(v) do
Logger.debug(inspect v)
case v do
s when is_binary(s) -> {:ok, s}
i when is_integer(i) -> {:ok, i}
f when is_float(f) -> {:ok, f}
c = %Complex{} -> {:ok, c}
ms = %MyStruct{} -> convert_my_struct(ms)
# some other clauses omitted
%{} -> convert_map(v)
# some other clauses omitted
_ -> {:error, :not_implemented}
end
end
defp convert_map(v) do
# Use reduce_while to bail if errors inside the map
Enum.reduce_while(v, acc, fn {key, value}, acc ->
# details omitted
end)
# details omitted
end
end
end
When convert()
is called with a Complex
during testing, the match clause against the Complex
alias fails, and the more generalised match against a map is triggered, leading to an error in convert_map()
:
10:57:28.797 [debug] #ComplexNum (Cartesian) <2.0·𝑖>
1) test test_name (SomeTest)
test/some_test.exs:9124
** (Protocol.UndefinedError) protocol Enumerable not implemented for #ComplexNum (Cartesian) <2.0·𝑖> of type ComplexNum (a struct). This protocol is implemented for the following type(s): MapSet, HashSet, Range, Function, HashDict, File.Stream, GenEvent.Stream, List, Stream, IO.Stream, Date.Range, Map
code: Enum.each(test_cases, fn tcase ->
stacktrace:
(elixir) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir) lib/enum.ex:141: Enumerable.reduce/3
(elixir) lib/enum.ex:1998: Enum.reduce_while/3
Note that when a MyStruct
is passed, the correct match clause is triggered and convert_my_struct()
called.
I’ve used the alias in other contexts without problems, so I don’t think it’s that. Can anyone point out what is causing the match clause against %Complex{}
to fail? Thanks.