@@ -64,7 +64,7 @@ function mapfoldl(f, op, itr)
6464 return Base. mapreduce_empty_iter (f, op, itr, iteratoreltype (itr))
6565 end
6666 (x, i) = next (itr, i)
67- v0 = f ( x)
67+ v0 = mapreduce_single (f, op, x)
6868 mapfoldl_impl (f, op, v0, itr, i)
6969end
7070
@@ -133,7 +133,7 @@ function mapfoldr(f, op, itr)
133133 if isempty (itr)
134134 return Base. mapreduce_empty_iter (f, op, itr, iteratoreltype (itr))
135135 end
136- return mapfoldr_impl (f, op, f ( itr[i]), itr, i- 1 )
136+ return mapfoldr_impl (f, op, mapreduce_single (f, op, itr[i]), itr, i- 1 )
137137end
138138
139139"""
@@ -174,7 +174,7 @@ foldr(op, itr) = mapfoldr(identity, op, itr)
174174@noinline function mapreduce_impl (f, op, A:: AbstractArray , ifirst:: Integer , ilast:: Integer , blksize:: Int )
175175 if ifirst == ilast
176176 @inbounds a1 = A[ifirst]
177- return f ( a1)
177+ return mapreduce_single (f, op, a1)
178178 elseif ifirst + blksize > ilast
179179 # sequential portion
180180 @inbounds a1 = A[ifirst]
@@ -238,12 +238,30 @@ pairwise_blocksize(::typeof(abs2), ::typeof(+)) = 4096
238238
239239# handling empty arrays
240240_empty_reduce_error () = throw (ArgumentError (" reducing over an empty collection is not allowed" ))
241+
242+ """
243+ Base.reduce_empty(op, T)
244+
245+ The value to be returned when calling [`reduce`](@ref) with `op` over an empty array with
246+ element type of `T`.
247+
248+ If not defined, this will throw an `ArgumentError`.
249+ """
241250reduce_empty (op, T) = _empty_reduce_error ()
242251reduce_empty (:: typeof (+ ), T) = zero (T)
243252reduce_empty (:: typeof (* ), T) = one (T)
244253reduce_empty (:: typeof (& ), :: Type{Bool} ) = true
245254reduce_empty (:: typeof (| ), :: Type{Bool} ) = false
246255
256+
257+ """
258+ Base.mapreduce_empty(f, op, T)
259+
260+ The value to be returned when calling [`mapreduce`](@ref) with `f` and `op` over an empty
261+ array with element type of `T`.
262+
263+ If not defined, this will throw an `ArgumentError`.
264+ """
247265mapreduce_empty (f, op, T) = _empty_reduce_error ()
248266mapreduce_empty (:: typeof (identity), op, T) = reduce_empty (op, T)
249267mapreduce_empty (f:: _PromoteSysSizeFunction , op, T) =
@@ -266,6 +284,19 @@ mapreduce_empty_iter(f, op::typeof(&), itr, ::EltypeUnknown) = true
266284mapreduce_empty_iter (f, op:: typeof (| ), itr, :: EltypeUnknown ) = false
267285mapreduce_empty_iter (f, op, itr, :: EltypeUnknown ) = _empty_reduce_error ()
268286
287+ # handling of single-element iterators
288+ """
289+ Base.mapreduce_single(f, op, x)
290+
291+ The value to be returned when calling [`mapreduce`] with `f` and `op` over an iterator
292+ which contains a single element `x`.
293+
294+ The default is `f(x)`.
295+ """
296+ mapreduce_single (f, op, x) = f (x)
297+
298+
299+
269300_mapreduce (f, op, A:: AbstractArray ) = _mapreduce (f, op, IndexStyle (A), A)
270301
271302function _mapreduce (f, op, :: IndexLinear , A:: AbstractArray{T} ) where T
@@ -275,7 +306,7 @@ function _mapreduce(f, op, ::IndexLinear, A::AbstractArray{T}) where T
275306 return mapreduce_empty (f, op, T)
276307 elseif n == 1
277308 @inbounds a1 = A[inds[1 ]]
278- return f ( a1)
309+ return mapreduce_single (f, op, a1)
279310 elseif n < 16 # process short array here, avoid mapreduce_impl() compilation
280311 @inbounds i = inds[1 ]
281312 @inbounds a1 = A[i]
0 commit comments