当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Elixir Stream用法及代码示例


Elixir语言中 Stream 相关用法介绍如下。

用于创建和组合流的函数。

流是可组合的、惰性的可枚举(有关可枚举的介绍,请参阅 Enum 模块)。在枚举过程中一个一个地生成元素的任何可枚举对象都称为流。例如,Elixir 的 Range 是一个流:

iex> range = 1..5
1..5
iex> Enum.map(range, &(&1 * 2))
[2, 4, 6, 8, 10]

在上面的示例中,当我们在范围上进行映射时,被枚举的元素是在枚举过程中一一创建的。 Stream 模块允许我们映射范围,而不触发其枚举:

iex> range = 1..3
iex> stream = Stream.map(range, &(&1 * 2))
iex> Enum.map(stream, &(&1 + 1))
[3, 5, 7]

请注意,我们从一个范围开始,然后我们创建了一个流,该流旨在将范围中的每个元素乘以 2。此时,没有进行任何计算。只有当 Enum.map/2 被调用时,我们才真正枚举范围内的每个元素,将其乘以 2 并加 1。我们说 Stream 中的函数是 lazy Enum 中的函数是 eager

由于它们的惰性,流在处理大型(甚至无限)集合时很有用。当使用 Enum 链接许多操作时,会创建中间列表,而 Stream 创建稍后执行的计算配方。让我们看另一个例子:

1..3
|> Enum.map(&IO.inspect(&1))
|> Enum.map(&(&1 * 2))
|> Enum.map(&IO.inspect(&1))
1
2
3
2
4
6
#=> [2, 4, 6]

请注意,我们首先打印列表中的每个元素,然后将每个元素乘以 2,最后打印每个新值。在此示例中,列表被枚举了 3 次。让我们看一个流的例子:

stream = 1..3
|> Stream.map(&IO.inspect(&1))
|> Stream.map(&(&1 * 2))
|> Stream.map(&IO.inspect(&1))
Enum.to_list(stream)
1
2
2
4
3
6
#=> [2, 4, 6]

虽然最终结果是一样的,但元素的打印顺序发生了变化!使用流,我们打印第一个元素,然后打印它的双精度。在这个例子中,列表只被枚举了一次!

这就是我们之前所说的流是可组合的、惰性的枚举的意思。请注意,我们可以多次调用 Stream.map/2 ,从而有效地组合流并使它们保持惰性。仅当您从 Enum 模块调用函数时才会执行计算。

Enum 一样,此模块中的函数以线性时间工作。这意味着,执行操作所需的时间与列表长度的增长速度相同。这在诸如 Stream.map/2 之类的操作中是预期的。毕竟,如果我们要遍历流上的每一个元素,流越长,我们需要遍历的元素越多,需要的时间也就越长。

创建流

Elixir 的标准库中有许多返回流的函数,例如:

该模块还提供了许多用于创建流的便利函数,例如 Stream.cycle/1 Stream.unfold/2 Stream.resource/3 等。

请注意,此模块中的函数保证返回可枚举值。由于枚举可以有不同的形状(结构、匿名函数等),这个模块中的函数可能会返回这些形状中的任何一个,并且这可能随时改变。例如,今天返回匿名函数的函数可能会在将来的版本中返回结构。

相关用法


注:本文由纯净天空筛选整理自elixir-lang.org大神的英文原创作品 Stream。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。