In elixir we have Maps:
> map = %{:a => \"one\", :b => \"two\"} # = %{a: \"one\", b: \"two\"}
> map.a # = \"one\"
>
The main benefit of keyword lists is a backward compatibility with existing elixir and erlang codebase.
They also adds syntax sugar if used as functions arguments which resembles for e.g. a ruby syntax:
def some_fun(arg, opts \\ []), do: ...
some_fun arg, opt1: 1, opt2: 2
The main drawback of using keyword lists is that it's not possible to perform a partial pattern matching on them:
iex(1)> m = %{a: 1, b: 2}
%{a: 1, b: 2}
iex(2)> %{a: a} = m
%{a: 1, b: 2}
iex(3)> a
1
iex(4)> k = [a: 1, b: 2]
[a: 1, b: 2]
iex(5)> [a: a] = k
** (MatchError) no match of right hand side value: [a: 1, b: 2]
Let's extend it to function arguments. Imagine we need to handle a multiclause function based on a value of one of the options:
def fun1(arg, opt1: opt1) when is_nil(opt1), do: do_special_thing
def fun1(arg, opts), do: do_regular_thing
def fun2(arg, %{opt1: opt1}) when is_nil(opt1), do: do_special_thing
def fun2(arg, opts), do: do_regular_thing
This will never execute the do_special_thing
:
fun1("arg", opt1: nil, opt2: "some value")
doing regular thing
With map arguments it will work:
fun2("arg", %{opt1: nil, opt2: "some value"})
doing special thing