Elixir 创建状态变化的惰性序列(流),例如斐波那契数?
问题:是否有可能创建一个ElixirElixir 创建状态变化的惰性序列(流),例如斐波那契数?,elixir,Elixir,问题:是否有可能创建一个Elixir流,它在内部保持某种状态,并随着每次调用而改变?代码看起来会是什么样子呢 我很高兴看到Elixir0.10.2除了正常的Enum模块外,还有Streams。虽然有关于如何使用Streams的文档,但几乎没有描述如何创建它们的文档或可全局搜索的文档。阅读流模块的源代码不是很有启发性。我也研究了它的答案,虽然很有趣,但它也没有涉及到状态的变化 考虑生成需要记住前两个值的斐波那契数。或者想想 首先,我在理解这是否可能时遇到的问题是: 记录的可枚举元素仅通过一些示例设
流
,它在内部保持某种状态,并随着每次调用而改变?代码看起来会是什么样子呢
我很高兴看到Elixir0.10.2除了正常的Enum
模块外,还有Stream
s。虽然有关于如何使用Stream
s的文档,但几乎没有描述如何创建它们的文档或可全局搜索的文档。阅读流
模块的源代码不是很有启发性。我也研究了它的答案,虽然很有趣,但它也没有涉及到状态的变化
考虑生成需要记住前两个值的斐波那契数。或者想想
首先,我在理解这是否可能时遇到的问题是:
可枚举
元素仅通过一些示例设置,并且始终设置为现有的固定列表。处理无限序列的示例根本不涉及可枚举
(例如迭代
或重复
)fun
提供的函数应该返回另一个函数,而不是新的流。Lazy
记录,据我所知,这与Clojure的Lazy序列有很大区别,在Clojure的Lazy序列中,使用Lazy seq
返回新序列acc
,我还是有些不解。看起来fun
本身并没有修改它;相反,一些调用fun
的外部函数会这样做这就是我的问题。我只是在小溪边玩耍。我可能没有抓住要点,但是为了维护状态,可以使用exactor(gen_服务器) 定义
defmodule Sample do
use ExActor
defcall next(x), state: state, do: reply(state + x, x)
def fib(n) do
{:ok, act} = Sample.start(1)
Stream.iterate(0, fn(x) -> Sample.next(act, x) end) |> Enum.take(n)
end
end
跑
我不是惰性流方面的专家,但以下是我的尝试: 但是请注意,在这个示例中,状态是公共的,而不是内部的,所以我不知道这是否是您要寻找的 解决方案首先依赖于创建一个记录(在本例中是私有的),并公开一个可以将记录移动到下一个状态的函数:
fib0 = Fibonacci.new
fib1 = Fibonacci.next(fib0)
fib2 = Fibonacci.next(fib1)
fib3 = Fibonacci.next(fib2)
IO.inspect fib3
每个fibx
都包含完整状态。在本例中,我保留当前的数字,加上之前生成的两个数字
基于此,我现在可以使用创建一个无休止的惰性集合:
Fibonacci.lazy
|> Enum.take(5)
|> IO.inspect
由于它基于Fibonacci.next,因此每个生成的元素都是一条记录,而不是一个值。您可以使用Fibonacci.value
从每个元素中提取值
还可以执行更复杂的操作:
Fibonacci.lazy
|> Stream.drop(3) # drop first three
|> Enum.first # take the first
|> Fibonacci.lazy # start lazy from it
|> Stream.filter(&(rem(Fibonacci.value(&1), 2) == 1)) # take only odd values
|> Stream.map(&(Fibonacci.value(&1))) # extract values from it
|> Enum.take(10) # take first 10
|> IO.inspect # print it
允许您在维护“累加器”(状态)的同时生成一系列值
我刚刚在这里使用它构建了一个懒惰的斐波那契序列函数:我一定要看看它。谢谢你的指点。不过我会把这个问题留待讨论,因为你的帖子并没有给出确切的答案。谢谢!我一定会让它转一转。公共状态或多或少是一个品味问题,对我来说并不重要。这似乎是Elixir0.12.0中的一个新功能。很高兴他们也加入了这个。
Fibonacci.lazy
|> Stream.drop(3) # drop first three
|> Enum.first # take the first
|> Fibonacci.lazy # start lazy from it
|> Stream.filter(&(rem(Fibonacci.value(&1), 2) == 1)) # take only odd values
|> Stream.map(&(Fibonacci.value(&1))) # extract values from it
|> Enum.take(10) # take first 10
|> IO.inspect # print it