From d90a2ac00d6d47b5447730eada07e33ce4f4ba95 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet <fourquet.rafael@gmail.com> Date: Mon, 13 Apr 2020 09:44:09 +0200 Subject: [PATCH 1/2] verbose replace for Tuple --- base/set.jl | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/base/set.jl b/base/set.jl index b6c9765a0b6cc..b0c34af0cbec1 100644 --- a/base/set.jl +++ b/base/set.jl @@ -728,3 +728,73 @@ function _replace!(new::Callable, t::Set{T}, ::AbstractSet, count::Int) where {T end t end + +### replace for tuples + +@inline replace(f::Callable, t::Tuple{}, count::Int) = () +@inline replace(f::Callable, t::Tuple{Any}, count::Int) = + count == 0 ? t : (f(t[1]),) + +@inline replace(f::Callable, t::Tuple{Any,Any}, count::Int) = + if count >= 2 + (f(t[1]), f(t[2])) + elseif count == 0 + t + elseif count == 1 + x = f(t[1]) + x === t[1] ? + (x, f(t[2])) : + (x, t[2]) + end + +@inline replace(f::Callable, t::Tuple{Any,Any,Any}, count::Int) = + if count >= 3 + (f(t[1]), f(t[2]), f(t[3])) + elseif count == 0 + t + else + x = f(t[1]) + if x === t[1] + if count == 1 + y = f(t[2]) + y === t[2] ? + (x, y, f(t[3])) : + (x, y, t[3]) + else # count == 2 + (x, f(t[2]), f(t[3])) + end + elseif count == 1 + (x, t[2], t[3]) + else + y = f(t[2]) + y === t[2] ? + (x, y, f(t[3])) : + (x, y, t[3]) + end + end + +@inline replace(f::Callable, t::Tuple, count::Int) = + if count >= length(t) + map(f, t) + elseif count == 0 + t + else + x = f(t[1]) + (x, _replace(f, tail(t), count - !==(x, t[1]))...) + end + +@inline replace(f::Callable, t::Tuple; count::Integer=typemax(Int)) = + replace(f, t, check_count(count)) + +function replace(t::Tuple, count::Int, old_new::Tuple{Vararg{Pair}}) + @inline function new(x) + for o_n in old_new + isequal(first(o_n), x) && return last(o_n) + end + return x + end + replace(new, t, count) +end + +replace(t::Tuple, old_new::Pair...; count::Integer=typemax(Int)) = + replace(t, check_count(count), old_new) From aa7ce21358ecd2af80adee67dc66f1d652dd5ef3 Mon Sep 17 00:00:00 2001 From: Rafael Fourquet <fourquet.rafael@gmail.com> Date: Wed, 28 Oct 2020 19:29:08 +0100 Subject: [PATCH 2/2] add replace methods for Tuple --- base/set.jl | 61 ++++++++-------------------------------------------- test/sets.jl | 6 ++++++ 2 files changed, 15 insertions(+), 52 deletions(-) diff --git a/base/set.jl b/base/set.jl index b0c34af0cbec1..a04bc106ed1da 100644 --- a/base/set.jl +++ b/base/set.jl @@ -731,70 +731,27 @@ end ### replace for tuples -@inline replace(f::Callable, t::Tuple{}, count::Int) = () -@inline replace(f::Callable, t::Tuple{Any}, count::Int) = - count == 0 ? t : (f(t[1]),) - -@inline replace(f::Callable, t::Tuple{Any,Any}, count::Int) = - if count >= 2 - (f(t[1]), f(t[2])) - elseif count == 0 - t - elseif count == 1 - x = f(t[1]) - x === t[1] ? - (x, f(t[2])) : - (x, t[2]) - end - -@inline replace(f::Callable, t::Tuple{Any,Any,Any}, count::Int) = - if count >= 3 - (f(t[1]), f(t[2]), f(t[3])) - elseif count == 0 - t - else - x = f(t[1]) - if x === t[1] - if count == 1 - y = f(t[2]) - y === t[2] ? - (x, y, f(t[3])) : - (x, y, t[3]) - else # count == 2 - (x, f(t[2]), f(t[3])) - end - elseif count == 1 - (x, t[2], t[3]) - else - y = f(t[2]) - y === t[2] ? - (x, y, f(t[3])) : - (x, y, t[3]) - end - end - -@inline replace(f::Callable, t::Tuple, count::Int) = - if count >= length(t) - map(f, t) - elseif count == 0 +function _replace(f::Callable, t::Tuple, count::Int) + if count == 0 || isempty(t) t else x = f(t[1]) (x, _replace(f, tail(t), count - !==(x, t[1]))...) end +end -@inline replace(f::Callable, t::Tuple; count::Integer=typemax(Int)) = - replace(f, t, check_count(count)) +replace(f::Callable, t::Tuple; count::Integer=typemax(Int)) = + _replace(f, t, check_count(count)) -function replace(t::Tuple, count::Int, old_new::Tuple{Vararg{Pair}}) - @inline function new(x) +function _replace(t::Tuple, count::Int, old_new::Tuple{Vararg{Pair}}) + _replace(t, count) do x + @_inline_meta for o_n in old_new isequal(first(o_n), x) && return last(o_n) end return x end - replace(new, t, count) end replace(t::Tuple, old_new::Pair...; count::Integer=typemax(Int)) = - replace(t, check_count(count), old_new) + _replace(t, check_count(count), old_new) diff --git a/test/sets.jl b/test/sets.jl index 82f2a3b0aab6f..46854dae957c6 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -586,11 +586,14 @@ end @testset "replace! & replace" begin a = [1, 2, 3, 1] @test replace(x -> iseven(x) ? 2x : x, a) == [1, 4, 3, 1] + @test replace(x -> iseven(x) ? 2x : x, Tuple(a)) === (1, 4, 3, 1) @test replace!(x -> iseven(x) ? 2x : x, a) === a @test a == [1, 4, 3, 1] @test replace(a, 1=>0) == [0, 4, 3, 0] + @test replace(Tuple(a), 1=>0) === (0, 4, 3, 0) for count = (1, 0x1, big(1)) @test replace(a, 1=>0, count=count) == [0, 4, 3, 1] + @test replace(Tuple(a), 1=>0, count=count) === (0, 4, 3, 1) end @test replace!(a, 1=>2) === a @test a == [2, 4, 3, 2] @@ -615,6 +618,7 @@ end for count = (0, 0x0, big(0)) # count == 0 --> no replacements @test replace([1, 2], 1=>0, 2=>0; count) == [1, 2] + @test replace((1, 2), 1=>0, 2=>0; count) === (1, 2) for dict = (Dict(1=>2, 2=>3), IdDict(1=>2, 2=>3)) @test replace(dict, (1=>2) => (1=>3); count) == dict end @@ -668,7 +672,9 @@ end # test that isequal is used @test replace([NaN, 1.0], NaN=>0.0) == [0.0, 1.0] + @test replace((NaN, 1.0), NaN=>0.0) === (0.0, 1.0) @test replace([1, missing], missing=>0) == [1, 0] + @test replace((1, missing), missing=>0) === (1, 0) end @testset "⊆, ⊊, ⊈, ⊇, ⊋, ⊉, <, <=, issetequal" begin