【问题标题】:Lazily concatenate an enumerable of lists懒惰地连接一个可枚举的列表
【发布时间】:2013-09-21 03:51:00
【问题描述】:

我想编写一个类似于 List.concat/1 的函数,它接受一个可枚举的列表并将连接的列表作为连续流发出。

它会像这样工作:

iex> 1..3 |> Stream.map(&([&1])) |> Enum.to_list
[[1], [2], [3]]
iex> 1..3 |> Stream.map(&([&1])) |> MyStream.concat |> Enum.to_list
[1, 2, 3]

到目前为止,我想出的是:

defmodule MyStream do
  def concat(lists) do
    Enumerable.reduce(lists, [], fn(x, acc) -> acc ++ x end)
  end
end

这会产生正确的结果,但显然不是懒惰的。

我没有成功尝试使用Stream.Lazy,但真的无法理解它的内部工作原理。对Stream.Lazy 的任何解释将不胜感激!

【问题讨论】:

    标签: stream lazy-evaluation elixir


    【解决方案1】:

    Elixir 中的可枚举通过归约函数表示。只要您告诉我们如何减少它,我们就可以映射任何结构。

    Stream 的整体理念是您可以组合这些归约函数。我们以地图为例:

    def map(enumerable, f) do
      Lazy[enumerable: enumerable,
           fun: fn(f1) ->
             fn(entry, acc) ->
               f1.(f.(entry), acc)
             end
           end]
    end
    

    你收到一个可枚举的并且你想用函数f 映射每个元素。惰性版本接收实际的约简函数f1 并返回一个新函数,该函数接收entryaccf1 将接收相同的参数)然后调用f.(entry) 在调用@ 之前有效映射元素987654328@(减少功能)。注意我们是如何一一映射元素的。

    这种平面地图的变体可能是这样的:

    def flat_map(enumerable, f) do
      Lazy[enumerable: enumerable,
           fun: fn(f1) ->
             fn(entry, acc) ->
               Enumerable.reduce(f.(entry), acc, f1)
             end
           end]
    end
    

    现在,每次您调用 f.(entry) 时,您都会返回一个列表,并且您想要迭代这个新列表的每个元素,而不是迭代整个列表。

    我没有尝试过上面的代码(我可能遗漏了一些细节),但这就是 Streams 的一般工作方式。

    【讨论】:

      【解决方案2】:

      对于the help of José Valim,从他的代码到我正在寻找的内容只是一小步。我可能提出这个问题相当糟糕,但我真正想要的是与 Python 的 itertools.chain 函数等效的。

      def chain(enumerable) do
        Stream.Lazy[enumerable: enumerable,
                    fun: fn(f1) ->
                      fn(entry, acc) ->
                        Enumerable.reduce(entry, acc, f1)
                      end
                    end]
      end
      

      这允许您链接两个流或列表的潜在无限枚举。

      iex> 1..1000000 |> Stream.map(&(1..(&1))) |> MyModule.chain |> Enum.take(20)
      [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
      

      【讨论】:

        猜你喜欢
        • 2018-04-28
        • 2019-02-25
        • 2013-05-24
        • 2011-03-24
        • 1970-01-01
        • 2014-05-31
        • 1970-01-01
        • 2015-08-24
        • 2021-08-08
        相关资源
        最近更新 更多