如何获取流的元素(Elixir)并保持流的状态?

Ric*_*ast 6 stream elixir

我爱长生不老药流。特别是我有一个函数可以构造无限数量的质数流。您可以使用适当的Stream / Enum操作(Enum.take(10_000)Enum.take_while(& (&1 < 1_000_000))分别)获取前10,000个或低于1,000,000的所有素数。

但是假设我事先不知道我需要多少个素数。我到了某个程度,我说,嘿,实际上还需要再加1000个素数。有没有办法说,获取流的前10,000个元素,然后以某种方式保存生成的流对象,这样我就可以按需获取(当然是重复地)下一个 1,000 个元素?

Ale*_*kin 5

TL;DR保存累加器,而不是“流”。

@Dogbert 在评论中提供了强大的解决方案:StreamSplitpackage 似乎完全符合要求。

为了历史起见,我的回答是:有许多Stream函数(全部派生自Stream.transform/4,它是几乎所有可能需要的通用流实现)可以解决问题。例如,考虑斐波那契数列。人们可以将它们实现为:

stream = Stream.iterate({1, 1}, fn {acc, i} ->
  {acc + i, acc}
end)
#? #Function<61.36862645/2 in Stream.unfold/2>
stream |> Enum.take(5) 
#? [{1, 1}, {2, 1}, {3, 2}, {5, 3}, {8, 5}]
current = stream |> Enum.take(5) |> List.last
#? {8, 5}
Run Code Online (Sandbox Code Playgroud)

如果您想继续获取数字:

#              ??????
Stream.iterate({8, 5}, fn {acc, i} ->
  {acc + i, acc}
end)
Run Code Online (Sandbox Code Playgroud)

只需保持中间状态并将其作为初始值传递给您用来获取素数的流函数。我个人认为保留“tail”而不是累加器没有任何优势,但我可能肯定是错的。