Tbl
April 6, 2022, 6:23pm
#1
I was experimenting with function `sum`

and found out that it does not work for empty collections of matrices, Julia 1.7.2. The reason is there is no method `zero(::Type{Array{T,N}})`

, thus you must specify `init`

manually. However, there is a method `zero(::Array{T,N})`

. As a consequence `zero([1 2; 3 4])`

works but `zero(Matrix{Int})`

does not work. Maybe there is a reason for this, but for me it seems to be very unintuitive. Similar thing happens for function `one`

and consequently `prod`

.

Mason
April 6, 2022, 6:28pm
#2
What would `zero(Matrix{Float64})`

return? I guess you could have a lazy representation that doesn’t actually have a definite size, but that’s very different from what the other version does, be wise the input object has a size.

1 Like

DNF
April 6, 2022, 6:28pm
#3

Tbl:

zero(Matrix{Int})

But what should this call return?

Maybe `0*LinearAlgebra.I`

? Be aware that this cannot be mutated/updated, though.

jar1
April 6, 2022, 6:31pm
#4
There is a family of initial-value issues

opened 08:58AM - 02 Dec 19 UTC

julep
maths

(This issue is a follow-up to #34000 #28854 #31303)
The docstring for `zero(x… )` says
> Get the additive identity element for the type of x
However, defining this additive identity precisely seems to be confusing, especially for union types, and in the presence of type promotion rules. The rest of this issue is dedicated to exploring more precisely what the semantics of `zero(T)` is (to help figure out what exactly the semantics should be).
1. In many situations, `zero(::Union)` is undefined when it could be defined. Intuitively, one might expect that the presence of multiple zeros might complicate the definition. However, type promotion seems to allow for a uniquely defined result. If we take the definition above seriously, the statements
```julia
julia> Float16(0.0) + Float32(1.0) === Float32(1.0) #works for Float32
true
julia> Float16(0.0) + Float16(1.0) === Float16(1.0) #and for Float16
true
```
would argue that `zero(Union{Float16,Float32}) === Float16(0.0)` (it is currently undefined).
2. A counterargument to the above would be that `Int(0)` is also a valid choice for `zero(Union{Float16,Float32})`, since
```julia
julia> 0 + Float16(1.0) === Float16(1.0) # works because of type promotion
true
```
However, the statement above would also imply that `Int(0)` is a valid choice for `zero(Float16)`.
We can exclude this value by requiring `zero()` to be endomorphic, i.e. `zero(::T) :: T`, and by extension `zero(T) :: T`.
3. `Int(0)` appears to be the result of `zero(T)` whenever`T <: Union{Missing,Number,Complex}`, even though it is not always the unique (or even correct) additive identity in `T`:
```
julia> zero(Union{Int,Complex})
0
julia> zero(Union{Real,Complex}) #due to type promotion, see #2
0
julia> 0 + Complex{Bool}(0) === Complex{Bool}(0) # Counterexample: actually Complex{Int}(0), so Int(0) is not an additive identity over Complex
false
julia> Int(0) + Int16(0) === Int(0) #Counterexample: Int16 <: Real but adding Int(0) to it promotes to Int
true
julia> Int(0) + false === Int(0) #Counterexample: Bool <: Real but adding Int(0) to it promotes to Int
true
```
---
## Proposal
1. `zero(T)` for non-union types should be defined as the unique additive identity such that
a. `zero(T)::T`, i.e. `zero()` is an endomorphism, and
b. The identity `zero(T) + zero(T) === zero(T)` is satisfied for all `T`.
2. `zero(Union{T,S}) === zero(T)` when `zero(T) + zero(S) === zero(S)`, taking into account type promotion rules.
3. If no unique endomorphic zero exists, then `zero(T)` should be undefined, except for `zero(Bool) === false` as a special case.
This definition would preserve the endomorphic property for leaf types, like `zero(Float16) === Float16(0.0)`.
This definition would preserve the result for `zero(Bool) === false`, to be consistent with current arithmetic semantics of `Bool`.
This definition would preserve the semantics of #28854 for `zero(Missing) === missing`.
This definition would define `zero(Union{Float16,Float32,Float64})` to be `Float16(0.0)` (currently undefined).
This definition would define `zero(Union{Float16,Int16})` to be `Int16(0)` (currently undefined).
This definition would *change* `zero(Real)` to be `false` (and similarly in Case 3 above; currently `Int(0)`); arguably a bug fix.
This definition would *change* `zero(Union{Bool,Int})` to be `false` (currently `Int(0)`); arguably a bug fix.

opened 01:13PM - 01 Jun 20 UTC

This is a persistent source of confusion (most recently #36099), and there are i… ncorrect definitions of `one` scattered across the ecosystem. (We're still deprecating them in Colors-world.) The best answer is to `@deprecate one onemult` and simply not have a function called `one`.

The basic reason is that the size of the matrix is not encoded in the type. (If you use an `SMatrix`

it works fine, in contrast, because StaticArrays include the size in the type.)

4 Likes

It’s also not of the type you asked for.

1 Like

Tbl
April 6, 2022, 8:58pm
#7
A, yes, this is unfortunate. It skipped my mind this is the case. I guess there is no good fix then. Functions `sum`

and `prod`

becoming type unstable would be even worse.