-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Define length(::SkipMissing)
#35946
base: master
Are you sure you want to change the base?
Define length(::SkipMissing)
#35946
Conversation
435e2a3
to
6f664cb
Compare
Actually I'm not sure why we don't have this as a definition for |
6f664cb
to
888006b
Compare
OK I nerd-sniped myself. The generalization is at #35947. |
FYI It seems that #35947 won't be suitable (at least for the time being), so I'd still like to have this PR considered. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use count
?
@@ -258,6 +258,13 @@ keys(itr::SkipMissing) = | |||
v === missing && throw(MissingException("the value at index $I is missing")) | |||
v | |||
end | |||
function length(itr::SkipMissing) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function length(itr::SkipMissing) | |
length(itr::SkipMissing) = count(_->true, itr) |
Doesn't this suffer the same problem as #35947 in case someone wraps a stateful iterator in |
This is where I'm confused - I'm not "saved" from calling I thought I've seen people argue it's a good model to use reductions over
Unfortunately, having a determinate size is orthogonal to being stateful, and we don't have a trait for iterator-statefulness. Besides, that particular approach would destroy composibility of multiple layers of lazy filtering. You can see the current situation below. julia> a = Iterators.Stateful([1, 2, missing, 4]);
julia> Base.IteratorSize(a)
Base.HasLength()
julia> length(a)
4
julia> length(a)
4
julia> (length ∘ skipmissing)(a)
ERROR: MethodError: no method matching length(::Base.SkipMissing{Base.Iterators.Stateful{Array{Union{Missing, Int64},1},Union{Nothing, Tuple{Union{Missing, Int64},Int64}}}})
Closest candidates are:
length(::Core.SimpleVector) at essentials.jl:596
length(::Base.MethodList) at reflection.jl:852
length(::Core.MethodTable) at reflection.jl:938
...
Stacktrace:
[1] (::Base.var"#64#65"{typeof(length),typeof(skipmissing)})(::Base.Iterators.Stateful{Array{Union{Missing, Int64},1},Union{Nothing, Tuple{Union{Missing, Int64},Int64}}}) at ./operators.jl:859
[2] top-level scope at REPL[4]:1
[3] eval(::Module, ::Any) at ./boot.jl:331
[4] eval_user_input(::Any, ::REPL.REPLBackend) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
[5] run_backend(::REPL.REPLBackend) at /home/ferris/.julia/packages/Revise/AMRie/src/Revise.jl:1023
[6] top-level scope at none:0
[7] eval(::Module, ::Any) at ./boot.jl:331
[8] eval_user_input(::Any, ::REPL.REPLBackend) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
[9] run_backend(::REPL.REPLBackend) at /home/ferris/.julia/packages/Revise/AMRie/src/Revise.jl:1023
[10] top-level scope at none:0
julia> ((itr -> count(_ -> true, itr)) ∘ skipmissing)(a)
3
julia> ((itr -> count(_ -> true, itr)) ∘ skipmissing)(a)
0 |
Right, doing this for |
This adds a definition for the
length
ofSkipMissing
. Note that theIteratorSize
trait remains available for algorithms to know that this function is not O(1).In particular, it seems odd that I can do:
but not:
Now we have: