Iszero and zero: wrong usage (?) and bad error message

I am trying to use iszero for a custom struct. I defined zero for it, which appeared to be the necessary method. But iszero does not work, and the error message is not clear, because it complains that the zero function (just defined) does not exist.

julia> struct S
           x::Int
       end

julia> Base.zero(::Type{S}) = S(0)

julia> zero(S)
S(0)

julia> x = S(0)
S(0)

julia> iszero(x)
ERROR: MethodError: no method matching zero(::S)
Closest candidates are:
  zero(::Union{Type{P}, P}) where P<:Dates.Period at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/Dates/src/periods.jl:53
  zero(::LinearAlgebra.UniformScaling{T}) where T at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/LinearAlgebra/src/uniformscaling.jl:136
  zero(::SparseArrays.AbstractSparseArray) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/SparseArrays/src/SparseArrays.jl:55
  ...
Stacktrace:
 [1] iszero(x::S)
   @ Base ./number.jl:40
 [2] top-level scope
   @ REPL[12]:1

julia> 

If I define

Base.zero(x::S) = S(0)

the problem is solved. However, this seems redundant with the definition of Base.zero(::Type{S}) , since (I guess) there could be a

Base.zero(x::T) where T = Base.zero(T)

in fact I am surprised that this is not already implemented (and curious for the reason).

What if not all information is available in the type parameters?

julia> struct A{T}
           v1::T
           v2::Number
       end

julia> Base.zero(a::A) = A(zero(a.v1), zero(a.v2))

julia> zero(A(0.3, 1))
A{Float64}(0.0, 0)

julia> Base.zero(::Type{A}) where T = A(0, 0)

julia> zero(A)
A{Int64}(0, 0)
3 Likes

Another example is vectors/arrays: only the dimension and the element type are available in the type itself, not the size (which is nevertheless needed to build a neutral element of the correct size).

i.e:

julia> v = [1,2,3]
3-element Vector{Int64}:
 1
 2
 3

julia> zero(v)  # needs the size of v, which is not contained in its type
3-element Vector{Int64}:
 0
 0
 0
3 Likes