Updating a map's values that are lists

Not remotely? Stream’s are just a function composition pattern that is common in most languages (built in to the very fabric of some like Haskell) but are entirely non-opaque.

Syntax sugar that turns a: 1 into {:a, 1} (though the fact you can’t freely intermix those constantly drives me crazy).

Syntax sugar that turns that in to fn a -> a*a end, a useful and common shortening for something very commonly used.

Elixir has plenty of inconsistent bits in it’s syntax, and other than the ordering of a: 1 things none of the above is that. :slight_smile:

It’s trivial to make your own yeah, though I too always preferred if the initial in update/4 was actually the default passed in so I can properly dynamically create either the start or the next in the function without incurring a cost on initial potentially unused construction every call.

irb(main):001:0> h = Hash.new {|hash, key| hash[key] = []}
=> {}
irb(main):002:0> h.has_key?(:a)
=> false
irb(main):003:0> h[:a]
=> []
irb(main):004:0> h.has_key?(:a)
=> true
irb(main):005:0> g = Hash.new([])
=> {}
irb(main):006:0> g.has_key?(:a)
=> false
irb(main):007:0> g[:a]
=> []
irb(main):008:0> g.has_key?(:a)
=> false
irb(main):009:0>

I think it needs to be said that Hash is an object - where behaviour and data are complected (possibly even on the instance level) - while Map is a data structure where the Map module provides the necessary functions to consistently manipulate that data structure.

So with Maps custom behaviour is either accomplished by injecting custom behaviour (under the control of the user of the data structure) functions like the Access.key/2 example or by defining new new manipulation functions as part of a new module - possibly creating a new data structure altogether that the standard Map becomes a part of.

2 Likes

The way I interpreted what you had written was that there was an explicit value of []. Seeing the docs explicitly says that the initial value is not passed into the fun [*] it seemed a reasonable way of interpreting it. Sorry if I was wrong.

[*] Whether this is a good choice or not is another question.

The definition for Map.update is
def update(map, key, initial, fun) when is_function(fun, 1) where fun is a 1 arity function that receives the existing value.

I don’t think it would be a breaking change to add this definition:
def update(map, key, initial, fun) when is_function(fun, 2) where fun is a 2 arity function that receives the existing value and the initial value. By initial value, I mean the value that the user supplied as the 3rd argument.

The second definition is what I expected the functionality of update to be and what I would prefer (and I think this is what @7stud and @OvermindDL1 would prefer). Importantly, there would be no impact for anyone who did not want to use the initial value in fun. They could simply continue to provide a 1 arity function as fun.

As @overmindDL1 points out, there are options to work around this limitation, but I agree with @7stud that this is an oversight.