{"action":"created","issue":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/34003","repository_url":"https://api.github.com/repos/JuliaLang/julia","labels_url":"https://api.github.com/repos/JuliaLang/julia/issues/34003/labels{/name}","comments_url":"https://api.github.com/repos/JuliaLang/julia/issues/34003/comments","events_url":"https://api.github.com/repos/JuliaLang/julia/issues/34003/events","html_url":"https://github.com/JuliaLang/julia/issues/34003","id":530983185,"node_id":"MDU6SXNzdWU1MzA5ODMxODU=","number":34003,"title":"Defining zero() seriously","user":{"login":"jiahao","id":1732,"node_id":"MDQ6VXNlcjE3MzI=","avatar_url":"https://avatars3.githubusercontent.com/u/1732?v=4","gravatar_id":"","url":"https://api.github.com/users/jiahao","html_url":"https://github.com/jiahao","followers_url":"https://api.github.com/users/jiahao/followers","following_url":"https://api.github.com/users/jiahao/following{/other_user}","gists_url":"https://api.github.com/users/jiahao/gists{/gist_id}","starred_url":"https://api.github.com/users/jiahao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jiahao/subscriptions","organizations_url":"https://api.github.com/users/jiahao/orgs","repos_url":"https://api.github.com/users/jiahao/repos","events_url":"https://api.github.com/users/jiahao/events{/privacy}","received_events_url":"https://api.github.com/users/jiahao/received_events","type":"User","site_admin":false},"labels":[{"id":66307780,"node_id":"MDU6TGFiZWw2NjMwNzc4MA==","url":"https://api.github.com/repos/JuliaLang/julia/labels/julep","name":"julep","color":"F4F0CB","default":false,"description":"Julia Enhancement Proposal"},{"id":171885699,"node_id":"MDU6TGFiZWwxNzE4ODU2OTk=","url":"https://api.github.com/repos/JuliaLang/julia/labels/maths","name":"maths","color":"009800","default":false,"description":"Mathematical functions"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":12,"created_at":"2019-12-02T08:58:27Z","updated_at":"2019-12-11T17:59:56Z","closed_at":null,"author_association":"MEMBER","body":"(This issue is a follow-up to #34000 #28854 #31303)\r\n\r\nThe docstring for `zero(x)` says\r\n\r\n> Get the additive identity element for the type of x\r\n\r\nHowever, 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).\r\n\r\n1. 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\r\n\r\n```julia\r\njulia> Float16(0.0) + Float32(1.0) === Float32(1.0) #works for Float32\r\ntrue\r\n\r\njulia> Float16(0.0) + Float16(1.0) === Float16(1.0) #and for Float16\r\ntrue\r\n```\r\n\r\n  would argue that `zero(Union{Float16,Float32}) === Float16(0.0)` (it is currently undefined).\r\n\r\n2. A counterargument to the above would be that `Int(0)` is also a valid choice for `zero(Union{Float16,Float32})`, since\r\n\r\n```julia\r\njulia> 0 + Float16(1.0) === Float16(1.0) # works because of type promotion\r\ntrue\r\n```\r\n\r\n   However, the statement above would also imply that `Int(0)` is a valid choice for `zero(Float16)`.\r\n   We can exclude this value by requiring `zero()` to be endomorphic, i.e. `zero(::T) :: T`, and by extension `zero(T) :: T`.\r\n\r\n3. `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`:\r\n\r\n```\r\njulia> zero(Union{Int,Complex})\r\n0\r\n\r\njulia> zero(Union{Real,Complex}) #due to type promotion, see #2\r\n0\r\n\r\njulia> 0 + Complex{Bool}(0) === Complex{Bool}(0) # Counterexample: actually Complex{Int}(0), so Int(0) is not an additive identity over Complex\r\nfalse\r\n\r\njulia> Int(0) + Int16(0) === Int(0) #Counterexample: Int16 <: Real but adding Int(0) to it promotes to Int\r\ntrue\r\n\r\njulia> Int(0) + false === Int(0) #Counterexample: Bool <: Real but adding Int(0) to it promotes to Int\r\ntrue\r\n```\r\n\r\n---\r\n\r\n## Proposal\r\n\r\n1. `zero(T)` for non-union types should be defined as the unique additive identity such that\r\n    a. `zero(T)::T`, i.e. `zero()` is an endomorphism, and\r\n    b. The identity `zero(T) + zero(T) === zero(T)` is satisfied for all `T`.\r\n\r\n2. `zero(Union{T,S}) === zero(T)` when `zero(T) + zero(S) === zero(S)`, taking into account type promotion rules.\r\n\r\n3. If no unique endomorphic zero exists, then `zero(T)` should be undefined, except for `zero(Bool) === false` as a special case.\r\n\r\nThis definition would preserve the endomorphic property for leaf types, like `zero(Float16) === Float16(0.0)`.\r\n\r\nThis definition would preserve the result for `zero(Bool) === false`, to be consistent with current arithmetic semantics of `Bool`. \r\n\r\nThis definition would preserve the semantics of #28854 for `zero(Missing) === missing`.\r\n\r\nThis definition would define `zero(Union{Float16,Float32,Float64})` to be `Float16(0.0)` (currently undefined).\r\n\r\nThis definition would define `zero(Union{Float16,Int16})` to be `Int16(0)` (currently undefined).\r\n\r\nThis definition would *change* `zero(Real)` to be `false` (and similarly in Case 3 above; currently `Int(0)`); arguably a bug fix.\r\n\r\nThis definition would *change* `zero(Union{Bool,Int})` to be `false` (currently `Int(0)`); arguably a bug fix.\r\n"},"comment":{"url":"https://api.github.com/repos/JuliaLang/julia/issues/comments/564662179","html_url":"https://github.com/JuliaLang/julia/issues/34003#issuecomment-564662179","issue_url":"https://api.github.com/repos/JuliaLang/julia/issues/34003","id":564662179,"node_id":"MDEyOklzc3VlQ29tbWVudDU2NDY2MjE3OQ==","user":{"login":"StefanKarpinski","id":153596,"node_id":"MDQ6VXNlcjE1MzU5Ng==","avatar_url":"https://avatars2.githubusercontent.com/u/153596?v=4","gravatar_id":"","url":"https://api.github.com/users/StefanKarpinski","html_url":"https://github.com/StefanKarpinski","followers_url":"https://api.github.com/users/StefanKarpinski/followers","following_url":"https://api.github.com/users/StefanKarpinski/following{/other_user}","gists_url":"https://api.github.com/users/StefanKarpinski/gists{/gist_id}","starred_url":"https://api.github.com/users/StefanKarpinski/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/StefanKarpinski/subscriptions","organizations_url":"https://api.github.com/users/StefanKarpinski/orgs","repos_url":"https://api.github.com/users/StefanKarpinski/repos","events_url":"https://api.github.com/users/StefanKarpinski/events{/privacy}","received_events_url":"https://api.github.com/users/StefanKarpinski/received_events","type":"User","site_admin":false},"created_at":"2019-12-11T17:59:56Z","updated_at":"2019-12-11T17:59:56Z","author_association":"MEMBER","body":"I don't disagree; what would you prefer to write?"}}
{"actor":{"display_login":"StefanKarpinski"}}