From 4ae91695b3964c6974e34988ac8e4a7d197ad418 Mon Sep 17 00:00:00 2001 From: Andy Ferris Date: Wed, 20 May 2020 11:36:54 +1000 Subject: [PATCH] Add a default implementation of `length` using `iterate`. --- NEWS.md | 1 + base/generator.jl | 12 ++++++++++++ test/missing.jl | 1 + 3 files changed, 14 insertions(+) diff --git a/NEWS.md b/NEWS.md index ea03e90990f59..9de2d9a6a63e2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -43,6 +43,7 @@ Standard library changes ------------------------ * The `nextprod` function now accepts tuples and other array types for its first argument ([#35791]). * The function `isapprox(x,y)` now accepts the `norm` keyword argument also for numeric (i.e., non-array) arguments `x` and `y` ([#35883]). +* There is a default implementation of `length` for all iterables with `IteratorSize` of `SizeUnknown` (using simple iteration) ([#35947]). #### LinearAlgebra diff --git a/base/generator.jl b/base/generator.jl index 7cd075d255b01..def286527a194 100644 --- a/base/generator.jl +++ b/base/generator.jl @@ -97,6 +97,18 @@ IteratorSize(::Type{Any}) = SizeUnknown() haslength(iter) = IteratorSize(iter) isa Union{HasShape, HasLength} +function length(iter) + if IteratorSize(iter) isa SizeUnknown + i = 0 + for _ in iter + i += 1 + end + return i + else + throw(MethodError(length, (iter,))) + end +end + abstract type IteratorEltype end struct EltypeUnknown <: IteratorEltype end struct HasEltype <: IteratorEltype end diff --git a/test/missing.jl b/test/missing.jl index 850482585b2cd..e84548b9d921f 100644 --- a/test/missing.jl +++ b/test/missing.jl @@ -363,6 +363,7 @@ end @testset "skipmissing" begin x = skipmissing([1, 2, missing, 4]) @test eltype(x) === Int + @test length(x) == 3 @test collect(x) == [1, 2, 4] @test collect(x) isa Vector{Int}