diff --git a/base/reduce.jl b/base/reduce.jl index d98b237e4997c..2b6c00eb41f58 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -347,6 +347,8 @@ reduce_empty(::typeof(*), ::Type{T}) where {T} = one(T) reduce_empty(::typeof(*), ::Type{<:AbstractChar}) = "" reduce_empty(::typeof(&), ::Type{Bool}) = true reduce_empty(::typeof(|), ::Type{Bool}) = false +reduce_empty(::typeof(∘), ::Type{Union{}}) = _empty_reduce_error(∘, Union{}) +reduce_empty(::typeof(∘), ::Type) = identity reduce_empty(::typeof(add_sum), ::Type{Union{}}) = _empty_reduce_error(add_sum, Union{}) reduce_empty(::typeof(add_sum), ::Type{T}) where {T} = reduce_empty(+, T) @@ -356,6 +358,9 @@ reduce_empty(::typeof(mul_prod), ::Type{Union{}}) = _empty_reduce_error(mul_prod reduce_empty(::typeof(mul_prod), ::Type{T}) where {T} = reduce_empty(*, T) reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:SmallSigned} = one(Int) reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:SmallUnsigned} = one(UInt) +reduce_empty(::typeof(max), ::Type{T}) where {T} = _empty_reduce_error(maximum, T) +reduce_empty(::typeof(max), ::Type{T}) where {T<:Unsigned} = zero(T) +reduce_empty(::typeof(max), ::Type{Union{}}) = _empty_reduce_error(maximum, Union{}) reduce_empty(op::BottomRF, ::Type{T}) where {T} = reduce_empty(op.rf, T) reduce_empty(op::MappingRF, ::Type{T}) where {T} = mapreduce_empty(op.f, op.rf, T) @@ -753,7 +758,8 @@ julia> maximum([1,2,3]) 3 julia> maximum(()) -ERROR: MethodError: reducing over an empty collection is not allowed; consider supplying `init` to the reducer +ERROR: ArgumentError: reducing with maximum over an empty collection of element type Union{} is not allowed. +You may be able to prevent this error by supplying an `init` value to the reducer. Stacktrace: [...] diff --git a/test/reduce.jl b/test/reduce.jl index 2c852084de37e..c6914c46be9ae 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -53,6 +53,9 @@ end @test reduce(max, [8 6 7 5 3 0 9]) == 9 @test reduce(+, 1:5; init=1000) == (1000 + 1 + 2 + 3 + 4 + 5) @test reduce(+, 1) == 1 +@test reduce(∘, [])(42) == 42 +@test reduce(∘, [x->2x+1])(42) == 85 +@test reduce(∘, [x->x*"2", x->x*"1"])("0") == "012" @test_throws "reducing with * over an empty collection of element type Union{} is not allowed" reduce(*, ()) @test_throws "reducing with * over an empty collection of element type Union{} is not allowed" reduce(*, Union{}[]) @@ -248,10 +251,12 @@ prod2(itr) = invoke(prod, Tuple{Any}, itr) # maximum & minimum & extrema -@test_throws "reducing over an empty" maximum(Int[]) +@test_throws "reducing with maximum over an empty" maximum(Int[]) @test_throws "reducing over an empty" minimum(Int[]) @test_throws "reducing over an empty" extrema(Int[]) +@test maximum(UInt[]) === UInt(0) + @test maximum(Int[]; init=-1) == -1 @test minimum(Int[]; init=-1) == -1 @test extrema(Int[]; init=(1, -1)) == (1, -1) diff --git a/test/reducedim.jl b/test/reducedim.jl index daa0a3fbe1f92..c5b461ebb15fe 100644 --- a/test/reducedim.jl +++ b/test/reducedim.jl @@ -184,7 +184,8 @@ end @test prod(A) === 1 @test_throws ["reducing over an empty", "consider supplying `init`"] minimum(A) - @test_throws "consider supplying `init`" maximum(A) + @test_throws ["reducing with maximum over an empty", + "prevent this error by supplying an `init`"] maximum(A) @test isequal(sum(A, dims=1), zeros(Int, 1, 1)) @test isequal(sum(A, dims=2), zeros(Int, 0, 1))