Balcony on Passeig de Gràcia

Elixir provides MapSet module to handle sets—lists of unique elements (shall I say “arrays” instead of lists here?). They are very handy under many circumstances. During my work on the minor update in Exvalibur, I changed the list I mistakenly used before to be MapSet. And there was a pitfall. Everywhere is the code I used different function clauses for empty list. But MapSet is a module. That said, this code

@spec func(input :: list()) :: :ok | :error
def func([]), do: :error
def func([_ | _]), do: :ok

cannot be easily converted to work with MapSet. MapSet.size/1 is an external function that cannot be used in guards. Of course one might appeal to if as a last resort, but that’d be silly. But hey, MapSet is a struct underneath. And it keeps the values in map field. So yes, we still can use different clauses and guards

@spec func(input :: list()) :: :ok | :error
def func(%MapSet{map: map}) when map_size(map) == 0, do: :error
def func(%MapSet{}), do: :ok

Happy mapsetting!