Strange behavior in Elixir when updating a MapSet inside a for loop

list1 = [2,3,4]
map22 = MapSet.new()
map22 = MapSet.put(map22,25)
for i <- list1 do
  map22 = MapSet.put(map22,i)
end
IO.puts("The updated map is #{inspect(map22)}")

When i run the above program i see that the updates within the for loop doesn't work at all. Why is this so?


Scoping in Elixir works as:

  1. Any variables defined in the surrounding scope are accessible in all other scopes it contains.
  2. Any variable in a nested scope whose name coincides with a variable from the surrounding scope will shadow that outer variable. In other words, the variable inside the nested scope temporarily hides the variable from the surrounding scope, but does not affect it in any way.

source: Scoping Rules in Elixir (and Erlang)

Back to your problem, you would like to take the rebinding out from the for scope. For example:

list1 = [2, 3, 4]
map22 = MapSet.new()
map22 = MapSet.put(map22, 25)

map22 =
  for i <- list1, reduce: map22 do
    acc ->
      MapSet.put(acc, i)
  end

IO.inspect(map22)

#MapSet<[2, 3, 4, 25]>

I realise your example is contrived, but to add a list of values to an existing MapSet, you can use MapSet.union/2 or Enum.into/2:

Given:

a = MapSet.new([1,2,3])
b = [4,5,6]

Then both of the following:

MapSet.union(a, MapSet.new(b))
Enum.into(b, a)

produce #MapSet<[1, 2, 3, 4, 5, 6]>