是否可以减少 Elixir 中的流?
我看到 Stream.scan 但它不返回累加器。
file_stream
|> Stream.each(&parse_line/1)
|> Enum.reduce(&reduce_fn/2)
我似乎遇到了以下问题,但想知道是否可以这样做?
减少流量是没有意义的。
Enum
模块与Stream
中的函数之间的核心区别是,前者是贪婪的,而后者是懒惰的。
也就是说,
Stream
产生一组转换,可以在每个集合的元素基础上延迟应用,传递。
但是
reduce
(又名foldl
)已经是一种有效的贪心操作,如果不遍历整个集合就无法得到结果。 (顺便说一句,这就是为什么 Stream.scan/3
不返回累积值的原因。)
枚举
# ===== code ===== ===== piped through =====
[1, 2, 3] # [1, 2, 3]
# # ⇓
|> Enum.map(&IO.inspect/1) # [1, 2, 3]
# # ⇓
|> Enum.map(&IO.inspect/1) # [1, 2, 3]
#⇒ 1 2 3 1 2 3
直播
# ===== code ===== ===== piped through =====
[1, 2, 3] # 1 2 3
# # ⇓ ⇓ ⇓
|> Stream.map(&IO.inspect/1) # 1 2 3
# # ⇓ ⇓ ⇓
|> Stream.map(&IO.inspect/1) # 1 2 3
|> Enum.to_list() # termination!
# # ⇒ ⇒ ⇒
#⇒ 1 1 2 2 3 3
如果您想积累一些价值,您可能会寻找
Stream.transform/3
、Stream.transform/4
或 Stream.transform/5
。这将允许您保留一个累加器,这通常就是人们会在枚举器上进行归约的原因。
例如,文档显示了如何通过以下方式实现 Stream.take(enum, n):
enum = 1001..9999
n = 3
stream = Stream.transform(enum, 0, fn i, acc ->
if acc < n, do: {[i], acc + 1}, else: {:halt, acc}
end)
Enum.to_list(stream)
[1001, 1002, 1003]
更多信息:https://hexdocs.pm/elixir/1.12.3/Stream.html#transform/3