# Is it possible to update multiple values in Enum.reduce without using maps as accumulator?

So, from what I know, we can only update one value using `Enum.reduce/3`. Is it possible to update multiple values using `Enum.reduce/3` without using maps?

To generalize this in more coding terms, I want to update the values of both `mycurr` and `myglobal`. Now if we use `Enum.reduce/3`, we cannot update both of these without incorporating them in a map and passing that off as an accumulator. The reason why I don’t want to use maps here is because that would increase the space complexity to O(n).

An example of what I want to do in Python is like this:

``````  mylist = [1,2,3,4,5]
mycurr = mylist[0]
myglobal = mylist[0]
for val in mylist:
if mycurr < 0:
mycurr = val
else:
mycurr += val

if myglobal < mycurr:
myglobal = mycurr
``````

Over here, both `mycurr` and `myglobal` gets updated. In Elixir, if we try using `Enum.reduce/3`, we can only update one of this unless we use a map as an accumulator, which would increase the space complexity to O(n).

``````Enum.reduce(mylist, 0, fn(val, acc) -> # 0 here refers to acc which is one one of mycurr or myglobal
``````

Are there any better alternatives to using `Enum.reduce/3` for this or is it possible to update multiple values without using a map as an accumulator?

The accumulator can be anything you want it to be, and for your example a tuple would suffice which is both space and time efficient. Something like:

``````{my_curr, my_global} =
Enum.reduce(mylist, {my_curr, my_global}, fn
val, {curr, global} when curr < 0 -> {val, global}
val, {curr, global} when global < curr -> {curr, curr}
...
end)
``````

Of course the function clauses aren’t what you’re after exactly since the code is truncated, but hopefully that gives you and idea of one approach.

4 Likes

This is brilliant. Thank you very much!

While kip is correct in that tuples are more efficient on paper I’d also add that `O(n)` for `n = 2` is also not really inefficient – problems arise for large values for `n`. Adding to that the implementation detail that maps with less than 32 keys are stored as tuples behind the scenes the difference in efficiency is likely almost none.

2 Likes

Good to know.

My understanding is that access to tuple elements is `O(1)` (ie constant time). See also the erlangist.com section on tuples

Accessing any element takes constant time

Modifying it is `O(n)` (ie linear time), meaning exactly as @LostKobrakai says. It might be more efficient to use a 2-element list but I suspect the timing wouldn’t be much different.

1 Like