Elixir 在每个块中添加元素时,列表的值不变

Elixir 在每个块中添加元素时,列表的值不变,elixir,Elixir,我有一张空名单 val = [] 当运行下面的代码时 Enum.each [1, 2, 3], fn x -> IO.puts x end 我们得到以下输出 1 2 3 :ok 这意味着,可以在每个块中访问元素 现在,当我运行以下代码时: Enum.each [1, 2, 3], fn x -> IO.puts x val = val ++ [x] end 这将得到以下结果 1 2 3 :ok 但是val的值没有改变,它仍然是[] 如果我单独在iex上运行 va

我有一张空名单

val = []
当运行下面的代码时

Enum.each [1, 2, 3], fn x ->
  IO.puts x
end
我们得到以下输出

1
2
3
:ok
这意味着,可以在每个块中访问元素

现在,当我运行以下代码时:

Enum.each [1, 2, 3], fn x ->
  IO.puts x
  val = val ++ [x]
end
这将得到以下结果

1
2
3
:ok
但是
val
的值没有改变,它仍然是
[]

如果我单独在iex上运行

val = val ++ [1]
val
的值更改为[1]


我对长生不老药很陌生,有红宝石方面的经验。需要了解上述行为背后的原因。

这是一个范围问题。Elixir的未来版本甚至可能会发出警告,如果您试图在内部作用域内重新绑定外部变量(当作用域离开时,该反弹变量会立即被丢弃),即上面的代码三次将外部
[]
重新绑定到
[i]
,然后有效地将其丢弃

要达到您的要求,请使用任何减速器,例如:

Enum.reduce[1,2,3],],fn x,val->
IO.x
val++[x]#返回累加器
结束
#⇒ 1
#  2
#  3
#⇒ [1, 2, 3]

旁注:在Ruby中,将累加器变量泄漏出作用域和/或混合作用域也被认为是一种代码气味:

#坏
val=[]

[1,2,3]。每个(&val.method)(:这是一个范围问题。如果您尝试在内部作用域内重新绑定外部变量,Elixir的未来版本甚至可能会发出警告(当作用域离开时,该反弹变量立即被丢弃),这表示上述代码将外部
[]
重新绑定到
[i]
并在之后有效地丢弃它

要达到您的要求,请使用任何减速器,例如:

Enum.reduce[1,2,3],],fn x,val->
IO.x
val++[x]#返回累加器
结束
#⇒ 1
#  2
#  3
#⇒ [1, 2, 3]

旁注:在Ruby中,将累加器变量泄漏出作用域和/或混合作用域也被认为是一种代码气味:

#坏
val=[]

[1,2,3]。每个(&val.method)(:是的,我理解。在ruby中,我通常在这种情况下使用
inject
Enumerable#inject
Enumerable#reduce
的别名(反之亦然)看到这种情况有点奇怪。为什么有人希望在范围离开后立即放弃对变量的更改。如果我们有一个同名的参数,这似乎很好。Elixir中没有“对变量的更改”这样的东西。Elixir中的所有内容都是不可变的(也有一些例外,但它们超出了正常的开发流程。)也就是说,我们不能改变任何东西的值。我们可以重新绑定变量,但这个反弹变量显然应该随着作用域而消亡,否则,我们最终将拥有数十亿个已定义的变量。内部
val
与外部变量无关(好吧,除了他们有共同的名字)当从任何允许可变性的语言切换时,这听起来有点令人震惊,但回报很好:一个人不能修改地图、列表或Elixir中的任何东西。当需要时,你只需生成一个新的地图/列表/任何东西,有时使用相同的名称。后者被称为“重新绑定”。“是的,我明白。在ruby中,我通常在这种情况下使用
inject
Enumerable#inject
Enumerable#reduce
的别名(反之亦然)看到这种情况有点奇怪。为什么有人希望在范围离开后立即放弃对变量的更改。如果我们有一个同名的参数,这似乎很好。Elixir中没有“对变量的更改”这样的东西。Elixir中的所有内容都是不可变的(也有一些例外,但它们超出了正常的开发流程。)也就是说,我们不能改变任何东西的值。我们可以重新绑定变量,但这个反弹变量显然应该随着作用域而消亡,否则,我们最终将拥有数十亿个已定义的变量。内部
val
与外部变量无关(好吧,除了他们有相同的名字)当从任何允许可变的语言切换时,这听起来有点让人吃惊,但回报很好:一个人不能修改地图、列表或Elixir中的任何东西。当需要时,你只需生成一个新的地图/列表/任何东西,有时使用相同的名称。后者被称为“重新绑定”