This is a repost from the mailing list, as i realized only after sending it there that the mailing list is depreciated.
Today i banged my head against this one :
iex(13)> [[true,false],[false],[true]]|>Stream.filter(fn([x|tail])-> IO.inspect([filter: x]); x end)
|>Stream.take(1)
|> Stream.flat_map(fn(x)-> IO.inspect([flat_map: x]); x end)
|> Enum.to_list()
[filter: true]
[flat_map: [true, false]]
[filter: false]
[filter: true]
[true, false]
Why is Stream.filter
’s argument executed after Stream.flat_map
’s argument has been called?
taking away the culprit Stream.flat_map
prevents the execution of Stream.filter
’s function after the first element:
[[true,false],[false],[true]]|>Stream.filter(fn([x|tail])-> IO.inspect([filter: x]); x end)
|>Stream.take(1)
|> Enum.to_list()
[filter: true]
[[true, false]]
It seems to me that this is a bug, but what i find more puzzling is that i do not know how Stream.flat_map
has even any influence on the Stream.filter
function.
Did i miss here how Stream.flat_map
should work or shall I file ~a bug request~ [EDIT: an issue :)]?
[Edit 2:] Actually the “culprit” is Stream.take/2
. Citing @josevalim from the mailing list:
You got the bug backwards. The issue is that flat_map continues even after take(1). Streams are by design meant to halt when items will no longer be consumed.