Don't implement inv via / and binary - via unary -, do it the other way around
fingolfin opened this issue · 1 comments
A minor suggestion:
In general it is not possible to implement x-y
as x+(-y)
: think of a strict unsigned type, then -y
is not defined (at best one can implicitly convert to another signed type). Mathematically speaking, on the natural numbers, there is no unary minus; -1 is not a natural number; but there still is a binary minus: 2-1 = 1 is well-defined even though 1 is not.
I would therefore instead make binary minus a primitive, and define unary minus via zero(x)-x
Similar for inv(x): there is no inverse of 2 in the integers, but 4/2 = 2 is valid. So inv(x) = one(x)/x
I'm trying to find a situation where this makes a difference. I understand the closure argument, and interestingly enough it's different for division on Integer
vs subtraction on Unsigned
-(::T)::T where T <: Unsigned
, but inv(::Int)::Float64
. But a concrete example where this is happening would help.
julia> 0x00ff + -(0x01)
0x01fe
julia> 0x00ff - 0x01
0x00fe
julia> n(x) = zero(x) - x
n (generic function with 1 method)
julia> n(0x01)
0xff
julia> n(0x0001)
0xffff
I wonder if you looked at something like
julia> struct A <: Number
end
julia> -(A(), A())
ERROR: - not defined for A
Stacktrace:
[1] error(::String, ::String, ::Type{T} where T) at ./error.jl:42
[2] no_op_err(::String, ::Type{T} where T) at ./promotion.jl:383
[3] -(::A, ::A) at ./promotion.jl:386
[4] top-level scope at none:0
and read the error message as implying that there is a fallback on -(::A)
. There isn't, I just think the message is a bit misleading: https://github.com/JuliaLang/julia/blob/04e47cf5ff95daf887808f52b96d79ae03b1942a/base/promotion.jl#L387