この記事で遅延評価の例を書きましたが、Enum.all/2を使えばStreamを使わなくても書ける内容でした。
もうすこしStreamらしい例を考えてみました。
heavy_processを10回よびだす。
返り値がすべて正の数だった場合、trueを返す関数をStreamで作成してみます。
def get_result() do
Stream.repeatedly(fn -> heavy_process() end)
|> Stream.take(10)
|> Stream.map(fn val -> val > 0 end)
|> Enum.all?()
end
def heavy_process() do
IO.puts("heavy!")
hd Enum.take_random([-1, 10, 20, 30, 40], 1)
end
iex> Tutorial012.get_result_stream2
heavy!
heavy!
false
うまく動きました。
ちなみにパイプの間でどんな値になっているのかinspectでみてみると
def get_result_stream2() do
Stream.repeatedly(fn -> heavy_process2() end)
|> IO.inspect(label: "a")
|> Stream.take(10)
|> IO.inspect(label: "b")
|> Stream.map(fn val -> val > 0 end)
|> IO.inspect(label: "c")
|> Enum.all?()
|> IO.inspect(label: "d")
end
こんな感じになっています。実際の値が受け渡されているわけではありません。
iex(28)> Tutorial012.get_result_stream2
a: #Function<51.124013645/2 in Stream.repeatedly/1>
b: #Stream<[
enum: #Function<51.124013645/2 in Stream.repeatedly/1>,
funs: [#Function<56.124013645/1 in Stream.take_after_guards/2>]
]>
c: #Stream<[
enum: #Function<51.124013645/2 in Stream.repeatedly/1>,
funs: [#Function<56.124013645/1 in Stream.take_after_guards/2>,
#Function<48.124013645/1 in Stream.map/2>]
]>
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
d: true
true