为什么 "The Julia Language Documentation" 中的这一行为输入参数是不同类型的情况定义了一个外部构造函数?
Why does this line from "The Julia Language Documentation" define an outside constructor for a case where input parameteres are different types?
我正在重新阅读 Julia 语言文档以构建性能声音队列应用程序,有关参数构造函数和外部构造函数的部分让我感到困惑。他们展示的例子如下:
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 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.
由此我开始理解这个构造函数处理两个参数的情况。它从 (num 和 den) 的类型推断出 T,然后将其提供给 OurRational 内部构造函数。
文档接着说:
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.
查看代码,我不明白这是怎么回事。根据我认为 Julia 的评估方式,第二个构造函数不会处理 n 和 d 都是显式整数的情况吗?否则,我真的很难看到 Julia 是如何看待这条线的。此外,赋值后缀中的省略号表示类似 "now go to the outer constructor for when both parameters have the same type" 的意思,对吧?
我理解第三个外部构造函数。
第一个和第二个外部构造函数不同,因为第二个构造函数处理分子和分母都是整数的情况,但它们是两个不同的具体子类型,都是抽象类型 Integer。
如您所知,Julia 有许多内置的整数类型。考虑例如 UInt8,
这是单字节语法的默认类型,例如 0x1f。看结果的时候
我们混合使用 UInt8 和默认的 Integer 类型 Int64:
julia> struct OurRational{T<:Integer} <: Real
num::T
den::T
function OurRational{T}(num::T, den::T) where T<:Integer
println("Inner")
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>
julia> OurRational(n::T, d::T) where {T<:Integer} = begin println("Outer 1"); OurRational{T}(n,d) end
OurRational
julia> OurRational(n::Integer, d::Integer) = begin println("Outer 2"); OurRational(promote(n,d)...) end
OurRational
julia> OurRational(n::Integer) = begin println("Outer 3"); OurRational(n,one(n)) end
OurRational
julia> OurRational{UInt8}(0x2, 0x5)
Inner
OurRational{UInt8}(0x02, 0x05)
julia> OurRational(2, 5)
Outer 1
Inner
OurRational{Int64}(2, 5)
julia> OurRational(0x2, 5)
Outer 2
Outer 1
Inner
OurRational{Int64}(2, 5)
julia> OurRational(0x3)
Outer 3
Outer 1
Inner
OurRational{UInt8}(0x03, 0x01)
因此,第二个外部构造函数将参数提升为相同类型,然后将它们传递给第一个外部构造函数,然后传递给内部构造函数。
我正在重新阅读 Julia 语言文档以构建性能声音队列应用程序,有关参数构造函数和外部构造函数的部分让我感到困惑。他们展示的例子如下:
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 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.
由此我开始理解这个构造函数处理两个参数的情况。它从 (num 和 den) 的类型推断出 T,然后将其提供给 OurRational 内部构造函数。
文档接着说:
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.
查看代码,我不明白这是怎么回事。根据我认为 Julia 的评估方式,第二个构造函数不会处理 n 和 d 都是显式整数的情况吗?否则,我真的很难看到 Julia 是如何看待这条线的。此外,赋值后缀中的省略号表示类似 "now go to the outer constructor for when both parameters have the same type" 的意思,对吧?
我理解第三个外部构造函数。
第一个和第二个外部构造函数不同,因为第二个构造函数处理分子和分母都是整数的情况,但它们是两个不同的具体子类型,都是抽象类型 Integer。
如您所知,Julia 有许多内置的整数类型。考虑例如 UInt8, 这是单字节语法的默认类型,例如 0x1f。看结果的时候 我们混合使用 UInt8 和默认的 Integer 类型 Int64:
julia> struct OurRational{T<:Integer} <: Real
num::T
den::T
function OurRational{T}(num::T, den::T) where T<:Integer
println("Inner")
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>
julia> OurRational(n::T, d::T) where {T<:Integer} = begin println("Outer 1"); OurRational{T}(n,d) end
OurRational
julia> OurRational(n::Integer, d::Integer) = begin println("Outer 2"); OurRational(promote(n,d)...) end
OurRational
julia> OurRational(n::Integer) = begin println("Outer 3"); OurRational(n,one(n)) end
OurRational
julia> OurRational{UInt8}(0x2, 0x5)
Inner
OurRational{UInt8}(0x02, 0x05)
julia> OurRational(2, 5)
Outer 1
Inner
OurRational{Int64}(2, 5)
julia> OurRational(0x2, 5)
Outer 2
Outer 1
Inner
OurRational{Int64}(2, 5)
julia> OurRational(0x3)
Outer 3
Outer 1
Inner
OurRational{UInt8}(0x03, 0x01)
因此,第二个外部构造函数将参数提升为相同类型,然后将它们传递给第一个外部构造函数,然后传递给内部构造函数。