Types julia参数构造函数-外部构造函数的问题

Types julia参数构造函数-外部构造函数的问题,types,constructor,julia,Types,Constructor,Julia,我试图按照安德烈亚斯·诺克(Andreas Noack)在2015年斯坦福大学演讲中的素描来实现GF类型,但我在早期遇到了一些问题。我使用的是Julia 0.3.10 他的相关代码如下: # Scalar finite fields immutable GF{P,T<:Integer} <: Number data::T function GF(x::Integer) return new(mod(x, P)) end end # m

我试图按照安德烈亚斯·诺克(Andreas Noack)在2015年斯坦福大学演讲中的素描来实现GF类型,但我在早期遇到了一些问题。我使用的是Julia 0.3.10

他的相关代码如下:

# Scalar finite fields
immutable GF{P,T<:Integer} <: Number
    data::T
    function GF(x::Integer)
        return new(mod(x, P))
    end
end

    # methods for scalar finite field
import Base: convert, inv, one, promote_rule, show, zero

function call{P}(::Type{GF{P}}, x::Integer)
    if !isprime(P)
        throw(ArgumentError("P must be a prime"))
    end
    return GF{P,typeof(x)}(mod(x, P))
end
convert{P,T}(::Type{GF{P,T}}, x::Integer) = GF{P}(x)
convert{P}(::Type{GF{P}}, x::Integer) = GF{P}(x)
convert{P,T}(::Type{GF{P,T}}, x::GF{P}) = GF{P,T}(x.data)
promote_rule{P,T1,T2<:Integer}(::Type{GF{P,T1}}, ::Type{T2}) = GF{P,promote_type(T1,T2
)}
show(io::IO, x::GF) = show(io, x.data)
你得到

无法构造类型

好的,所以没有自动构造函数

GF{2,Int64}(11)

问题在于没有自动构造函数,其他函数(如zero(x))会失败

尝试创建外部构造函数对我来说不起作用:

我认为
GF{p}(x::Integer)=GF{p,Int64}(x)
应该可以工作,但我得到了

警告:在[4]:1中,GF的签名中未出现静态参数p。 该方法将不可调用

基本上,关于如何指定一个类似 GF{3}(x)应该创建GF{3,typeof(x)}(x)的实例

我知道我错过了一些显而易见的东西


谢谢

不幸的是,这在0.3上根本不可能实现。重载
调用
的功能是0.4中提供的一大新功能。调用不完全参数化的类型(如
GF{2}
)需要此功能。看起来Andreas在这个演示中使用了0.4-dev版本;如果你想直接关注他的演示,我建议你也这样做


更多详细信息和解决方法:

在0.3中,只需调用类型即可调用类型的内部构造函数,但它必须是具体(或[leaf])类型。这意味着,如果它具有类型参数,则必须对其进行完全参数化。在本例中,这意味着您需要手动指定整数类型,以便调用内部构造函数:
GF{2,Int}(5)

您还可以定义外部构造函数,其外观和行为与碰巧具有相同基名称的泛型函数类似。您也可以将类型参数添加到泛型函数中,但尽管它们看起来与类型的参数相似(尤其是在名称相同时),但它们的行为却截然不同!函数的参数定义一个局部变量,该变量将用于匹配参数的类型。这就是为什么你的定义
GF{P}(x::Integer)=GF{P,Int64}(x)
会抛出这样的警告:因为你从不使用
P
来定义参数类型,Julia将无法弄清楚
P
应该是什么,因此它永远不会被调用。我们可以创建一个函数,该函数总是生成一个
GF{2}

julia> GF2{T}(x::T) = GF{2,T}(x) # Call the fully parameterized inner constructor
GF2 (generic function with 1 method)

julia> GF2(3)
GF{2,Int64}(1)
请注意,当我调用
GF2
时,我没有指定
t
应该是什么-朱莉娅明白了这一点。当您为参数化类型定义外部构造函数时,这会让人感到困惑,因为
GF{P}(x::Integer)=…
是函数参数和类型参数看起来相同的重叠点!函数参数胜出,因此,虽然您可以使用参数定义外部构造函数,但这些参数的含义不同,您可以在不使用它们的情况下调用外部构造函数:
GF(…)
。您可以调用内部构造函数,但必须在那里指定所有参数:
GF{2,Int}(…)
。0.3没有中间地带

这在0.4中有所改变:现在您可以定义调用任意对象时发生的情况!这就是
函数调用{P}(::Type{GF{P},x::Integer)
所定义的:如果调用不完整的类型
GF{2}
,那么将使用
P=2
调用此方法。事实上,这概括了外部构造函数。外部构造函数(即使是参数化的)只是一个“糖”,用于定义类型
GF
调用(::Type{GF},x::Integer)
,而不带任何参数。这就是0.4如何通过调用重载实现各种出色的行为


如果您真的想在0.3上实现这一点,您可以在硬编码
p
值上方定义类似于
GF2
的函数,或者降低类型的灵活性:

immutable GF{P} <: Number
    data::Int
    function GF(x::Integer)
        return new(mod(convert(Int, x), P))
    end
end

<代码>不变的GF{p}多谢,这有很大帮助,移动到开发分支似乎是走的路…@罗宾如果你觉得这个(极好的)回答回答你的问题,那么请通过点击反应旁边的嘀嗒记号来指示,并考虑投票。干杯
immutable GF{P} <: Number
    data::Int
    function GF(x::Integer)
        return new(mod(convert(Int, x), P))
    end
end