JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.82k stars 5.49k forks source link

Revise `zero` and define `zerounit`? #24853

Open omus opened 6 years ago

omus commented 6 years ago

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
Sacha0 commented 6 years ago

Related: #24595 :).

fredrikekre commented 6 years ago

But zero should be the additive identity, so zero == zerounit, right? So (if anything) it is the zeronounit function that is missing.

stevengj commented 6 years ago

You can always do zero(one(T)) if you want zero without units, but this is not an additive identity for T.

Sacha0 commented 6 years ago

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!

omus commented 6 years ago

I was mainly noting the style inconsistency. My ideal world would have Dates.Minute(0) == 0 be true

mschauer commented 6 years ago

(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.

mschauer commented 6 years ago

Post scriptum: I think this could be closed in favour of #22216

stevengj commented 6 years ago

Note that one does not always exist when zero does, so zero(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?

dalum commented 6 years ago

This is not related to units, but from a purely abstract point of view:

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.

mschauer commented 6 years ago

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.

andreasnoack commented 6 years ago

Assuming one(x) exists, zero(one(x)) would be synonymous with zeronounit(x).

I don't think that theorem is true. Try with a Float64. hint The absorbing element for Float64s under * isn't 0.0.

StefanKarpinski commented 6 years ago

The absorbing element for Float64s under * isn't 0.0.

0.0 also isn't the additive identity for Float64, technically.

goretkin commented 5 years ago

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)