针对您的具体问题作出回答:
在Julia中定义新类型时,通常会扩展一些标准方法到您的新类型中,包括deepcopy
。例如:
type MyType
x::Vector
y::Vector
end
import Base.deepcopy
Base.deepcopy(m::MyType) = MyType(deepcopy(m.x), deepcopy(m.y))
现在你可以对一个
MyType
实例调用
deepcopy
,并且你将得到一个全新,真正独立的
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文档性能提示中指出:为组合类型的字段声明特定类型。请注意,您可以对这些声明进行参数化,例如:
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
是
Mixture
的一个实例,以获取之前存储在
K
字段中的内容。
您类型
mixture
中的内部构造函数是不寻常的。标准做法是让内部构造函数接受与类型字段一一对应(按顺序)的参数,然后内部构造函数的剩余部分只执行任何您希望在初始化类型时执行的错误检查。由于
qq
不是(必要地)数组,您偏离了这种行为。这种行为最好保留给外部构造函数。那么,我对构造函数做了什么?
Mixture
的内部构造函数实际上并没有做任何事情,只是通过
new
将参数传递到字段中。这是因为目前没有任何需要执行的错误检查(但是我可以在未来轻松添加一些)。
如果我想调用此内部构造函数,我需要编写类似
m = Mixture{MyType}(x)
的东西,其中
x
是
Vector{MyType}
。这有点烦人。因此,我的第一个外部构造函数使用
eltype(x)
自动推断出
{...}
的内容。由于我的第一个外部构造函数,我现在可以使用
m = Mixture(x)
而不是
m = Mixture{MyType}(x)
来初始化
Mixture
。
我的第二个外部构造函数对应于您的内部构造函数。我认为您在此处追求的行为是使用重复
K
次的相同组件初始化
Mixture
中
components
的每个字段。因此,我使用循环推导式对
x
进行操作,只要对
x
定义了
deepcopy
方法,它就可以工作。如果不存在
deepcopy
方法,则会出现
No Method Exists
错误。这种编程称为鸭子类型,在Julia中通常不会有性能损失。
请注意,我的第二个外部构造函数将调用我的第一个外部构造函数
K
次,每次,我的第一个外部构造函数将调用我的内部构造函数。在更复杂的情况下,嵌套功能将大大减少代码重复。
抱歉,我知道这很多。希望有所帮助。