# BoundsError using reduce function (Julia 1.3.1)

**URL:** <https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232>\
**Category:** General Usage\
**Created:** [March 19, 2020, 10:29pm UTC](https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232 "2020-03-19T22:29:20Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![erratic](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@erratic](https://discourse.julialang.org/u/erratic)\
**Post date:** [March 19, 2020, 10:29pm UTC](https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232/1 "2020-03-19T22:29:20Z")

</div>

I get the following error when I try to reduce the tuple array. Honestly I have no idea why this happen.

> julia\> a = [(x, rand()\*10) for x in 1:20]  
> 20-element Array{Tuple{Int64,Float64},1}:  
> (1, 8.090189006962254)  
> (2, 2.117390143738971)  
> (3, 3.720862674831744)  
> (4, 3.3448022839992686)  
> (5, 8.663485519459988)  
> (6, 2.8559985846713887)  
> (7, 8.90791074876892)  
> (8, 1.8252199991786422)  
> (9, 8.850720581613224)  
> (10, 2.3484428215704645)  
> (11, 7.05697492936725)  
> (12, 5.204279968934786)  
> (13, 9.661816648445496)  
> (14, 8.822892862843808)  
> (15, 9.937308741925413)  
> (16, 4.386983103895896)  
> (17, 6.657011304452505)  
> (18, 3.1464881449135285)  
> (19, 5.202863099252719)  
> (20, 5.450333298946468)

Correctly reduce on first tuple argument:

> julia\> reduce((x, y) → x[1] + y[1], a)  
> 210

Error when reducing on second tuple argument:

> julia\> reduce((x, y) → x[2] + y[2], a)  
> ERROR: BoundsError  
> Stacktrace:  
> [1] getindex at .\number.jl:78 [inlined]  
> [2] #21 at .\REPL[10]:1 [inlined]  
> [3] macro expansion at .\reduce.jl:158 [inlined]  
> [4] macro expansion at .\simdloop.jl:77 [inlined]  
> [5] mapreduce\_impl(::typeof(identity), ::var"#21#22", ::Array{Tuple{Int64,Float64},1}, ::Int64, ::Int64, ::Int64) at .\reduce.jl:156  
> [6] mapreduce\_impl at .\reduce.jl:170 [inlined]  
> [7] \_mapreduce(::typeof(identity), ::var"#21#22", ::IndexLinear, ::Array{Tuple{Int64,Float64},1}) at .\reduce.jl:316  
> [8] \_mapreduce\_dim(::Function, ::Function, ::NamedTuple{(),Tuple{}}, ::Array{Tuple{Int64,Float64},1}, ::Colon) at .\reducedim.jl:312  
> [9] #mapreduce#584 at .\reducedim.jl:307 [inlined]  
> [10] mapreduce at .\reducedim.jl:307 [inlined]  
> [11] #reduce#586 at .\reducedim.jl:352 [inlined]  
> [12] reduce(::Function, ::Array{Tuple{Int64,Float64},1}) at .\reducedim.jl:352  
> [13] top-level scope at REPL[10]:1

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [March 20, 2020, 6:23am UTC](https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232/2 "2020-03-20T06:23:55Z")

</div>

Note that in your example, a typical argument is

```julia
x, y = 1, 8.090189006962254

```

so I am not sure what you are expecting from `y[2]`.

The fact that `y[1]` etc works is a design wart of Julia, cf

```julia
julia> 2[1]
2

```

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [March 20, 2020, 6:44am UTC](https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232/3 "2020-03-20T06:44:51Z")

</div>

I think what you want is `mapreduce(x -> x[1], +, a)` and `mapreduce(x -> x[2], +, a)`.

Note that the argument `op` for `reduce` is fed back to one of its arguments. If you are returning a number from `op` you need to be able to handle a number.

---

<div class="post-metadata">

**Author:** ![erratic](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@erratic](https://discourse.julialang.org/u/erratic)\
**Post date:** [March 20, 2020, 7:26am UTC](https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232/4 "2020-03-20T07:26:55Z")

</div>

Since it is an array of tuple and a tuple is an indexable collection, what I expect is the sum of all element at second place. In fact the expression:

> sum(t → t[2], a)  
> 130.64905626543398

Do the job. (Which is a special implementation of reduce as Julia official doc say)

---

<div class="post-metadata">

**Author:** ![erratic](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@erratic](https://discourse.julialang.org/u/erratic)\
**Post date:** [March 20, 2020, 7:30am UTC](https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232/5 "2020-03-20T07:30:01Z")

</div>

Yes, and I think is more terse this other solution:

> sum(t → t[2], a)

As I wrote above, but in case the operator was not so simple still remain this unexpected behaviour. Why this happen just for second element of the tuple?

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [March 20, 2020, 7:43am UTC](https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232/6 "2020-03-20T07:43:41Z")

</div>

This does what you want:

```julia
reduce((x, y) -> x + y[2], a, init = 0.0)

```

To better understand what was going on in your example, try

```julia
reduce((x, y) -> (@show x y; x[1] + y[1]), a)

```

---

<div class="post-metadata">

**Author:** ![erratic](https://avatars.discourse-cdn.com/v4/letter/e/a9adbd/32.png) [@erratic](https://discourse.julialang.org/u/erratic)\
**Post date:** [March 20, 2020, 11:36am UTC](https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232/7 "2020-03-20T11:36:20Z")

</div>

Thanks! 😀

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [March 20, 2020, 8:25pm UTC](https://discourse.julialang.org/t/boundserror-using-reduce-function-julia-1-3-1/36232/8 "2020-03-20T20:25:50Z")

</div>

> [@GunnarFarneback](#):
>
> ```julia
> reduce((x, y) -> x + y[2], a, init = 0.0)
> 
> ```

This is wrong. It works because of an implementation detail (`reduce` fallbacks to `foldl` in this case). Please read the documentation:

> Reduce the given collection `itr` with the given binary operator `op`. If provided, the initial value `init` must be a neutral element for `op` that will be returned for empty collections. It is unspecified whether `init` is used for non-empty collections.
> 
> — [https://docs.julialang.org/en/latest/base/collections/#Base.reduce-Tuple{Any,Any}](https://docs.julialang.org/en/latest/base/collections/#Base.reduce-Tuple%7BAny,Any%7D)

It says `init` has to be a neutral element aka [identity](https://en.wikipedia.org/wiki/Identity_element) of `op`. This is to say, following must hold:

```julia
for x in a
    @assert op(x, init) == x
    @assert op(init, x) == x
end

```

However, `op = (x, y) -> x + y[2]` and `init = 0.0` does not satisfy this. Element-wise processing must use `mapreduce`, not `reduce`. Alternatively, just use `foldl`. It is correct to invoke `foldl((x, y) -> x + y[2], a, init = 0.0)`.

Note also that `op` for `reduce` has to be [associative](https://en.wikipedia.org/wiki/Associative_property) (i.e., it has to be a [monoid](https://en.wikipedia.org/wiki/Monoid)). `op = (x, y) -> x + y[2]` does not satisfy this.

A general advice is to be careful with “asymmetric looking” `op` when using `reduce`. If you can’t convince yourself that given `op` is associative and `init` is its identity, use `foldl`.

(All these complication may discourage you to use `reduce`. However, it is one of the most fundamental tool for parallel computation. So I think it’s important to learn how to use `reduce`.)
