elixir - 为什么这个无限灵药流中的变量没有反弹?

标签 elixir

我有以下内容:

counter = 0

try do
  for _ <- Stream.cycle([:ok]) do
    IO.puts "Counter is #{counter}"
    counter = counter + 1
    IO.puts "After counter: #{counter}"

    if counter == 3 do
      throw :halt
    end
  end
catch
  :halt -> IO.puts "Finished processing"
end

根据我所读到的内容,我认为 counter = counter + 1 会重新绑定(bind)变量,最终 counter == 3 条件将为 true。但是,我得到的输出是这样的:

Counter is 0
After counter: 1
Counter is 0
After counter: 1
Counter is 0
...

所以,基本上,计数器会回到初始值。感觉 for 内部的重新绑定(bind)就像局部变量一样工作,或者隐藏了第一个变量。我怎样才能使该值持续存在(如果可能的话不使用递归)?

最佳答案

回答标题问题:它不会被重新绑定(bind),因为 do block 通常*不能更改其范围之外的变量。您的 IO 语句表明它可以更改作用域内的变量;但是当 do block 再次运行时,它会在新的作用域中再次运行,其中初始值是根据原始值设置的。

回答内心的问题:这取决于你想要做什么。您的示例并没有详细说明为什么选择 Stream 模块而不是 Enum。假设您知道需要进行三次迭代,实现目标的一种方法是使用 for 理解:

for i <- (1..3) do
  IO.inspect i
end

我可能过度解释了你的问题,我当然不是有意侮辱,但你似乎厌恶递归。如果您计划在 Elixir 中编写大量代码,那么您需要克服这一点 - 这是一种函数式语言,其中递归是惯用的 - 在任何语言中,使用该语言编写会更加高效而不是尝试围绕您不熟悉的部分进行编码。

*有关异常(exception)情况,请参阅 macro programming

关于elixir - 为什么这个无限灵药流中的变量没有反弹?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32811831/

相关文章:

elixir - 覆盖毒物编码器

module - 如何使用 Phoenix 项目的 lib/文件夹中定义的模块?

elixir - 如何在 Elixir 或 "abstract"函数中创建 "virtual"模块?

elixir - 如何正确重新安装Elixir?

javascript - Phoenix - 使用数据表的站点范围搜索功能

elixir - 如何在 Elixir 中使用 `select`?

elixir - Phoenix 框架和验证嵌入

erlang - 缺少模型之间的 ecto 关联

elixir - 将 map 转换为 URI 查询字符串

functional-programming - 函数式语言中同名不同参数的函数