How is reduce function initialized?

question

#1

Is this normal?

julia> a = reduce(0, 1:4) do x,y
       x += y < -1 
       end
0

julia> a = reduce(1:4) do x,y
       x += y < -1 
       end
1

I’d expect both to result in zero.


#2

I am not sure why you expect this. Try

f(x, y) = x += y < -1 

f(0, 1)
f(0, 2)
# ...

f(1, 2)

#3

Oh, I understand my problem here, I thought that the initial value of reduce defaults to zero when it’s omitted from the function call. But it’s set to the first element of the iterable, right?


#4

See ?reduce:

It is unspecified whether v0 is used for non-empty collections.

Ideally, v0 is a “neutral element”, so it should not matter. But this does not hold in your case.


#5

I have to admit that even after reading reduce’s help and your reply, I just don’t understand what the initial value is set to when it’s omitted from the function call :confused:


#6

In that case reduction starts with the first pair:

julia> function f(x, y)
           println("called with $x and $y")
           x + y
       end
f (generic function with 2 methods)

julia> reduce(f, 1:4)
called with 1 and 2
called with 3 and 3
called with 6 and 4
10

But as stated in the docstring, this won’t work for empty collections:

julia> reduce(f, [])
ERROR: ArgumentError: reducing over an empty collection is not allowed
Stacktrace:
 [1] _mapreduce(::Base.#identity, ::#f, ::IndexLinear, ::Array{Any,1}) at ./reduce.jl:265
 [2] reduce(::Function, ::Array{Any,1}) at ./reduce.jl:330