Sum(i for i in Vector{Int}()) raises error instead of returning 0?

sum(i for i in Vector{Int}())

raises an error:

ERROR: MethodError: no method matching zero(::Type{Any})
Closest candidates are:
zero(::Type{Base.LibGit2.Oid}) at libgit2/oid.jl:88
zero(::Type{Base.Pkg.Resolve.VersionWeights.VWPreBuildItem}) at pkg/resolve/versionweight.jl:80
zero(::Type{Base.Pkg.Resolve.VersionWeights.VWPreBuild}) at pkg/resolve/versionweight.jl:120

in mr_empty(::Base.#identity, ::Base.#+, ::Type{T}) at ./reduce.jl:130
in mapfoldl(::Base.#identity, ::Function, ::Base.Generator{Array{Int64,1},##11#12}) at ./reduce.jl:60
in sum(::Base.Generator{Array{Int64,1},##11#12}) at ./reduce.jl:229

Why can’t sum infer that the type is Int, and return an integer 0?
(The mathematical definition of an empty sum is 0)

1 Like

See also the related issue and

1 Like

Is there / shouldn’t there be a way to specify the eltype of a generator? What’s the equivalent of sum(Int[i for i in Vector{Int}()])

Something like

sum(f(x)::Int for x in Vector())

should tell the compiler that the generator’s eltype is an Int. Currently it raises the same error (julia v0.5.0).

I defined a “safe sum” that guarantees a return type and returns the correct 0 for empty iterators:

function sumf(::Type{T}, itr)::T where T
    isempty(itr) ? zero(T) : sum(x::T for x in itr)::T

Perhaps this should be added as a method to Base.sum?

Note that while it may be useful, adding it to sum would conflict with the existing sum(::Union{Function, Type}, ::Any) method.

You can always call reduce instead.

1 Like