的回答您的具体问题:
当你定义在朱莉娅一个新的类型,常见的是一些在Base
标准方法扩展到新的类型,包括deepcopy
。例如:
type MyType
x::Vector
y::Vector
end
import Base.deepcopy
Base.deepcopy(m::MyType) = MyType(deepcopy(m.x), deepcopy(m.y))
现在,您可以拨打deepcopy
超过MyType
一个实例,你会得到的MyType
一个新的,真正独立,副本输出。
请注意,我的import Base.deepcopy
实际上是多余的,因为我在我的函数定义中引用了Base
,例如, Base.deepcopy(m::MyType)
。但是,我做了这两个向您展示了从Base
扩展方法的两种方法。
其次注意,如果您的类型有很多领域,你可能反而比使用deepcopy
领域的迭代如下:
Base.deepcopy(m::MyType) = MyType([ deepcopy(getfield(m, k)) for k = 1:length(names(m)) ]...)
你的代码中的注释:
首先, Julia的标准做法是大写类型名称,例如Component1
而不是component1
。当然,你不必这样做,但...
二,从Julia docs performance tips:声明复合类型的字段的具体类型。请注意,您可以参数化这些声明,例如
type Component1{T1, T2}
x::T1
y::T2
end
第三,这里是我会怎样定义你的新类型:
type Mixture{T}
components::Vector{T}
Mixture{T}(c::Vector{T}) = new(c)
end
Mixture{T}(c::Vector{T}) = Mixture{eltype(c)}(c)
Mixture(x, K::Int) = Mixture([ deepcopy(x) for k = 1:K ])
有我的代码和你之间这里有几个重要区别。我会一次一个地检查他们。
您的K
字段是多余的(我认为),因为它似乎只是components
的长度。所以它可能是简单的length
方法只是扩展到新的类型,如下所示:
Base.length(m::Mixture) = length(m.components)
,现在你可以使用length(m)
,其中m
是得到什么以前存储在K
领域Mixture
一个实例。
您的类型mixture
中的内部构造函数不常见。标准做法是让内部构造函数将一对一(依次)与您的类型的字段相对应的参数,然后内部构造函数的其余部分仅执行任何错误检查,只要您初始化类型。你偏离了这个,因为qq
不是(必然)是一个数组。这种行为更适合外部构造函数。那么,我用构造函数做了什么?
Mixture
的内部构造函数除了通过new
将参数传递给字段之外,没有其他任何操作。这是因为目前没有任何错误检查需要执行(但我可以在将来轻松添加一些错误)。
如果我想调用这个内部构造函数,我需要写一些像m = Mixture{MyType}(x)
,其中x
是Vector{MyType}
。这有点烦人。因此,我的第一个外部构造函数使用eltype(x)
自动推断{...}
的内容。因为我的第一个外部构造的,我可以用现在初始化Mixture
的m = Mixture(x)
代替m = Mixture{MyType}(x)
我的第二个外部构造对应于你内心的构造函数。在我看来,您在此之后的行为是在components
的每个字段中重复使用Mixture
,并重复使用K
次。所以我通过x
来完成循环理解,只要定义了deepcopy
方法就可以工作。如果不存在deepcopy
方法,则会出现No Method Exists
错误。这种编程称为鸭子打字,在Julia中,使用它通常没有性能损失。
请注意,我的第二个外部构造函数会调用我的第一个外部构造函数K
次,并且每次我的第一个外部构造函数都会调用我的内部构造函数。在更复杂的情况下,以这种方式嵌套功能将大量减少代码重复。
对不起,这是我知道的很多东西。希望能帮助到你。
谢谢您的完整回复。我很熟悉多次调度的概念,但我不确定最好的方法是修改Base.deepcopy。 也感谢您的意见。关于第三条评论,并且避免了在构造函数中声明类型的需要,尽管我设法使用了你的方法,但是我不太明白它! – Adham
@Adham我已经更新了我的答案。如果现在还不清楚,让我知道,我会再试一次:-) –
谢谢。现在更清楚了(对我来说,作为Julia的初学者:D) – Adham