JuliaFolds / Transducers.jl

Efficient transducers for Julia
https://juliafolds.github.io/Transducers.jl/dev/
MIT License
432 stars 24 forks source link

Length of `fixed_size_collection |> Take(n)` is unkonwn #481

Open lassepe opened 3 years ago

lassepe commented 3 years ago

To my surprise, a transducer using Take does not know its size, even if there are no Filter calls in the pipeline:

julia> 1:100 |> Take(10) |> length
ERROR: ArgumentError: Base.IteratorSize(ed) isa Union{Base.HasLength, Base.HasShape} must hold. Got
Base.IteratorSize(ed) => SizeUnknown()
Union{Base.HasLength, Base.HasShape} => Union{HasLength, HasShape}
Stacktrace:
 [1] macro expansion
   @ ~/.julia/packages/ArgCheck/5xEDR/src/checks.jl:243 [inlined]
 [2] length(ed::Transducers.Eduction{Transducers.Reduction{Take, Transducers.BottomRF{Transducers.Completing{typeof(BangBang.push!!)}}}, UnitRange{Int64}})
   @ Transducers ~/.julia/packages/Transducers/oLdU1/src/processes.jl:581
 [3] |>(x::Transducers.Eduction{Transducers.Reduction{Take, Transducers.BottomRF{Transducers.Completing{typeof(BangBang.push!!)}}}, UnitRange{Int64}}, f::typeof(length))
   @ Base ./operators.jl:858
 [4] top-level scope
   @ REPL[44]:1

collection |> Take(n) could still know about its length. Not because of Take(n) alone but because the input reducible may also knows its length. If there is no transducer that modifies the length depending on the input data, one should still be able to compute the length of the whole pipeline without materializing it; in this example the Take transducer could simply return min(length(collection), n).