Are Keyword lists restricted to atoms of a given type?

I can create a keyword list only with an atom of type :atom, but not Foo. Why is that?

iex(1)> [foo: "bar"]
[foo: "bar"]
iex(2)> is_atom(Foo)
iex(3)> [Foo "bar"]
** (SyntaxError) iex:3: syntax error before: "bar"
1 Like

yes, keyword is internally alist of tuples where first element is atom, second value. If you want different type as keys, you need to use something lime Map.

1 Like

To rephrase slightly, if :foo and Foo are both atom, why doesn’t the latter work in a Keyword list?

1 Like

Of course you can use Foo as keyword in a Keywordlist, but you do not have syntactic sugar then (or you have to spell it out)

iex(1)> [{Foo, "bar"}]
[{Foo, "bar"}]
iex(2)> ["Elixir.Foo": "bar"]
[{Foo, "bar"}]
iex(3)> Keyword.fetch(v(2), Foo)
{:ok, "bar"}

you can,
you need to use the semi-colon

iex> [Foo: “bar”]
[Foo: “bar”]

1 Like

This one renders the first term as :Foo however.

iex(1)> kw = [Foo: "bar"]
[Foo: "bar"]
iex(2)> Keyword.get(kw, :Foo)
iex(3)> Keyword.get(kw, Foo) 

I got @NobbZ 's approach I got to work.

iex(6)> kw = [{Foo, "bar"}]
[{Foo, "bar"}]
iex(7)> Keyword.get(kw, Foo)
iex(8)> is_atom(Foo)

Thanks everyone!

1 Like

Foo is a shorthand for Elixir.Foo
that is why it doesn’t work


There is a slight difference between Foo and :Foo! The first is an alias which expands to an atom prefixed by :Elixir. but the exact name depends on the context. :Foo on the other hand will not be expanded to anything but is always the same value regardless of context.

defmodule A do
  alias Foo, as: Bar
  def check(Bar), do: true
  def check(_), do: false

IO.puts A.check(Foo) #=> true
IO.puts A.check(Bar) #=> false

That code looks a bit clunky though and is untreated since I’m on my mobile right now.

edit: Tested and repaired the example.


No, for :"Elixir.Foo" or whatever else you alias it to…

1 Like

ah yes, sure. As others suggested you can do that but it sort of looses the appeal if you do that without syntactic sugar this way.

1 Like