user9106677
user9106677

Reputation: 61

elixir not updating values in mapset using enum.each

map_set = MapSet.new()
Enum.each(filtered_list, fn x -> map_set = MapSet.put(MapSet.new(map_set),x)

Here filtered_list is a list containing string but when I am printing map_set it is returning an empty set. Why?

Upvotes: 1

Views: 766

Answers (2)

Adam Millerchip
Adam Millerchip

Reputation: 23091

Your code is equivalent to this this:

map_set = MapSet.new()

Enum.each(filtered_list, fn x ->
  other = MapSet.put(MapSet.new(map_set), x)
end)

The map_set you assign to inside the enum is a local variable, it's not related to the map_set outside the enum. It may as well be called other, because you are discarding the variable. Elixir is an immutable language, so you need to assign the result of the enumerable to map_set.

If you just want to convert a list to a set, you can simply do:

MapSet.new(filtered_list)

Upvotes: 2

fhdhsni
fhdhsni

Reputation: 1629

For each item in filtered_list you're creating a new MapSet in the scope of the callback function. You can't rebind map_set of the upper scope in the callback function (although you can read it, rebinding it just makes a new scoped variable). Instead you should use the returned value of expressions. For example

filtered_list = ["foo", "bar"]
map_set = MapSet.new()         # this is actually redundant 

map_set = Enum.reduce(filtered_list, map_set, fn filter, map_set ->
  MapSet.put(map_set, filter)
end)

This is true of if, case, cond, ... you use the returned value of your expression.

something = "foo"

if true do
  something = something <> "bar"
end

# it's still foo
something

if you want to rebind something you have to use the returned value of the if expression

something = "foo"

something =
  if true do
    something <> " bar"
  end

# is "foo bar"
something

By the way, you can just pass the filtered_list to MapSet.new/1 and if you need any transformation you can use MapSet.new/2

Upvotes: 4

Related Questions