gpt4 book ai didi

stream - 懒惰地串联一个可枚举的列表

转载 作者:行者123 更新时间:2023-12-04 13:32:45 24 4
gpt4 key购买 nike

我想编写一个类似于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的解释将不胜感激!

最佳答案

Elixir中的可枚举通过归约函数表示。只要您告诉我们如何简化结构,我们就可以绘制任何结构。

Stream的整体思想是您可以组成这些归约函数。让我们以 map 为例:

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

您将收到一个可枚举的对象,并且您想使用 f函数映射每个元素。惰性版本接收实际的归约函数 f1并返回一个新函数,该函数接收 entryacc(与 f1会接收相同的参数),然后在调用 f.(entry)(归约函数)之前调用 f1有效地映射该元素。注意我们如何在元素之间一一对应。

平面 map 的变体可能类似于:
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通常的工作方式。

关于stream - 懒惰地串联一个可枚举的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18341466/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com