在Elixir

时间:2015-12-08 22:38:32

标签: functional-programming elixir

我是功能/不可变编程的新手,我已经碰壁了。我尝试在Elixir中实施一个非常简单的重复数据删除功能,以便对stdin进行重复数据删除。

我使用Stream.transform/2进行了非常简单的实现,但我的原始实现使用Stream.filter/2这样(为了示例目的而愚蠢)并且我不确定我理解它为什么&#39 ; s不工作:

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))

这个想法显然是包含读入的行的集合,并且每次循环都会更新。

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

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

var hashes = new Set();

arr.filter(function (element) {
    var hashes = something(element); // i.e. using var not using outer scope
});

任何人都可以准确地澄清上述实施的错误吗?在此先感谢:)

2 个答案:

答案 0 :(得分:8)

来自https://elixir-lang.readthedocs.org/en/latest/technical/scoping.html#function-clause-scope

  

每个函数子句定义一个新的词法范围:在其中绑定的任何新变量都不会在该子句之外可用

由于在Elixir中实现了不变性和变量,因此在内部函数中分配hashes与每次绑定到新变量相同。

答案 1 :(得分:0)

为什么不与Stream.uniq/2uniq/2)一起过滤掉所有重复的行

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