我是功能/不可变编程的新手,我已经碰壁了.我正在尝试实现一个非常简单的重复数据删除功能来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))
这个想法显然是有一个包含读入行的Set,并且它在每个循环中都会更新.
现在,一些调试让我知道回调hashes
内部filter
在每个循环中都是空的,所以我猜它不会改变外部变量?我相信我只想在外部重新绑定变量,而不是在filter函数内部重新绑定变量.这可能吗?
我认为我正在遇到这个JavaScript所证明的范围问题(这是我能想到的唯一比较):
var hashes = new Set(); arr.filter(function (element) { var hashes = something(element); // i.e. using var not using outer scope });
任何人都可以准确地澄清上述实施中的错误吗?提前致谢 :)
来自https://elixir-lang.readthedocs.org/en/latest/technical/scoping.html#function-clause-scope:
每个函数子句定义一个新的词法范围:在其中绑定的任何新变量都不会在该子句之外可用
由于在Elixir中实现了不变性和变量,因此分配到hashes
内部函数内部与每次绑定到新变量相同.