# Recursive definition of zero, one

Hi all,

Imagine I have a data type like:

``````struct foo{T,N}
c::NTuple{N,T}
end
``````

and I want to define the zero function

``````import Base.zero
zero(s::foo{T,N}) where {T,N} = foo{T,N}(ntuple(i -> zero(T), N))
``````

This allows me to get, for example:

``````julia> s = foo((1.2,2.2))
foo{Float64, 2}((1.2, 2.2))

julia> zero(s)
foo{Float64, 2}((0.0, 0.0))
``````

But if I try a recursive definition, this fails:

``````julia> ss = foo((s,s))
foo{foo{Float64, 2}, 2}((foo{Float64, 2}((1.2, 2.2)), foo{Float64, 2}((1.2, 2.2))))

julia> zero(ss)
ERROR: MethodError: no method matching zero(::Type{foo{Float64, 2}})
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(::foo{T, N}) where {T, N} at REPL:1
zero(::SparseArrays.AbstractSparseArray) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/SparseArrays/src/SparseArrays.jl:55
...
``````

I do not understand why it fails. `zero(foo{Float64,2})` is perfectly well defined in terms of `zero(Float64)`.

Many thanks!

It’s because you haven’t defined `zero(::Type{foo})`, but only `zero(::foo)` instead:

``````julia> Base.zero(::Type{foo{T,N}}) where {T,N} = foo{T,N}(ntuple(i -> zero(T), N))

julia> zero(ss)
foo{foo{Float64, 2}, 2}((foo{Float64, 2}((0.0, 0.0)), foo{Float64, 2}((0.0, 0.0))))
``````

Your naive recursive definition falls back to calling `zero` on the type `foo{Float64, 2}` and not its instance.

2 Likes