From c1ce2ff63e431134f75c5fb6ba6a129d743cc8f3 Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Mon, 27 Jul 2020 20:54:04 +0200 Subject: [PATCH 1/7] Add each-function --- src/IterTools.jl | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index f8f11d2..e0c71ec 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -30,7 +30,8 @@ export takewhile, properties, propertyvalues, - fieldvalues + fieldvalues, + each function has_length(it) it_size = IteratorSize(it) @@ -1031,4 +1032,31 @@ function iterate(fs::FieldValues, state=1) return (getfield(fs.x, state), state + 1) end +""" + each(ElementType::Type, element::ElementType) + each(ElementType::Type, collection) + +Return `element` wrapped in a `Tuple` or the `collection` if it has `eltype<:ElementType`. +Otherwise throw an error. +`eltype(each(T,collection)) <: T`, even if `eltype(collection)` is not. + +# Examples +```jldoctest +julia> println.(each(Tuple, [(1, 2), (3, 4)])); +(1, 2) +(3, 4) + +julia> println.(each(Tuple, (1, 2))); +(1, 2) + +julia> println.(each(String, (1, 2))); +ERROR: ArgumentError +``` +""" +function each(::Type{T}, collection) where T + eltype(collection) <:T && return collection + throw(ArgumentError("$(typeof(collection)) does not contain elements of type $T")) +end +each(::Type{T}, element::T) where T = (element,) + end # module IterTools From f19769ea2404d9e38abc8a9693ef12dca064ceaa Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Mon, 27 Jul 2020 21:26:49 +0200 Subject: [PATCH 2/7] Added tests for each --- test/runtests.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 2fa7de9..7a44f3a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -554,5 +554,11 @@ include("testing_macros.jl") @test IteratorSize(typeof(g)) == IteratorSize(typeof(iter)) end end + + @testset "each" begin + @test each(Tuple,[(1,2),(1,2)]) == [(1,2),(1,2)] + @test each(Tuple,(1,2)) == ((1,2),) + @test_throws ArgumentError each(Tuple,["something"]) + end end end From 7bca46619c4b08140224389a3e85f96755ad1df1 Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Mon, 27 Jul 2020 22:50:40 +0200 Subject: [PATCH 3/7] Change each to use try and convert --- src/IterTools.jl | 14 +++++++++----- test/runtests.jl | 3 ++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index e0c71ec..daff17e 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -1050,13 +1050,17 @@ julia> println.(each(Tuple, (1, 2))); (1, 2) julia> println.(each(String, (1, 2))); -ERROR: ArgumentError +ERROR: MethodError: Cannot `convert` an object of type Array{Int64,1} to an object of type String +[...] ``` """ -function each(::Type{T}, collection) where T - eltype(collection) <:T && return collection - throw(ArgumentError("$(typeof(collection)) does not contain elements of type $T")) +function each(::Type{T},collection) where T + try + out = convert(T,collection) + return (out,) + catch MethodError + out = convert.(T,collection) + end end -each(::Type{T}, element::T) where T = (element,) end # module IterTools diff --git a/test/runtests.jl b/test/runtests.jl index 7a44f3a..d58a1fe 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -558,7 +558,8 @@ include("testing_macros.jl") @testset "each" begin @test each(Tuple,[(1,2),(1,2)]) == [(1,2),(1,2)] @test each(Tuple,(1,2)) == ((1,2),) - @test_throws ArgumentError each(Tuple,["something"]) + @test_throws MethodError each(Tuple,["something"]) + @test eltype(each(Int32,(1,2))) == Int32 end end end From 615e8872a5f5157215703a5ccfcf55d8917cd731 Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Mon, 27 Jul 2020 22:59:57 +0200 Subject: [PATCH 4/7] cleaned up each --- src/IterTools.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index daff17e..3fe666d 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -1056,10 +1056,9 @@ ERROR: MethodError: Cannot `convert` an object of type Array{Int64,1} to an obje """ function each(::Type{T},collection) where T try - out = convert(T,collection) - return (out,) + return (convert(T,collection),) catch MethodError - out = convert.(T,collection) + return convert.(T,collection) end end From bcfff3f8b847a79ce7764d77ac7963314e684fd3 Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Sun, 2 Aug 2020 19:20:44 +0200 Subject: [PATCH 5/7] Update documentation --- src/IterTools.jl | 99 ++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index 3fe666d..f8a548b 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -9,29 +9,29 @@ import Base: SizeUnknown, IsInfinite, HasLength, HasShape import Base: HasEltype, EltypeUnknown export - firstrest, - takestrict, - repeatedly, - chain, - product, - distinct, - partition, - groupby, - imap, - subsets, - iterated, - nth, - takenth, - peekiter, - peek, - ncycle, - ivec, - flagfirst, - takewhile, - properties, - propertyvalues, - fieldvalues, - each +firstrest, +takestrict, +repeatedly, +chain, +product, +distinct, +partition, +groupby, +imap, +subsets, +iterated, +nth, +takenth, +peekiter, +peek, +ncycle, +ivec, +flagfirst, +takewhile, +properties, +propertyvalues, +fieldvalues, +each function has_length(it) it_size = IteratorSize(it) @@ -224,7 +224,7 @@ Iterate through values skipping over those already encountered. ```jldoctest julia> for i in distinct([1,1,2,1,2,4,1,2,3,4]) - @show i + @show i end i = 1 i = 2 @@ -272,7 +272,7 @@ Group values into `n`-tuples. ```jldoctest julia> for i in partition(1:9, 3) - @show i + @show i end i = (1, 2, 3) i = (4, 5, 6) @@ -283,7 +283,7 @@ If the `step` parameter is set, each tuple is separated by `step` values. ```jldoctest julia> for i in partition(1:9, 3, 2) - @show i + @show i end i = (1, 2, 3) i = (3, 4, 5) @@ -291,14 +291,14 @@ i = (5, 6, 7) i = (7, 8, 9) julia> for i in partition(1:9, 3, 3) - @show i + @show i end i = (1, 2, 3) i = (4, 5, 6) i = (7, 8, 9) julia> for i in partition(1:9, 2, 3) - @show i + @show i end i = (1, 2) i = (4, 5) @@ -379,7 +379,7 @@ Group consecutive values that share the same result of applying `f`. ```jldoctest julia> for i in groupby(x -> x[1], ["face", "foo", "bar", "book", "baz", "zzz"]) - @show i + @show i end i = ["face", "foo"] i = ["bar", "book", "baz"] @@ -435,7 +435,7 @@ exhausted. ```jldoctest julia> for i in imap(+, [1,2,3], [4,5,6]) - @show i + @show i end i = 5 i = 7 @@ -469,7 +469,7 @@ otherwise. ```jldoctest julia> for i in subsets([1, 2, 3]) - @show i + @show i end i = Int64[] i = [1] @@ -481,7 +481,7 @@ i = [2, 3] i = [1, 2, 3] julia> for i in subsets(1:4, 2) - @show i + @show i end i = [1, 2] i = [1, 3] @@ -491,7 +491,7 @@ i = [2, 4] i = [3, 4] julia> for i in subsets(1:4, Val{2}()) - @show i + @show i end i = (1, 2) i = (1, 3) @@ -591,14 +591,14 @@ iterate(it::StaticSizeBinomial{0}, state=false) = state ? nothing : ((), true) pop(t::NTuple) = reverse(tail(reverse(t))), t[end] function advance(it::StaticSizeBinomial{K}, idx) where {K} - xs = it.xs - lidx, i = pop(idx) + xs = it.xs + lidx, i = pop(idx) i += 1 - if i > length(xs) - K + length(idx) - lidx = advance(it, lidx) - i = lidx[end] + 1 - end - return (lidx..., i) + if i > length(xs) - K + length(idx) + lidx = advance(it, lidx) + i = lidx[end] + 1 + end + return (lidx..., i) end advance(it::StaticSizeBinomial, idx::NTuple{1}) = (idx[end]+1,) @@ -707,7 +707,7 @@ Use `Base.Iterators.take()` to obtain the required number of elements. ```jldoctest julia> for i in Iterators.take(iterated(x -> 2x, 1), 5) - @show i + @show i end i = 1 i = 2 @@ -716,7 +716,7 @@ i = 8 i = 16 julia> for i in Iterators.take(iterated(sqrt, 100), 6) - @show i + @show i end i = 100 i = 10.0 @@ -794,7 +794,7 @@ Cycle through `iter` `n` times. ```jldoctest julia> for i in ncycle(1:3, 2) - @show i + @show i end i = 1 i = 2 @@ -1033,12 +1033,11 @@ function iterate(fs::FieldValues, state=1) end """ - each(ElementType::Type, element::ElementType) each(ElementType::Type, collection) -Return `element` wrapped in a `Tuple` or the `collection` if it has `eltype<:ElementType`. -Otherwise throw an error. -`eltype(each(T,collection)) <: T`, even if `eltype(collection)` is not. +If `collection` can be `convert`ed into `ElementType`, it is converted and wrapped in a +`Tuple{ElementType}`. Otherwise, the *elements* of `collection` are converted into +`ElementType`. # Examples ```jldoctest @@ -1050,14 +1049,14 @@ julia> println.(each(Tuple, (1, 2))); (1, 2) julia> println.(each(String, (1, 2))); -ERROR: MethodError: Cannot `convert` an object of type Array{Int64,1} to an object of type String +ERROR: MethodError: Cannot `convert` an object of type Int64 to an object of type String [...] ``` """ function each(::Type{T},collection) where T - try + try return (convert(T,collection),) - catch MethodError + catch return convert.(T,collection) end end From 26c442b8aaff7198397435a3fc0562f05cc9efb3 Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Sun, 2 Aug 2020 19:28:42 +0200 Subject: [PATCH 6/7] squash! cleaned up each --- src/IterTools.jl | 72 ++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index f8a548b..5959e6f 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -9,29 +9,29 @@ import Base: SizeUnknown, IsInfinite, HasLength, HasShape import Base: HasEltype, EltypeUnknown export -firstrest, -takestrict, -repeatedly, -chain, -product, -distinct, -partition, -groupby, -imap, -subsets, -iterated, -nth, -takenth, -peekiter, -peek, -ncycle, -ivec, -flagfirst, -takewhile, -properties, -propertyvalues, -fieldvalues, -each + firstrest, + takestrict, + repeatedly, + chain, + product, + distinct, + partition, + groupby, + imap, + subsets, + iterated, + nth, + takenth, + peekiter, + peek, + ncycle, + ivec, + flagfirst, + takewhile, + properties, + propertyvalues, + fieldvalues, + each function has_length(it) it_size = IteratorSize(it) @@ -224,7 +224,7 @@ Iterate through values skipping over those already encountered. ```jldoctest julia> for i in distinct([1,1,2,1,2,4,1,2,3,4]) - @show i + @show i end i = 1 i = 2 @@ -272,7 +272,7 @@ Group values into `n`-tuples. ```jldoctest julia> for i in partition(1:9, 3) - @show i + @show i end i = (1, 2, 3) i = (4, 5, 6) @@ -283,7 +283,7 @@ If the `step` parameter is set, each tuple is separated by `step` values. ```jldoctest julia> for i in partition(1:9, 3, 2) - @show i + @show i end i = (1, 2, 3) i = (3, 4, 5) @@ -291,14 +291,14 @@ i = (5, 6, 7) i = (7, 8, 9) julia> for i in partition(1:9, 3, 3) - @show i + @show i end i = (1, 2, 3) i = (4, 5, 6) i = (7, 8, 9) julia> for i in partition(1:9, 2, 3) - @show i + @show i end i = (1, 2) i = (4, 5) @@ -379,7 +379,7 @@ Group consecutive values that share the same result of applying `f`. ```jldoctest julia> for i in groupby(x -> x[1], ["face", "foo", "bar", "book", "baz", "zzz"]) - @show i + @show i end i = ["face", "foo"] i = ["bar", "book", "baz"] @@ -435,7 +435,7 @@ exhausted. ```jldoctest julia> for i in imap(+, [1,2,3], [4,5,6]) - @show i + @show i end i = 5 i = 7 @@ -469,7 +469,7 @@ otherwise. ```jldoctest julia> for i in subsets([1, 2, 3]) - @show i + @show i end i = Int64[] i = [1] @@ -481,7 +481,7 @@ i = [2, 3] i = [1, 2, 3] julia> for i in subsets(1:4, 2) - @show i + @show i end i = [1, 2] i = [1, 3] @@ -491,7 +491,7 @@ i = [2, 4] i = [3, 4] julia> for i in subsets(1:4, Val{2}()) - @show i + @show i end i = (1, 2) i = (1, 3) @@ -707,7 +707,7 @@ Use `Base.Iterators.take()` to obtain the required number of elements. ```jldoctest julia> for i in Iterators.take(iterated(x -> 2x, 1), 5) - @show i + @show i end i = 1 i = 2 @@ -716,7 +716,7 @@ i = 8 i = 16 julia> for i in Iterators.take(iterated(sqrt, 100), 6) - @show i + @show i end i = 100 i = 10.0 @@ -794,7 +794,7 @@ Cycle through `iter` `n` times. ```jldoctest julia> for i in ncycle(1:3, 2) - @show i + @show i end i = 1 i = 2 From 32efa265ec3dcc6fb64a062e329beb75b45f5919 Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Tue, 18 Aug 2020 08:43:06 +0200 Subject: [PATCH 7/7] Add test for function with changed indentation --- test/runtests.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/runtests.jl b/test/runtests.jl index d58a1fe..33094c3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -320,6 +320,7 @@ include("testing_macros.jl") @test eltype(eltype(sk5)) == Int @test length(collect(sk5)) == binomial(4, i) end + @test iterate(subsets(collect(1:4),Val{2}()),(1,4)) == ((1,4), (2,3)) function collect_pairs(x) p = Vector{NTuple{2, eltype(x)}}(undef, binomial(length(x), 2))