We may want to revise zero
to match how one
works. This would also mean we would need to create a zerounit
.
julia> using Dates
julia> one(Minute)
1
julia> oneunit(Minute)
1 minute
julia> zero(Minute)
0 minutes
julia> zerounit(Minute)
ERROR: UndefVarError: zerounit not defined
Related: #24595 :).
But zero
should be the additive identity, so zero == zerounit
, right? So (if anything) it is the zeronounit
function that is missing.
You can always do zero(one(T))
if you want zero without units, but this is not an additive identity for T
.
The asymmetry and minor ambiguity in one
/oneunit
and ?/zero
supports the symmetric pairs onemul
/oneadd
and zeromul
/zeroadd
discussed previously. No ambiguity or inconsistency of any kind there :). Best!
I was mainly noting the style inconsistency. My ideal world would have Dates.Minute(0) == 0
be true
(Partly summarising from slack:)
Note that one
does not always exist when zero
does, so zero(one(T))
is not a full solution. But a unitless zero cannot be multiplied or added to unitful quantities, so it is hard to come up with examples where this would be needed. After a long time I came up with the first situation where I actually did.
In this case to get a unitless white noise vector, which is to be scaled with a unitful scale. Because the scale carries a unit, the white noise vector, shouldn't. This could be conveniently written as randn!(zeronounit(x))
. Perhaps the only case.
Post scriptum: I think this could be closed in favour of #22216
Note that
one
does not always exist whenzero
does, sozero(one(T))
is not a full solution.
But a "unitless" zero is only meaningful when you have multiplication, in which case you should have one
, no?
This is not related to units, but from a purely abstract point of view:
zero(x)
is the identity element under the operator +
.one(x)
is the identity element under the operator *
.oneunit(x)
is the generative element under the operator +
.zeronounit(x)
would be the absorbing element under the operator *
.Assuming one(x)
exists, zero(one(x))
would be synonymous with zeronounit(x)
. However, it is not at all inconceivable that an identity element under multiplication would not exist for an arbitrarily defined object, while the absorbing element would. For instance, numbers on the interval [0, 1)
that only allow multiplication onto themselves.
I do not think zeronounit
is a good name for the absorbing element, though.
I would differentiate that zeronounit
may be an ugly name, but would be a good name in so far that this is the name different people came up independently when running into this.
Assuming
one(x)
exists,zero(one(x))
would be synonymous withzeronounit(x)
.
I don't think that theorem is true. Try with a Float64
. hint The absorbing element for Float64
s under *
isn't 0.0
.
The absorbing element for
Float64
s under*
isn't0.0
.
0.0
also isn't the additive identity for Float64
, technically.
If I can ask a concrete-algebra question, what would you do with the absorbing element of a type? I can only imagine using it to multiply an instance of the type.
y = zeronounit(x) * x
but in that case you might as well just do
y = zero(x)
Most helpful comment
But
zero
should be the additive identity, sozero == zerounit
, right? So (if anything) it is thezeronounit
function that is missing.