From 6dc205a521d789c7d3b34e3508ad2b7f75284ed0 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Fri, 28 Dec 2018 22:06:04 -0500 Subject: [PATCH] faster mapfoldl for tuples (#30471) --- base/tuple.jl | 12 ++++++++++++ test/tuple.jl | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/base/tuple.jl b/base/tuple.jl index 0bdec7547c164..3852ae14368c1 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -212,6 +212,18 @@ function map(f, t1::Any16, t2::Any16, ts::Any16...) (A...,) end +# mapafoldl, based on afold in operators.jl +mapafoldl(F,op,a) = a +mapafoldl(F,op,a,b) = op(a,F(b)) +mapafoldl(F,op,a,b,c...) = mapafoldl(F, op, op(a,F(b)), c...) +function mapafoldl(F,op,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,qs...) + y = op(op(op(op(op(op(op(op(op(op(op(op(op(op(op(a,F(b)),F(c)),F(d)),F(e)),F(f)),F(g)),F(h)),F(i)),F(j)),F(k)),F(l)),F(m)),F(n)),F(o)),F(p)) + for x in qs; y = op(y,F(x)); end + y +end +mapfoldl_impl(f, op, nt::NamedTuple{(:init,)}, t::Tuple) = mapafoldl(f, op, nt.init, t...) +mapfoldl_impl(f, op, nt::NamedTuple{()}, t::Tuple) = mapafoldl(f, op, f(t[1]), tail(t)...) +mapfoldl_impl(f, op, nt::NamedTuple{()}, t::Tuple{}) = mapreduce_empty_iter(f, op, t, IteratorEltype(t)) # type-stable padding fill_to_length(t::NTuple{N,Any}, val, ::Val{N}) where {N} = t diff --git a/test/tuple.jl b/test/tuple.jl index 3a22f3b089557..9b56ccff20fbe 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -237,6 +237,15 @@ end end end +@testset "mapfoldl" begin + @test (((1=>2)=>3)=>4) == foldl(=>, (1,2,3,4)) == + mapfoldl(identity, =>, (1,2,3,4)) == mapfoldl(abs, =>, (-1,-2,-3,-4)) + @test mapfoldl(abs, =>, (-1,-2,-3,-4), init=-10) == ((((-10=>1)=>2)=>3)=>4) + @test mapfoldl(abs, =>, (), init=-10) == -10 + @test mapfoldl(abs, Pair{Any,Any}, (-30:-1...,)) == mapfoldl(abs, Pair{Any,Any}, [-30:-1...,]) + @test_throws ArgumentError mapfoldl(abs, =>, ()) +end + @testset "comparison and hash" begin @test isequal((), ()) @test isequal((1,2,3), (1,2,3))