Elixir 创建状态变化的惰性序列(流),例如斐波那契数?

Elixir 创建状态变化的惰性序列(流),例如斐波那契数?,elixir,Elixir,问题:是否有可能创建一个Elixir流,它在内部保持某种状态,并随着每次调用而改变?代码看起来会是什么样子呢 我很高兴看到Elixir0.10.2除了正常的Enum模块外,还有Streams。虽然有关于如何使用Streams的文档,但几乎没有描述如何创建它们的文档或可全局搜索的文档。阅读流模块的源代码不是很有启发性。我也研究了它的答案,虽然很有趣,但它也没有涉及到状态的变化 考虑生成需要记住前两个值的斐波那契数。或者想想 首先,我在理解这是否可能时遇到的问题是: 记录的可枚举元素仅通过一些示例设

问题:是否有可能创建一个Elixir
,它在内部保持某种状态,并随着每次调用而改变?代码看起来会是什么样子呢

我很高兴看到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