# Inconsistency in \`sum\` of an empty generator

**URL:** <https://discourse.julialang.org/t/inconsistency-in-sum-of-an-empty-generator/89638>\
**Category:** Internals & Design\
**Tags:** generator, sum\
**Created:** [November 2, 2022, 2:48am UTC](https://discourse.julialang.org/t/inconsistency-in-sum-of-an-empty-generator/89638 "2022-11-02T02:48:18Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [November 2, 2022, 2:48am UTC](https://discourse.julialang.org/t/inconsistency-in-sum-of-an-empty-generator/89638/1 "2022-11-02T02:48:18Z")

</div>

On Julia 1.3, the following two empty generators both throw an error when you apply `sum` to them:

```julia
julia> g1 = (1 for i in Int[]);

julia> g2 = (x for x in [-1] if x > 0);

julia> eltype(g1)
Any

julia> eltype(g2)
Any

julia> sum(g1)
ERROR: ArgumentError: reducing over an empty collection is not allowed

julia> sum(g2)
ERROR: ArgumentError: reducing over an empty collection is not allowed

```

That seems like the correct behavior. On newer versions of Julia, you can avoid the error by setting the `init` keyword argument. (Not sure which version introduced that keyword argument.)

However, on Julia 1.4 the second generator sums to zero:

```julia
julia> g1 = (1 for i in Int[]);

julia> g2 = (x for x in [-1] if x > 0);

julia> eltype(g1)
Any

julia> eltype(g2)
Any

julia> sum(g1)
ERROR: ArgumentError: reducing over an empty collection is not allowed

julia> sum(g2)
0

```

Was that an intended change or an accidental change?

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [November 2, 2022, 7:22am UTC](https://discourse.julialang.org/t/inconsistency-in-sum-of-an-empty-generator/89638/2 "2022-11-02T07:22:54Z")

</div>

No idea about the inconsistency highlighted, but I just wanted to point out the fact that for the empty generator `g2`, Julia’s results:

```julia
sum(g2) # = 0
prod(g2) # = 1

```

seem to be consistent with the definitions of the [empty sum](https://en.wikipedia.org/wiki/Empty_sum) and [empty product](https://en.wikipedia.org/wiki/Empty_product).

---

<div class="post-metadata">

**Author:** ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)\
**Post date:** [November 2, 2022, 2:50pm UTC](https://discourse.julialang.org/t/inconsistency-in-sum-of-an-empty-generator/89638/3 "2022-11-02T14:50:25Z")

</div>

As far as I can tell, `sum(g)` does not promise to be exactly equivalent to `reduce(+, g)` so I do not have a problem with `sum(g2)` working.

What seems more concerning is that `reduce(+, Number[])` also returns `0`. Clearly the error message is incorrect here when it implies reducing over an empty collection is never allowed.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [November 2, 2022, 3:00pm UTC](https://discourse.julialang.org/t/inconsistency-in-sum-of-an-empty-generator/89638/4 "2022-11-02T15:00:33Z")

</div>

> [@adienes](#):
>
> What seems more concerning is that `reduce(+, Number[])` also returns `0`. Clearly the error message is incorrect here when it implies reducing over an empty collection is never allowed.

Reducing over an empty collection is not allowed if the eltype cannot be determined, because then it is impossible to know the correct type of `0` (for `sum`).

The reason it works for `g2` is that `eltype(g2.iter)` is known (`== Int`), and that is what is used nowadays under the hood for filtered iterators. No idea why `g1` can’t use `eltype(g1.iter)`, though — it seems like that could be improved.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [November 2, 2022, 3:07pm UTC](https://discourse.julialang.org/t/inconsistency-in-sum-of-an-empty-generator/89638/5 "2022-11-02T15:07:30Z")

</div>

Oh, that’s interesting. Why does `eltype(g2) == Any`, but `eltype(g2.iter) == Int`?

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [November 2, 2022, 3:46pm UTC](https://discourse.julialang.org/t/inconsistency-in-sum-of-an-empty-generator/89638/6 "2022-11-02T15:46:57Z")

</div>

I see. The `iter` field of a generator is the `iter` in the following expression:

```julia
g = (f(x) for x in iter)

```

A generator has two fields, `f` and `iter`. It appears that there is a specialization for the case when `f == identity`:

```julia
julia> sum(x for x in Int[])
0

julia> sum(2x for x in Int[])
ERROR: MethodError: reducing over an empty collection is not
allowed; consider supplying `init` to the reducer

```

I guess it makes sense, because the generator `(x for x in iter)` should be exactly the same as just iterating through `iter`.

This explains why `g1` doesn’t work: It’s because `x -> 1` is not the identity function. `sum` will throw an error when `f` is not the identity function because the return type of `f` might be different from the element type of `iter`.
