ConstantBall
Why do Elixir maps have an update syntax but no insert syntax, meanwhile Erlang has both?
We all know that we’re able to build a map using the literal syntax using %{key1 => value1, key2 => value2}, as well as update existing keys of a map with %{map | key2 => new_value2}. But what reason could there be for not allowing us to insert new key-value pairs into a map using the literal syntax?
Inserting and updating are both supported (simultaneous) operations in Erlang using the literal syntax where the update is denoted by the := operator and insertion by the => operator.
So what is stopping Elixir from having something analogous?
Marked As Solved
josevalim
I frequently struggle to remember when to use which operator in the Erlang syntax. So my goal was to introduce syntax for the struct-like API (i.e. you expect the keys exist and you can only update them) and leave the dictionary-like API (adding and removing keys) in the Map module. So you can do Map.put/3 to add, Map.delete/2 and so on.
Also Liked
josevalim
It is not a case common enough to prioritize, in my opinion, at the cost of having additional syntax for it. You may agree or disagree, but that’s the rationale. ![]()
Erlang also allows multiple keys to be given and you can add and update several keys at once.
I personally think the question has been answered, so it is probably a good time to wrap it up. ![]()
dimitarvp
If I was a language maintainer, my problem with such proposals would be that introducing syntax is a slippery slope that might never end.
So you would like to have a map inserting syntax. Cool. That’s reasonable, and I found myself wanting that in the past as well. But then somebody else comes along and says “Hey, what about a new syntax as a shortcut for Map.put_new and Map.put_new_lazy as well? I use these every day in my work!”. And you will find yourself in the very uncomfortable situation of having to explain why introducing new syntax X is reasonable but syntax Y is not.
(And let’s not even mention the maintenance burden of every new syntax, which is a very long topic by itself, but suffice to say they carry non-trivial opportunity costs.)
I agree with you that Elixir’s current choices and their tradeoffs might seem inconsistent for a newcomer or an outsider but I believe I speak for many people when I say that I’d still prefer knowing those choices and tradeoffs – and them being a reasonably low number – than to have more and more syntax that absolutely will confuse everyone but the biggest syntax advocates (and I’d argue they are likely below 1% of the language’s user base).
Elixir has quirks. All languages do. ¯_(ツ)_/¯ Elixir’s are not many though and are thus graspable and can easily be worked around.
sabiwara
Just for the record, I tried a quick benchmark to make sure we weren’t missing out any performance benefit compared to multiple Map.put/3 calls or a Map.merge/2: turns out all of these approaches are equivalent performance wise (so nothing to be gained on this front).
josevalim
If there was, it was a long time ago, before 1.0, on the elixir-lang-core mailing list.
Nicd
Structs always have all defined keys present, so inserting a new key into a struct doesn’t make sense and shouldn’t be a supported use case. This would mean the syntax is only for maps — for structs it would be (1) equivalent to the update syntax when using the form %Struct{struct | new_key => new_val}, and (2) would be able to break structs when using the form %{struct | new_key => new_val} (i.e. without compile time validation of keys).
Map.put can be used to break structs already, but at least it’s in the Map module which hints that it’s not the first tool to use for structs.








