HarrisonGrodin/radical-julia

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