gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 19:03:20 25 4
gpt4 key购买 nike

我正在尝试按照 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)

你得到

type cannot be constructed



好的,所以没有自动构造函数。
GF{2,Int64}(11)工作正常。

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

尝试制作外部构造函数并没有为我工作:

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

Warning: static parameter P does not occur in signature for GF at In[4]:1. The method will not be callable.



基本上我已经没有关于如何指定一个电话的想法了
GF{3}(x) 应该创建一个 GF{3,typeof(x)}(x) 的实例

我知道我错过了一些非常明显的东西。

谢谢

最佳答案

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

更多细节和解决方法:

在 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 的时候—— Julia 想通了。当您为参数化类型定义外部构造函数时,这只会让人感到困惑,因为 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)直接地。但是您已经失去了正在使用的整数类型的灵 active 。还有其他技巧,但那是另一次了。

关于types - julia 参数构造函数 - 外部构造函数的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31334824/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com