Mapsets are said to be the “go-to” set structure in Elixir, yet they offer none of the pattern match beauty afforded to our other base data structures Maps, Lists and Tuples. I assert that this is the main reason they are under utilized, and often overlooked.
What could sets look like if they had those features?
iex> %[]
%[]
iex> enum = [:foo, :bar, "set"]
...> set = %[enum]
...> set
%[:foo, :bar, "set"]
iex> set = %[:foo, :bar, "set"]
...> %[set | :foo] # no-op
%[:foo, :bar, "set"]
iex> %[set | :foo, :buzz, %Bang{}]
%[:foo, :bar, "set", :buzz, %Bang{}]
iex> %[set | set]
%[:foo, :bar, "set", %[:foo, :bar, "set"]]
iex> term = [%Bang{}, :foo]
...> %[term | set]
%[:foo, :bar, %Bang{}, "set"]
iex> Enum.into(term, set)
%[:foo, :bar, %Bang{}, "set"]
iex> def function_1(%[]), do: :match
...> def function_1(_), do: :error
...> %[:foo, :bar, "set"]
...> |> function_1()
:match
iex> def function_2(%[:foo]), do: :match
...> def function_2(_), do: :no_match
...> %[:foo, :bar]
...> |> function_2()
:match
iex> %[:bar]
...> |> function_2()
:no_match
iex> def function_3(%[:foo, %User{} = user]), do: user.id
...> %[:foo, %User{id: 1}]
...> |> function()
1
Mapsets feel incomplete. Aesthetics matter, and this would bring MapSets in line with our other data structures.
Some comments when this was brought up are below
Mapset is just a map under the skin.
Does that matter? A range also has this trait but has at least some of these affordances mentioned.
Because you cannot create a type in Erlang.
Do we need to? Can the elixir compiler convert %[:foo]
into %{map: %{:foo => []}}
?
I am happy to work on this if its a desired feature. Any and all direction is welcome.