From 49e0cfc56320b099a5727e95e1dfce632dcdc25a Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Tue, 29 Mar 2022 21:36:06 +0200 Subject: [PATCH 01/14] Implements a flatmap functor, and iteration methods for Some and Nothing --- base/iterators.jl | 53 +++++++++++++++++++++++++++++++++++++++++++++++ test/iterators.jl | 10 +++++++++ 2 files changed, 63 insertions(+) diff --git a/base/iterators.jl b/base/iterators.jl index 1b96a24a9c16f..d2101c5e0bc30 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1162,6 +1162,59 @@ end reverse(f::Flatten) = Flatten(reverse(itr) for itr in reverse(f.it)) last(f::Flatten) = last(last(f.it)) +""" + Iterators.flatmap(f, iterators...) + +Equivalent to flatten(map(f, iterators...)). + +# Examples +```jldoctest +julia> flatmap(n->-n:2:n, 1:3) |> collect +9-element Vector{Int64}: + -1 + 1 + -2 + 0 + 2 + -3 + -1 + 1 + 3 + +julia> flatmap(x -> (x+1)*x % 4 == 0 ? x*x : nothing, 1:11) |> collect +5-element Vector{Int64}: + 9 + 16 + 49 + 64 + 121 + +julia> [(j,k) for j in 1:3 for k in 1:3 if j>k] +3-element Vector{Tuple{Int64, Int64}}: + (2, 1) + (3, 1) + (3, 2) + +julia> flatmap(1:3) do j + flatmap(1:3) do k + j>k ? Some((j,k)) : nothing + end + end |> collect +3-element Vector{Tuple{Int64, Int64}}: + (2, 1) + (3, 1) + (3, 2) +``` +""" +# flatmap(f, c...) = flatten(map(f, c...)) +flatmap = flatten ∘ map + +# Allows filtering through `flatten` (or `flatmap`) by removing `nothing` values +iterate(_::Nothing) = nothing +iterate(x::Some{T}) where T = (something(x), nothing) +iterate(x::Some{T}, state::Nothing) where T = nothing +length(x::Some{T}) where T = 1 + """ partition(collection, n) diff --git a/test/iterators.jl b/test/iterators.jl index 70ce6866f4be3..ff705d32fed2e 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -469,6 +469,8 @@ end @test length(flatten(1:6)) == 6 @test collect(flatten(Any[])) == Any[] @test collect(flatten(())) == Union{}[] +@test collect(flatten([Some(1)])) == [1] +@test collect(flatten([nothing])) == Any[] @test_throws ArgumentError length(flatten(NTuple[(1,), ()])) # #16680 @test_throws ArgumentError length(flatten([[1], [1]])) @@ -476,6 +478,14 @@ end # see #29112, #29464, #29548 @test Base.return_types(Base.IteratorEltype, Tuple{Array}) == [Base.HasEltype] +# flatmap +# ------- +@test flatmap(1:3) do j + flatmap(1:3) do k + j>k ? Some((j,k)) : nothing + end + end |> collect == [(j,k) for j in 1:3 for k in 1:3 if j>k] + # partition(c, n) let v = collect(partition([1,2,3,4,5], 1)) @test all(i->v[i][1] == i, v) From 69f4bd8eb4e8041e9e4e12a44e89768457de7889 Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Tue, 29 Mar 2022 22:06:30 +0200 Subject: [PATCH 02/14] Implements flatmap and iteration methods for Some and Nothing flatmap is the composition of map and flatten. It is important for functional programming patterns. Some tasks that can be easily attained with list-comprehensions, including the composition of filter and mapping, or flattening a list of computed lists, can only be attained with do-syntax style if a flatmap functor is available. (Or appending a `|> flatten`, etc.) Filtering can be implemented by outputing empty lists or singleton lists for the values to be removed or kept. A more proper approach would be the optional monad, though, usually implemented in Julia as a union of Some and Nothing. This patch therefore also implements iteration methods for Some and Nothing, to enable the filtermap pattern with flatmap. --- base/iterators.jl | 7 ++----- base/some.jl | 5 +++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/base/iterators.jl b/base/iterators.jl index d2101c5e0bc30..ac53b4d36886e 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1206,14 +1206,11 @@ julia> flatmap(1:3) do j (3, 2) ``` """ -# flatmap(f, c...) = flatten(map(f, c...)) -flatmap = flatten ∘ map +# flatmap = flatten ∘ map +flatmap(f, c...) = flatten(map(f, c...)) # Allows filtering through `flatten` (or `flatmap`) by removing `nothing` values iterate(_::Nothing) = nothing -iterate(x::Some{T}) where T = (something(x), nothing) -iterate(x::Some{T}, state::Nothing) where T = nothing -length(x::Some{T}) where T = 1 """ partition(collection, n) diff --git a/base/some.jl b/base/some.jl index 8be58739a4df4..c3be079f2dded 100644 --- a/base/some.jl +++ b/base/some.jl @@ -143,3 +143,8 @@ macro something(args...) something = GlobalRef(Base, :something) return :($something($expr)) end + +# Allows filtering through `flatten` (or `flatmap`) by retaining `Some` values +iterate(x::Some{T}) where T = (something(x), nothing) +iterate(x::Some{T}, state::Nothing) where T = nothing +length(x::Some{T}) where T = 1 From 1b005a94a404dbc2b63623f087a42e79e731b5a8 Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Sat, 2 Apr 2022 11:55:12 +0200 Subject: [PATCH 03/14] removing Some and Nothing iterate methods and adding astuple method --- base/experimental.jl | 43 +++++++++++++++++++++++++++++++++++++++++++ base/iterators.jl | 3 --- base/some.jl | 5 ----- test/iterators.jl | 11 ++++------- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/base/experimental.jl b/base/experimental.jl index 9edd197c198e9..7861c628bbe27 100644 --- a/base/experimental.jl +++ b/base/experimental.jl @@ -359,4 +359,47 @@ adding them to the global method table. """ :@MethodTable +""" + astuple(x::Union{X, Nothing}) + +Converts values so that `nothing` becomes `()` and any other values are wrapped into a singleton tuple. + +# Example + +``` +julia> data = match.(r"(x.?)", ["x", "aoeu", "xoxo", ">>=", ";qjkx"]) +5-element Vector{Union{Nothing, RegexMatch}}: + RegexMatch("x", 1="x") + nothing + RegexMatch("xo", 1="xo") + nothing + RegexMatch("x", 1="x") + +julia> filter(!isnothing, data) +3-element Vector{Union{Nothing, RegexMatch}}: + RegexMatch("x", 1="x") + RegexMatch("xo", 1="xo") + RegexMatch("x", 1="x") + +julia> collect(Iterators.flatten(astuple.(data))) +3-element Vector{RegexMatch}: + RegexMatch("x", 1="x") + RegexMatch("xo", 1="xo") + RegexMatch("x", 1="x") + +julia> [optx for optx in data if !isnothing(optx) && optx[1] != "x"] +1-element Vector{RegexMatch}: + RegexMatch("xo", 1="xo") + +julia> Iterators.flatmap(astuple.(data)) do optx + Iterators.flatmap(optx) do x + x[1] == "x" ? () : (x,) + end + end |> collect +1-element Vector{RegexMatch}: + RegexMatch("xo", 1="xo") +``` +""" +astuple(x::Union{X, Nothing}) where {X} = isnothing(x) ? () : (x,) + end diff --git a/base/iterators.jl b/base/iterators.jl index ac53b4d36886e..90b7d84fa47b7 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1209,9 +1209,6 @@ julia> flatmap(1:3) do j # flatmap = flatten ∘ map flatmap(f, c...) = flatten(map(f, c...)) -# Allows filtering through `flatten` (or `flatmap`) by removing `nothing` values -iterate(_::Nothing) = nothing - """ partition(collection, n) diff --git a/base/some.jl b/base/some.jl index c3be079f2dded..8be58739a4df4 100644 --- a/base/some.jl +++ b/base/some.jl @@ -143,8 +143,3 @@ macro something(args...) something = GlobalRef(Base, :something) return :($something($expr)) end - -# Allows filtering through `flatten` (or `flatmap`) by retaining `Some` values -iterate(x::Some{T}) where T = (something(x), nothing) -iterate(x::Some{T}, state::Nothing) where T = nothing -length(x::Some{T}) where T = 1 diff --git a/test/iterators.jl b/test/iterators.jl index ff705d32fed2e..acc906d1543c6 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -469,8 +469,7 @@ end @test length(flatten(1:6)) == 6 @test collect(flatten(Any[])) == Any[] @test collect(flatten(())) == Union{}[] -@test collect(flatten([Some(1)])) == [1] -@test collect(flatten([nothing])) == Any[] +@test collect(flatten(astuple.([1,nothing]))) == [1] @test_throws ArgumentError length(flatten(NTuple[(1,), ()])) # #16680 @test_throws ArgumentError length(flatten([[1], [1]])) @@ -480,11 +479,9 @@ end # flatmap # ------- -@test flatmap(1:3) do j - flatmap(1:3) do k - j>k ? Some((j,k)) : nothing - end - end |> collect == [(j,k) for j in 1:3 for k in 1:3 if j>k] +@test flatmap(1:3) do j flatmap(1:3) do k + j!=k ? ((j,k),) : () +end end |> collect == [(j,k) for j in 1:3 for k in 1:3 if j!=k] # partition(c, n) let v = collect(partition([1,2,3,4,5], 1)) From f2f1523be9601b966f6818c959edb329ef95d5dc Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Sat, 2 Apr 2022 12:30:12 +0200 Subject: [PATCH 04/14] docstring fix --- base/iterators.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/iterators.jl b/base/iterators.jl index 90b7d84fa47b7..f5a085c7d3e55 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1195,9 +1195,9 @@ julia> [(j,k) for j in 1:3 for k in 1:3 if j>k] (3, 1) (3, 2) -julia> flatmap(1:3) do j - flatmap(1:3) do k - j>k ? Some((j,k)) : nothing +julia> Iterators.flatmap(1:3) do j + Iterators.flatmap(1:3) do k + j>k ? ((j,k),) : () end end |> collect 3-element Vector{Tuple{Int64, Int64}}: From dde1f9c9715ce4d3903430393f3dc83ff55ee2a0 Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Sat, 2 Apr 2022 12:35:23 +0200 Subject: [PATCH 05/14] docstring fix --- base/iterators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/iterators.jl b/base/iterators.jl index f5a085c7d3e55..64e717c954aed 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1181,7 +1181,7 @@ julia> flatmap(n->-n:2:n, 1:3) |> collect 1 3 -julia> flatmap(x -> (x+1)*x % 4 == 0 ? x*x : nothing, 1:11) |> collect +julia> flatmap(x -> (x+1)*x % 4 == 0 ? (x*x,) : (), 1:11) |> collect 5-element Vector{Int64}: 9 16 From a53a103edb2944eab7c09493a38ee7b59aae1bbc Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Sat, 2 Apr 2022 15:00:03 +0200 Subject: [PATCH 06/14] Moved astuple to base/tuple.jl --- base/experimental.jl | 43 ------------------------------------------- base/tuple.jl | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 43 deletions(-) diff --git a/base/experimental.jl b/base/experimental.jl index 7861c628bbe27..9edd197c198e9 100644 --- a/base/experimental.jl +++ b/base/experimental.jl @@ -359,47 +359,4 @@ adding them to the global method table. """ :@MethodTable -""" - astuple(x::Union{X, Nothing}) - -Converts values so that `nothing` becomes `()` and any other values are wrapped into a singleton tuple. - -# Example - -``` -julia> data = match.(r"(x.?)", ["x", "aoeu", "xoxo", ">>=", ";qjkx"]) -5-element Vector{Union{Nothing, RegexMatch}}: - RegexMatch("x", 1="x") - nothing - RegexMatch("xo", 1="xo") - nothing - RegexMatch("x", 1="x") - -julia> filter(!isnothing, data) -3-element Vector{Union{Nothing, RegexMatch}}: - RegexMatch("x", 1="x") - RegexMatch("xo", 1="xo") - RegexMatch("x", 1="x") - -julia> collect(Iterators.flatten(astuple.(data))) -3-element Vector{RegexMatch}: - RegexMatch("x", 1="x") - RegexMatch("xo", 1="xo") - RegexMatch("x", 1="x") - -julia> [optx for optx in data if !isnothing(optx) && optx[1] != "x"] -1-element Vector{RegexMatch}: - RegexMatch("xo", 1="xo") - -julia> Iterators.flatmap(astuple.(data)) do optx - Iterators.flatmap(optx) do x - x[1] == "x" ? () : (x,) - end - end |> collect -1-element Vector{RegexMatch}: - RegexMatch("xo", 1="xo") -``` -""" -astuple(x::Union{X, Nothing}) where {X} = isnothing(x) ? () : (x,) - end diff --git a/base/tuple.jl b/base/tuple.jl index 3803763960c16..5a89e625d9aa5 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -554,3 +554,46 @@ empty(@nospecialize x::Tuple) = () foreach(f, itr::Tuple) = foldl((_, x) -> (f(x); nothing), itr, init=nothing) foreach(f, itrs::Tuple...) = foldl((_, xs) -> (f(xs...); nothing), zip(itrs...), init=nothing) + +""" + astuple(x::Union{X, Nothing}) + +Converts values so that `nothing` becomes `()` and any other values are wrapped into a singleton tuple. + +# Example + +``` +julia> data = match.(r"(x.?)", ["x", "aoeu", "xoxo", ">>=", ";qjkx"]) +5-element Vector{Union{Nothing, RegexMatch}}: + RegexMatch("x", 1="x") + nothing + RegexMatch("xo", 1="xo") + nothing + RegexMatch("x", 1="x") + +julia> filter(!isnothing, data) +3-element Vector{Union{Nothing, RegexMatch}}: + RegexMatch("x", 1="x") + RegexMatch("xo", 1="xo") + RegexMatch("x", 1="x") + +julia> collect(Iterators.flatten(astuple.(data))) +3-element Vector{RegexMatch}: + RegexMatch("x", 1="x") + RegexMatch("xo", 1="xo") + RegexMatch("x", 1="x") + +julia> [optx for optx in data if !isnothing(optx) && optx[1] != "x"] +1-element Vector{RegexMatch}: + RegexMatch("xo", 1="xo") + +julia> Iterators.flatmap(astuple.(data)) do optx + Iterators.flatmap(optx) do x + x[1] == "x" ? () : (x,) + end + end |> collect +1-element Vector{RegexMatch}: + RegexMatch("xo", 1="xo") +``` +""" +astuple(x::Union{X, Nothing}) where {X} = isnothing(x) ? () : (x,) From ddda481f48046d155eb30181a7de417abf3dfdca Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Sat, 2 Apr 2022 16:09:16 +0200 Subject: [PATCH 07/14] Added a second test for flatmap --- test/iterators.jl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/iterators.jl b/test/iterators.jl index acc906d1543c6..2f18fd4a375fd 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -482,6 +482,23 @@ end @test flatmap(1:3) do j flatmap(1:3) do k j!=k ? ((j,k),) : () end end |> collect == [(j,k) for j in 1:3 for k in 1:3 if j!=k] +# Test inspired by the monad associativity law +fmf(x) = x<0 ? () : (x^2,) +fmg(x) = x<1 ? () : (x/2,) +fmdata = -2:0.75:2 +fmv1 = flatmap(tuple.(fmdata)) do h + flatmap(h) do x + fx = fmg(x) + flatmap(fx) do x + fmf(x) + end + end +end +fmv2 = flatmap(tuple.(fmdata)) do h + fh = flatmap(h) do x fmg(x) end + flatmap(fh) do x fmf(x) end +end +@test all(fmv1 .== fmv2) # partition(c, n) let v = collect(partition([1,2,3,4,5], 1)) From 38fa2e3024c3e4de85c2f851176b852c242a2f6b Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Sun, 3 Apr 2022 14:36:02 +0200 Subject: [PATCH 08/14] renamed astuple to monuple and added exports --- base/exports.jl | 1 + base/iterators.jl | 2 +- base/tuple.jl | 10 +++++----- test/iterators.jl | 10 +++++----- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/base/exports.jl b/base/exports.jl index dff6b0c9bc208..3f4d68e5164e9 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -716,6 +716,7 @@ export something, isnothing, nonmissingtype, + monuple, # time sleep, diff --git a/base/iterators.jl b/base/iterators.jl index 64e717c954aed..432a6288b0d45 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -22,7 +22,7 @@ import .Base: getindex, setindex!, get, iterate, popfirst!, isdone, peek -export enumerate, zip, rest, countfrom, take, drop, takewhile, dropwhile, cycle, repeated, product, flatten, partition +export enumerate, zip, rest, countfrom, take, drop, takewhile, dropwhile, cycle, repeated, product, flatten, partition, flatmap """ Iterators.map(f, iterators...) diff --git a/base/tuple.jl b/base/tuple.jl index 5a89e625d9aa5..6502bd783e521 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -556,9 +556,9 @@ foreach(f, itr::Tuple) = foldl((_, x) -> (f(x); nothing), itr, init=nothing) foreach(f, itrs::Tuple...) = foldl((_, xs) -> (f(xs...); nothing), zip(itrs...), init=nothing) """ - astuple(x::Union{X, Nothing}) + monuple(x::Union{X, Nothing}) -Converts values so that `nothing` becomes `()` and any other values are wrapped into a singleton tuple. +Converts values so that `nothing` becomes `()` and any other values are wrapped into a singleton tuple, also known as a monuple. # Example @@ -577,7 +577,7 @@ julia> filter(!isnothing, data) RegexMatch("xo", 1="xo") RegexMatch("x", 1="x") -julia> collect(Iterators.flatten(astuple.(data))) +julia> collect(Iterators.flatten(monuple.(data))) 3-element Vector{RegexMatch}: RegexMatch("x", 1="x") RegexMatch("xo", 1="xo") @@ -587,7 +587,7 @@ julia> [optx for optx in data if !isnothing(optx) && optx[1] != "x"] 1-element Vector{RegexMatch}: RegexMatch("xo", 1="xo") -julia> Iterators.flatmap(astuple.(data)) do optx +julia> Iterators.flatmap(monuple.(data)) do optx Iterators.flatmap(optx) do x x[1] == "x" ? () : (x,) end @@ -596,4 +596,4 @@ julia> Iterators.flatmap(astuple.(data)) do optx RegexMatch("xo", 1="xo") ``` """ -astuple(x::Union{X, Nothing}) where {X} = isnothing(x) ? () : (x,) +monuple(x::Union{X, Nothing}) where {X} = isnothing(x) ? () : (x,) diff --git a/test/iterators.jl b/test/iterators.jl index 2f18fd4a375fd..74a4cff49ecd7 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -469,7 +469,7 @@ end @test length(flatten(1:6)) == 6 @test collect(flatten(Any[])) == Any[] @test collect(flatten(())) == Union{}[] -@test collect(flatten(astuple.([1,nothing]))) == [1] +@test collect(flatten(monuple.([1,nothing]))) == [1] @test_throws ArgumentError length(flatten(NTuple[(1,), ()])) # #16680 @test_throws ArgumentError length(flatten([[1], [1]])) @@ -488,15 +488,15 @@ fmg(x) = x<1 ? () : (x/2,) fmdata = -2:0.75:2 fmv1 = flatmap(tuple.(fmdata)) do h flatmap(h) do x - fx = fmg(x) - flatmap(fx) do x + gx = fmg(x) + flatmap(gx) do x fmf(x) end end end fmv2 = flatmap(tuple.(fmdata)) do h - fh = flatmap(h) do x fmg(x) end - flatmap(fh) do x fmf(x) end + gh = flatmap(h) do x fmg(x) end + flatmap(gh) do x fmf(x) end end @test all(fmv1 .== fmv2) From a69552ffdc1f67561084832a67d70aea27e6ccc3 Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Sun, 3 Apr 2022 16:23:55 +0200 Subject: [PATCH 09/14] trying to pass 'detect_unbound_args in Base and Core' --- base/tuple.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/base/tuple.jl b/base/tuple.jl index 6502bd783e521..f8def9e77f6e1 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -556,7 +556,7 @@ foreach(f, itr::Tuple) = foldl((_, x) -> (f(x); nothing), itr, init=nothing) foreach(f, itrs::Tuple...) = foldl((_, xs) -> (f(xs...); nothing), zip(itrs...), init=nothing) """ - monuple(x::Union{X, Nothing}) + monuple(x) Converts values so that `nothing` becomes `()` and any other values are wrapped into a singleton tuple, also known as a monuple. @@ -596,4 +596,5 @@ julia> Iterators.flatmap(monuple.(data)) do optx RegexMatch("xo", 1="xo") ``` """ -monuple(x::Union{X, Nothing}) where {X} = isnothing(x) ? () : (x,) +monuple(x::Any) = tuple(x) +monuple(::Nothing) = () From 5bff01be8e6c47b3f7c6e977ee100dea10c56e50 Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Tue, 5 Apr 2022 18:04:30 +0200 Subject: [PATCH 10/14] Removing monuple --- base/exports.jl | 1 - base/tuple.jl | 44 -------------------------------------------- test/iterators.jl | 1 - 3 files changed, 46 deletions(-) diff --git a/base/exports.jl b/base/exports.jl index 3f4d68e5164e9..dff6b0c9bc208 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -716,7 +716,6 @@ export something, isnothing, nonmissingtype, - monuple, # time sleep, diff --git a/base/tuple.jl b/base/tuple.jl index f8def9e77f6e1..3803763960c16 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -554,47 +554,3 @@ empty(@nospecialize x::Tuple) = () foreach(f, itr::Tuple) = foldl((_, x) -> (f(x); nothing), itr, init=nothing) foreach(f, itrs::Tuple...) = foldl((_, xs) -> (f(xs...); nothing), zip(itrs...), init=nothing) - -""" - monuple(x) - -Converts values so that `nothing` becomes `()` and any other values are wrapped into a singleton tuple, also known as a monuple. - -# Example - -``` -julia> data = match.(r"(x.?)", ["x", "aoeu", "xoxo", ">>=", ";qjkx"]) -5-element Vector{Union{Nothing, RegexMatch}}: - RegexMatch("x", 1="x") - nothing - RegexMatch("xo", 1="xo") - nothing - RegexMatch("x", 1="x") - -julia> filter(!isnothing, data) -3-element Vector{Union{Nothing, RegexMatch}}: - RegexMatch("x", 1="x") - RegexMatch("xo", 1="xo") - RegexMatch("x", 1="x") - -julia> collect(Iterators.flatten(monuple.(data))) -3-element Vector{RegexMatch}: - RegexMatch("x", 1="x") - RegexMatch("xo", 1="xo") - RegexMatch("x", 1="x") - -julia> [optx for optx in data if !isnothing(optx) && optx[1] != "x"] -1-element Vector{RegexMatch}: - RegexMatch("xo", 1="xo") - -julia> Iterators.flatmap(monuple.(data)) do optx - Iterators.flatmap(optx) do x - x[1] == "x" ? () : (x,) - end - end |> collect -1-element Vector{RegexMatch}: - RegexMatch("xo", 1="xo") -``` -""" -monuple(x::Any) = tuple(x) -monuple(::Nothing) = () diff --git a/test/iterators.jl b/test/iterators.jl index 74a4cff49ecd7..4f0dbe2f9b984 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -469,7 +469,6 @@ end @test length(flatten(1:6)) == 6 @test collect(flatten(Any[])) == Any[] @test collect(flatten(())) == Union{}[] -@test collect(flatten(monuple.([1,nothing]))) == [1] @test_throws ArgumentError length(flatten(NTuple[(1,), ()])) # #16680 @test_throws ArgumentError length(flatten([[1], [1]])) From e73af27eb4ef653073e51ab42f5262af0b89a3b7 Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Wed, 6 Apr 2022 07:58:12 +0200 Subject: [PATCH 11/14] Update base/iterators.jl Co-authored-by: Takafumi Arakaki --- base/iterators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/iterators.jl b/base/iterators.jl index 432a6288b0d45..ee8a6741a7852 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1165,7 +1165,7 @@ last(f::Flatten) = last(last(f.it)) """ Iterators.flatmap(f, iterators...) -Equivalent to flatten(map(f, iterators...)). +Equivalent to `flatten(map(f, iterators...))`. # Examples ```jldoctest From e9947bc0355bc7ac6e86f8d282418ccb9fe8161f Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Wed, 6 Apr 2022 07:58:23 +0200 Subject: [PATCH 12/14] Update base/iterators.jl Co-authored-by: Takafumi Arakaki --- base/iterators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/iterators.jl b/base/iterators.jl index ee8a6741a7852..dc98424ae8ad8 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1181,7 +1181,7 @@ julia> flatmap(n->-n:2:n, 1:3) |> collect 1 3 -julia> flatmap(x -> (x+1)*x % 4 == 0 ? (x*x,) : (), 1:11) |> collect +julia> Iterators.flatmap(x -> (x+1)*x % 4 == 0 ? (x*x,) : (), 1:11) |> collect 5-element Vector{Int64}: 9 16 From 705017f82efac8931bf51d02f84354627ff87378 Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Wed, 6 Apr 2022 08:15:57 +0200 Subject: [PATCH 13/14] Update base/iterators.jl Co-authored-by: Takafumi Arakaki --- base/iterators.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/iterators.jl b/base/iterators.jl index dc98424ae8ad8..cdb50b0058add 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1169,7 +1169,7 @@ Equivalent to `flatten(map(f, iterators...))`. # Examples ```jldoctest -julia> flatmap(n->-n:2:n, 1:3) |> collect +julia> Iterators.flatmap(n->-n:2:n, 1:3) |> collect 9-element Vector{Int64}: -1 1 From a720be0e527486f87db349d70b62694518decd59 Mon Sep 17 00:00:00 2001 From: Nicolau Leal Werneck Date: Wed, 6 Apr 2022 12:03:53 +0200 Subject: [PATCH 14/14] Update base/iterators.jl Co-authored-by: Takafumi Arakaki --- base/iterators.jl | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/base/iterators.jl b/base/iterators.jl index cdb50b0058add..ccb910afa5758 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -1180,30 +1180,6 @@ julia> Iterators.flatmap(n->-n:2:n, 1:3) |> collect -1 1 3 - -julia> Iterators.flatmap(x -> (x+1)*x % 4 == 0 ? (x*x,) : (), 1:11) |> collect -5-element Vector{Int64}: - 9 - 16 - 49 - 64 - 121 - -julia> [(j,k) for j in 1:3 for k in 1:3 if j>k] -3-element Vector{Tuple{Int64, Int64}}: - (2, 1) - (3, 1) - (3, 2) - -julia> Iterators.flatmap(1:3) do j - Iterators.flatmap(1:3) do k - j>k ? ((j,k),) : () - end - end |> collect -3-element Vector{Tuple{Int64, Int64}}: - (2, 1) - (3, 1) - (3, 2) ``` """ # flatmap = flatten ∘ map