@@ -299,30 +299,42 @@ pairwise_blocksize(::typeof(abs2), ::typeof(+)) = 4096
299299
300300# handling empty arrays
301301_empty_reduce_error () = throw (ArgumentError (" reducing over an empty collection is not allowed" ))
302+ _empty_reduce_error (@nospecialize (f), @nospecialize (T:: Type )) = throw (ArgumentError ("""
303+ reducing with $f over an empty collection of element type $T is not allowed.
304+ You may be able to prevent this error by supplying an `init` value to the reducer.""" ))
302305
303306"""
304307 Base.reduce_empty(op, T)
305308
306309The value to be returned when calling [`reduce`](@ref), [`foldl`](@ref) or [`foldr`](@ref)
307310with reduction `op` over an empty array with element type of `T`.
308311
309- If not defined, this will throw an `ArgumentError`.
312+ This should only be defined in unambiguous cases; for example,
313+
314+ ```julia
315+ Base.reduce_empty(::typeof(+), ::Type{T}) where T = zero(T)
316+ ```
317+
318+ is justified (the sum of zero elements is zero), whereas
319+ `reduce_empty(::typeof(max), ::Type{Any})` is not (the maximum value of an empty collection
320+ is generally ambiguous, and especially so when the element type is unknown).
321+
322+ As an alternative, consider supplying an `init` value to the reducer.
310323"""
311- reduce_empty (op, :: Type{T} ) where {T} = _empty_reduce_error ()
312- reduce_empty (:: typeof (+ ), :: Type{Union{}} ) = _empty_reduce_error ()
324+ reduce_empty (:: typeof (+ ), :: Type{Union{}} ) = _empty_reduce_error (+ , Union{})
313325reduce_empty (:: typeof (+ ), :: Type{T} ) where {T} = zero (T)
314326reduce_empty (:: typeof (+ ), :: Type{Bool} ) = zero (Int)
315- reduce_empty (:: typeof (* ), :: Type{Union{}} ) = _empty_reduce_error ()
327+ reduce_empty (:: typeof (* ), :: Type{Union{}} ) = _empty_reduce_error (* , Union{} )
316328reduce_empty (:: typeof (* ), :: Type{T} ) where {T} = one (T)
317329reduce_empty (:: typeof (* ), :: Type{<:AbstractChar} ) = " "
318330reduce_empty (:: typeof (& ), :: Type{Bool} ) = true
319331reduce_empty (:: typeof (| ), :: Type{Bool} ) = false
320332
321- reduce_empty (:: typeof (add_sum), :: Type{Union{}} ) = _empty_reduce_error ()
333+ reduce_empty (:: typeof (add_sum), :: Type{Union{}} ) = _empty_reduce_error (add_sum, Union{} )
322334reduce_empty (:: typeof (add_sum), :: Type{T} ) where {T} = reduce_empty (+ , T)
323335reduce_empty (:: typeof (add_sum), :: Type{T} ) where {T<: SmallSigned } = zero (Int)
324336reduce_empty (:: typeof (add_sum), :: Type{T} ) where {T<: SmallUnsigned } = zero (UInt)
325- reduce_empty (:: typeof (mul_prod), :: Type{Union{}} ) = _empty_reduce_error ()
337+ reduce_empty (:: typeof (mul_prod), :: Type{Union{}} ) = _empty_reduce_error (mul_prod, Union{} )
326338reduce_empty (:: typeof (mul_prod), :: Type{T} ) where {T} = reduce_empty (* , T)
327339reduce_empty (:: typeof (mul_prod), :: Type{T} ) where {T<: SmallSigned } = one (Int)
328340reduce_empty (:: typeof (mul_prod), :: Type{T} ) where {T<: SmallUnsigned } = one (UInt)
@@ -337,11 +349,8 @@ reduce_empty(op::FlipArgs, ::Type{T}) where {T} = reduce_empty(op.f, T)
337349
338350The value to be returned when calling [`mapreduce`](@ref), [`mapfoldl`](@ref`) or
339351[`mapfoldr`](@ref) with map `f` and reduction `op` over an empty array with element type
340- of `T`.
341-
342- If not defined, this will throw an `ArgumentError`.
352+ of `T`. See [`Base.reduce_empty`](@ref) for more information.
343353"""
344- mapreduce_empty (f, op, T) = _empty_reduce_error ()
345354mapreduce_empty (:: typeof (identity), op, T) = reduce_empty (op, T)
346355mapreduce_empty (:: typeof (abs), op, T) = abs (reduce_empty (op, T))
347356mapreduce_empty (:: typeof (abs2), op, T) = abs2 (reduce_empty (op, T))
@@ -355,7 +364,10 @@ mapreduce_empty_iter(f, op, itr, ItrEltype) =
355364
356365@inline reduce_empty_iter (op, itr) = reduce_empty_iter (op, itr, IteratorEltype (itr))
357366@inline reduce_empty_iter (op, itr, :: HasEltype ) = reduce_empty (op, eltype (itr))
358- reduce_empty_iter (op, itr, :: EltypeUnknown ) = _empty_reduce_error ()
367+ reduce_empty_iter (op, itr, :: EltypeUnknown ) = throw (ArgumentError ("""
368+ reducing over an empty collection of unknown element type is not allowed.
369+ You may be able to prevent this error by supplying an `init` value to the reducer.""" ))
370+
359371
360372# handling of single-element iterators
361373"""
@@ -726,7 +738,7 @@ julia> maximum([1,2,3])
7267383
727739
728740julia> maximum(())
729- ERROR: ArgumentError : reducing over an empty collection is not allowed
741+ ERROR: MethodError : reducing over an empty collection is not allowed; consider supplying `init` to the reducer
730742Stacktrace:
731743[...]
732744
@@ -758,7 +770,7 @@ julia> minimum([1,2,3])
7587701
759771
760772julia> minimum([])
761- ERROR: ArgumentError : reducing over an empty collection is not allowed
773+ ERROR: MethodError : reducing over an empty collection is not allowed; consider supplying `init` to the reducer
762774Stacktrace:
763775[...]
764776
0 commit comments