药剂不使用enum.each更新mapset中的值

时间:2019-03-15 07:07:31

标签: elixir

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

这里filtered_list是一个包含字符串的列表,但是当我打印map_set时,它返回一个空集。为什么?

2 个答案:

答案 0 :(得分:3)

对于filtered_list中的每个项目,您都将在回调函数的范围内创建一个新的MapSet。您不能在回调函数中重新绑定上级作用域的map_set(尽管您可以读取它,但重新绑定它只会生成一个新的作用域变量)。相反,您应该使用表达式的返回值。例如

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)

ifcasecond,...都适用,您使用表达式的返回值。

something = "foo"

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

# it's still foo
something

如果您想重新绑定something,则必须使用if表达式的返回值

something = "foo"

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

# is "foo bar"
something

顺便说一句,您可以将filtered_list传递到MapSet.new/1,如果需要任何转换,可以使用MapSet.new/2

答案 1 :(得分:2)

您的代码与此等效:

map_set = MapSet.new()

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

您在枚举内分配的map_set是一个局部变量,它与枚举外的map_set无关。也可以将其称为other,因为您正在丢弃变量。 Elixir是一种不可变的语言,因此您需要将可枚举的结果分配给map_set

如果您只想将列表转换为集合,则只需执行以下操作:

MapSet.new(filtered_list)