Elixir 流

2023-12-15 13:53 更新
Elixir提供了支持懶惰操作的String模塊來作為Enum的替代品:
iex> 1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(odd?) |> Enum.sum
7500000000

流是懶惰的,組合的枚舉接口。

在上述例子中,1..100_000 |> Stream.map(&(&1 * 3))返回了一個(gè)數(shù)據(jù)類型,實(shí)際上是一個(gè)流,它代表了map計(jì)算在范圍1..100_000中:

iex> 1..100_000 |> Stream.map(&(&1 * 3))
#Stream<[enum: 1..100000, funs: [#Function<34.16982430/1 in Stream.map/2>]]>

而且它們是可組合的,因?yàn)槲覀兛梢杂霉苓B接許多流操作:

iex> 1..100_000 |> Stream.map(&(&1 * 3)) |> Stream.filter(odd?)
#Stream<[enum: 1..100000, funs: [...]]>

流沒有生成中間列表,而是構(gòu)建了一系列的計(jì)算,它們只會(huì)在我們將潛在的流傳遞給?Enum?模塊時(shí)才會(huì)被調(diào)用。流在處理大量的,有可能是無限的,集合時(shí)非常有用。

Stream模塊中的許多函數(shù)接受任何枚舉體作為參數(shù),并返回一個(gè)流作為結(jié)果。也有用于創(chuàng)建流的函數(shù)。例如,Stream.cycle/1用于創(chuàng)建一個(gè)將給定枚舉體無限循環(huán)的流,注意不要以這種流為參數(shù)調(diào)用例如Enum.map/2之類的函數(shù),因?yàn)樗麄儠?huì)無限循環(huán)下去:

iex> stream = Stream.cycle([1, 2, 3])
#Function<15.16982430/2 in Stream.cycle/1>
iex> Enum.take(stream, 10)
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1]

另一方面,?Stream.unfold/2?可以用于從給定的初始值中生成多個(gè)值:

iex> stream = Stream.unfold("he??o", &String.next_codepoint/1)
#Function<39.75994740/2 in Stream.unfold/2>
iex> Enum.take(stream, 3)
["h", "e", "?"]

另一個(gè)有趣的函數(shù)是?Stream.resource/3?,它可以用于包裹源代碼,保證它們在枚舉之前是開啟的且之后是關(guān)閉的,即使在失敗的案例中。例如,我們可以用它流一個(gè)文件:

iex> stream = File.stream!("path/to/file")
#Function<18.16982430/2 in Stream.resource/3>
iex> Enum.take(stream, 10)

上述例子將會(huì)獲得所選文件的前十行。這意味著流可以很好地處理巨大的文件,即使是像網(wǎng)絡(luò)資源那樣的慢資源。

EnumStream模塊中的函數(shù)數(shù)量也許一開始很嚇人,但你會(huì)一個(gè)案例一個(gè)案例地熟悉他們。首先專注于Enum模塊,只在要求懶惰性的情形下使用Stream模塊,例如處理慢資源,或巨大的,可能無限的集合。

我們將要講到Elixir的核心特性,進(jìn)程,它使得我們能以一種簡單易懂的方式編寫并發(fā),并行和分布式的程序。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)