From a9bea619c55be932a441dda0bcfd35d961f1b46d Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Mon, 17 Dec 2018 23:37:11 +0100 Subject: [PATCH 01/10] Added takewhile code --- src/IterTools.jl | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/IterTools.jl b/src/IterTools.jl index 5a69d3b..145033a 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -873,4 +873,37 @@ function iterate(ff::FlagFirst, state = (true, )) (isfirst, elt), (isfirst & false, nextstate) end +# TakeWhile iterates through values from an iterable as long as a given predicate is true. + +struct TakeWhile{I} + cond::Function + xs::I +end + +""" + takewhile(cond, xs) + +An iterator that yields values from the iterator `xs` as long as the +predicate `cond` is true. + +```jldoctest +julia> collect(takewhile(x-> x^2 < 10, 1:100) +3-element Array{Any,1}: + 1 + 2 + 3 +""" + +takewhile(cond, xs) = TakeWhile(cond, xs) + +function Base.iterate(it::TakeWhile, state=nothing) + (val, state) = state == nothing ? iterate(it.xs) : iterate(it.xs, state) + it.cond(val) || return nothing + val, state +end + +Base.IteratorSize(it::TakeWhile) = Base.SizeUnknown() + +end # module IterTools + end # module IterTools From a09beba35cd70fb566264c99dfb051a3a3285ecd Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Mon, 17 Dec 2018 23:38:12 +0100 Subject: [PATCH 02/10] Added takewhile --- docs/src/index.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/src/index.md b/docs/src/index.md index 488339f..56c9abf 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -117,6 +117,14 @@ Equivalent to `take`, but will throw an exception if fewer than `n` items are en takestrict ``` +## takewhile(cond, xs) + +Iterates through values from the iterable `xs` as long as a given predicate `cond` is true. + +```@docs +takewhile +``` + ## flagfirst(xs) Provide a flag to check if this is the first element. From eb586387b6d12913e7deb8b5e1fc8fa84f263e2b Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Mon, 17 Dec 2018 23:39:13 +0100 Subject: [PATCH 03/10] added testset "takewhile" --- test/runtests.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index bc09dc2..89c4c93 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -407,5 +407,11 @@ include("testing_macros.jl") @test collect(flagfirst(Int[])) == Tuple{Bool,Int}[] end + + @testset "takewhile" begin + @test collect(takewhile(x -> x^2 < 10, 1:10)) == Any[1, 2, 3] + @test collect(takewhile(x -> x^2 < 10, Iterators.countfrom(1))) == Any[1, 2, 3] + @test collect(takewhile(x -> x^2 < 10, 5:10)) == Any[] + end end end From 995472f035d766198a2b01b52cc6498cf713ae6c Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Mon, 17 Dec 2018 23:48:54 +0100 Subject: [PATCH 04/10] removed duplicate 'end' --- src/IterTools.jl | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index 145033a..9c5c642 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -905,5 +905,3 @@ end Base.IteratorSize(it::TakeWhile) = Base.SizeUnknown() end # module IterTools - -end # module IterTools From 5b8b790790ba481822d5d7934ee877f6c56c6ac7 Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Tue, 18 Dec 2018 00:13:17 +0100 Subject: [PATCH 05/10] removed blank line as per ararslan's comment --- src/IterTools.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index 9c5c642..42807a5 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -893,7 +893,6 @@ julia> collect(takewhile(x-> x^2 < 10, 1:100) 2 3 """ - takewhile(cond, xs) = TakeWhile(cond, xs) function Base.iterate(it::TakeWhile, state=nothing) From 488c0508bf6b5b2ec29453876cef5ceceab2016a Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Tue, 18 Dec 2018 00:16:51 +0100 Subject: [PATCH 06/10] Added takewhile to list of exports --- src/IterTools.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index 42807a5..8085d44 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -25,7 +25,8 @@ export peek, ncycle, ivec, - flagfirst + flagfirst, + takewhile function has_length(it) it_size = IteratorSize(it) From 2fcfd83de43f3d3a18aa3136e7f94d24d2c65712 Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Tue, 18 Dec 2018 19:32:01 +0100 Subject: [PATCH 07/10] Change of == to === as suggested by iamed2 --- src/IterTools.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index 8085d44..7d4fb4d 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -897,7 +897,7 @@ julia> collect(takewhile(x-> x^2 < 10, 1:100) takewhile(cond, xs) = TakeWhile(cond, xs) function Base.iterate(it::TakeWhile, state=nothing) - (val, state) = state == nothing ? iterate(it.xs) : iterate(it.xs, state) + (val, state) = state === nothing ? iterate(it.xs) : iterate(it.xs, state) it.cond(val) || return nothing val, state end From 8099414c07bde3583ba2dabecd8de90828ca3a65 Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Tue, 18 Dec 2018 20:57:55 +0100 Subject: [PATCH 08/10] added @ifsomething to fix bug in limit case --- src/IterTools.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index 7d4fb4d..823568f 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -897,7 +897,7 @@ julia> collect(takewhile(x-> x^2 < 10, 1:100) takewhile(cond, xs) = TakeWhile(cond, xs) function Base.iterate(it::TakeWhile, state=nothing) - (val, state) = state === nothing ? iterate(it.xs) : iterate(it.xs, state) + (val, state) = @ifsomething (state === nothing ? iterate(it.xs) : iterate(it.xs, state)) it.cond(val) || return nothing val, state end From a6f5fd4a19f589b9830b0f2cbfca1ecbf137d30e Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Tue, 18 Dec 2018 21:08:57 +0100 Subject: [PATCH 09/10] added eltype stuff as per iamed2's suggestion --- src/IterTools.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/IterTools.jl b/src/IterTools.jl index 823568f..8b91f12 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -903,5 +903,7 @@ function Base.iterate(it::TakeWhile, state=nothing) end Base.IteratorSize(it::TakeWhile) = Base.SizeUnknown() +eltype(::Type{TakeWhile{I}}) where {I} = eltype(I) +IteratorEltype(::Type{TakeWhile{I}}) where {I} = IteratorEltype(I) end # module IterTools From 16699eecd03cf090f8d826aad4a14f9aa521ade7 Mon Sep 17 00:00:00 2001 From: Reiner Martin Date: Tue, 18 Dec 2018 21:09:45 +0100 Subject: [PATCH 10/10] added test case which was failing in earlier version --- test/runtests.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/runtests.jl b/test/runtests.jl index 89c4c93..26f04b1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -412,6 +412,7 @@ include("testing_macros.jl") @test collect(takewhile(x -> x^2 < 10, 1:10)) == Any[1, 2, 3] @test collect(takewhile(x -> x^2 < 10, Iterators.countfrom(1))) == Any[1, 2, 3] @test collect(takewhile(x -> x^2 < 10, 5:10)) == Any[] + @test collect(takewhile(x -> true, 5:10)) == collect(5:10) end end end