Functional programming 在Elixir中重新绑定外部作用域中的变量

Functional programming 在Elixir中重新绑定外部作用域中的变量,functional-programming,elixir,Functional Programming,Elixir,我不熟悉函数式/不可变编程,我遇到了困难。我试图在Elixir中实现一个非常简单的重复数据消除功能,以消除stdin中的重复数据 我有一个使用Stream.transform/2的非常简单的实现,但我最初的实现使用了Stream.filter/2这样的实现(为了示例目的,这被简化了),我不确定它为什么不起作用: hashes = HashSet.new IO.stream(:stdio, :line) |> Stream.filter(fn(line) -> if

我不熟悉函数式/不可变编程,我遇到了困难。我试图在
Elixir
中实现一个非常简单的重复数据消除功能,以消除
stdin
中的重复数据

我有一个使用
Stream.transform/2
的非常简单的实现,但我最初的实现使用了
Stream.filter/2
这样的实现(为了示例目的,这被简化了),我不确定它为什么不起作用:

hashes = HashSet.new

IO.stream(:stdio, :line)
  |> Stream.filter(fn(line) ->
      if HashSet.member?(hashes, line) do
        false
      else
        hashes = HashSet.put(hashes, line)
        true
      end
    end)
  |> Enum.each(&IO.write(&1))
很明显,有一个集合包含读入的行,并在每个循环中更新

现在,通过一些调试,我发现
过滤器
回调中的
哈希值在每个循环中都是空的,所以我猜它没有改变外部变量?我相信我只是想在外部重新绑定变量,而不是在filter函数内部。这可能吗

我认为我遇到了一个范围问题,正如JavaScript所示(这是我能想到的唯一比较):


有人能澄清上述实现的错误之处吗?提前感谢:)

为什么不使用
Stream.uniq/2
()来过滤掉所有重复的行

IO.stream(:stdio, :line)
|> Stream.uniq
|> Enum.each(&IO.write(&1))
发件人:

每个函数子句定义一个新的词法作用域:它内部绑定的任何新变量在该子句外部都不可用


因为不变性和变量是如何在Elixir中实现的,在内部函数中分配给
散列
与每次绑定一个新变量是一样的。

这只是一个示例-如果我想根据每行上的某个值进行解析并进行唯一性处理,该怎么办?根据
uniq/2
的文档,您可以将函数作为第二个参数传递,以提供唯一性标准,eq
IO.stream(:stdio,:line)|>stream.uniq(fn(x)->String.length(x)end)|>Enum.each(&IO.write(&1))
这太棒了。我原以为可能是这样,但对我来说似乎从来没有起过作用。也许我需要更新。所以没有办法在外部范围内重新绑定某些内容?我希望有一种方法可以手动完成。我想没有。然而,它也不是惯用语。您通常不会为副作用调用函数,而是为返回值调用函数。通常您会使用Enum或Stream中的一些函数
Stream.uniq/2
可以在这里工作,更一般地说,
Enum.reduce/3
可以做几乎任何事情。原因是Stream.filter有并行实现,但Stream.uniq;)没有不过,感谢您提供的信息。作为参考,请参阅José对此的回答:
IO.stream(:stdio, :line)
|> Stream.uniq
|> Enum.each(&IO.write(&1))