我是功能/不可变编程的新手,我已经碰壁了。我尝试在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
});
任何人都可以准确地澄清上述实施的错误吗?在此先感谢:)
答案 0 :(得分:8)
来自https://elixir-lang.readthedocs.org/en/latest/technical/scoping.html#function-clause-scope:
每个函数子句定义一个新的词法范围:在其中绑定的任何新变量都不会在该子句之外可用
由于在Elixir中实现了不变性和变量,因此在内部函数中分配hashes
与每次绑定到新变量相同。
答案 1 :(得分:0)
为什么不与Stream.uniq/2
(uniq/2)一起过滤掉所有重复的行
IO.stream(:stdio, :line)
|> Stream.uniq
|> Enum.each(&IO.write(&1))