Map syntax issue, is it a bug?

Noticed a couple of inconsistencies in tests (that are often written very quickly) and then a bug that had to do with map syntax errors that should never have compiled in the first place.

Hier is a simple example:

iex(1)> %{"key1": "one", "key2" => "two", "key3" => "three"}
** (SyntaxError) iex:1: syntax error before: "key2"

tried to mix “:” with “=>” and got an error, so far all good, now the other way around:

iex(1)> %{"key1" => "one", "key2": "two", "key3": "three"}
%{:key2 => "two", :key3 => "three", "key1" => "one"}

same, but starting with => works, why? Not only that, but it converts the colon keys to atoms while leaving the string key. So that’s an issue that can creep into a longer map (in my case mostly in tests) without compiler noticing.

Should there always be an error if I mix the “:” and “=>” in the same map (or try to implicitly convert string keys to atoms)? Or (less preferred) should it always work and convert the keys? The fact that it works or fails depending on the order doesn’t seem right.

PS Elixir 1.4.1

3 Likes

The syntax foo: bar is a shorthand for {:foo, bar} in most cases and a shorthand for :foo => bar in maps (under the hood, it’s consistently {:foo, bar}), but only when at the end of a map/tuple/list/function call. You’ll notice that things like [foo: 1, 2] don’t work, but [1, foo: 2] translates to [1, {:foo, 2}]. This sugar is only supported for atom keys, so "some atom": bar will be converted to {:"some atom", bar}. There is no bug.

I’m having trouble finding this in the docs, but if it isn’t, we should add it.

6 Likes

@whatyouhide: that’s right and it’s already described:

When the key in a key-value pair is an atom, the key: value shorthand syntax can be used (as in many other special forms), provided key-value pairs are put at the end:

iex> %{“hello” => “world”, a: 1, b: 2}
%{:a => 1, :b => 2, “hello” => “world”}

from: Map module at hexdocs.pm.

3 Likes

@Eiji

%{“hello” => “world”, a: 1, b: 2}

this exaple is ok, but it’s not really the same, here we have explicit atom keys, in my example it’s about string keys that have an incorrect (accidental) colon down the map definition

@whatyouhide thanks, all but the “end of a call” part was clear to me, it’s similar to the case with keyword list as the last parameter of a function then, makes a little more sense this way. Despite things being pretty clear I still find it could work better for my example, where by changing the order I get a map with mixed atom / string keys or an error.

I’m unable to come up with any good ideas though so I’m marking the thread as solved, guess my problem has to do with me disliking all the optional syntax in general :smiley:

1 Like