I'm re-reading The Julia Language Documentation in interest for building a performance sound queue application, and the section regarding parametric constructors and outer constructors has me confused. The example they show is as follows:
julia> struct OurRational{T<:Integer} <: Real
num::T
den::T
function OurRational{T}(num::T, den::T) where T<:Integer
if num == 0 && den == 0
error("invalid rational: 0//0")
end
g = gcd(den, num)
num = div(num, g)
den = div(den, g)
new(num, den)
end
end
julia> OurRational(n::T, d::T) where {T<:Integer} = OurRational{T}(n,d)
OurRational
julia> OurRational(n::Integer, d::Integer) = OurRational(promote(n,d)...)
OurRational
julia> OurRational(n::Integer) = OurRational(n,one(n))
OurRational
The documentation states:
The first is the "standard" general (outer) constructor that infers the type parameter T from the type of the numerator and denominator when they have the same type.
From this I come to understand this constructor handles the case of two parameters. It infers T from (num and den)'s type, then supplies it to the OurRational internal constructor.
The documentation goes on to say:
The second applies when the given numerator and denominator values have different types: it promotes them to a common type and then delegates construction to the outer constructor for arguments of matching type.
Looking at the code, I do not see how this is case. Based on how I think Julia is evaluating, wouldn't the second constructor handle the case where both n and d are explicit Integers? If otherwise, I am seriously having trouble seeing how Julia sees this line. Also, the ellipses in the assignment suffix means something like "now go to the outer constructor for when both parameters have the same type" right?
I understand the third outer constructor well.