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

    # 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}(11)

你得到

类型无法构造

好的,因此没有自动构造函数。

GF{2,Int64}(11) 工作良好。

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

尝试构造外部构造函数对我没有起作用:

我认为GF{P}(x::Integer) = GF{P,Int64}(x)应该可以,但是我明白了

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

基本上,我对于如何指定像GF {3}(x)这样的调用应创建GF {3,typeof(x)}(x)实例的想法不多了

我知道我缺少明显的东西。

谢谢

马特·B。

不幸的是,这在0.3上根本不可能。过载能力call是0.4中将提供的一项重大新功能。调用不完全参数化的类型(如)需要此功能GF{2}看起来Andreas在此演示中使用的是0.4开发版本。如果您想直接观看他的演示,我建议您也这样做。


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

在0.3中,您可以通过简单地调用类型来调用类型的内部构造函数-但它必须是具体的(或[叶子])类型。这意味着,如果具有类型参数,则必须对其进行完全参数化。在这种情况下,这意味着您将需要手动指定整数类型才能调用内部构造函数: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)

请注意,我并没有说明具体T应该是,当我打电话GF2-朱莉娅想通了这一点。当您为参数化类型定义外部构造函数时,这变得令人困惑,因为GF{P}(x::Integer) = …函数参数和类型参数看起来是相同的重叠点!函数参数将获胜,因此,尽管您可以使用参数定义外部构造函数,但这些参数的含义有所不同,您可以在不使用它们的情况下调用外部构造函数:GF(…)您可以调用内部构造函数,但是必须在其中指定所有参数:GF{2, Int}(…)0.3没有中间地带。

更改为0.4:现在,您可以定义调用任意对象时发生的情况!function call{P}(::Type{GF{P}}, x::Integer)就是定义:如果您调用不完整类型GF{2},则将使用调用此方法P=2实际上,这可以概括外部构造函数。外部构造函数(即使已将其参数化)只是用于定义call(::Type{GF}, x::Integer)类型GF而没有任何参数的“糖” 因此,这就是0.4通过调用过载实现各种出色行为的方式。


如果您确实想在0.3上实现此功能,则可以定义GF2上面的函数,对P值进行硬编码,也可以降低类型的灵活性:

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

现在内部构造函数正是您想要的:GF{P},因此您可以GF{2}(5)直接调用但是您在使用的整数类型上失去了灵活性。也有其他技巧,但这是另外一次。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章