所以这是设置.我有多个复合类型定义了自己的字段和构造函数.让我们在这里展示两个简化的组件:
type component1
x
y
end
type component2
x
y
z
end
Run Code Online (Sandbox Code Playgroud)
现在我想定义一个新类型,以便它可以在其中保存一个大小为K的先前定义的复合类型的数组.因此它是具有两个字段的参数复合类型:一个是整数K,另一个是传递类型的大小为K的数组.
type mixture{T}
components::Array{T, 1}
K::Int64
function mixture(qq::T, K::Int64)
components = Array{typeof(qq), K}
for k in 1:K
components[k] = qq
end
new(components, K)
end
end
Run Code Online (Sandbox Code Playgroud)
但这不是正确的方法.因为所有K个组件都指的是一个对象并且操纵混合物.组件[k]将影响所有K个组件.在python中,我可以使用deepcopy来解决这个问题.但是Julia中的深度复制没有为复合类型定义.我该如何解决这个问题?
Col*_*ers 13
您的具体问题的答案:
在Julia中定义新类型时,通常会将一些标准方法扩展Base到新类型,包括deepcopy.例如:
type MyType
x::Vector
y::Vector
end
import Base.deepcopy
Base.deepcopy(m::MyType) = MyType(deepcopy(m.x), deepcopy(m.y))
Run Code Online (Sandbox Code Playgroud)
现在你可以调用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)) ]...)
Run Code Online (Sandbox Code Playgroud)
对您的代码的评论:
首先,Julia的标准做法是大写类型名称,例如Component1代替component1.当然,你不必这样做,但......
其次,来自Julia docs的性能提示:为复合类型的字段声明特定类型.注意,您可以参数化这些声明,例如
type Component1{T1, T2}
x::T1
y::T2
end
Run Code Online (Sandbox Code Playgroud)
第三,这是我如何定义你的新类型:
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 ])
Run Code Online (Sandbox Code Playgroud)
我的代码和你的代码之间有几个重要的区别.我会一次一个地浏览它们.
你的K领域是多余的(我认为),因为它似乎只是长度components.因此,将length方法扩展到新类型可能更简单,如下所示:
Base.length(m::Mixture) = length(m.components)
Run Code Online (Sandbox Code Playgroud)
现在你可以使用length(m),在这里m是一个实例Mixture得到什么以前存储在K现场.
你的类型中的内部构造函数mixture是不寻常的.标准做法是让内部构造函数接受与您的类型的字段一对一(按顺序)对应的参数,然后内部构造函数的其余部分只执行您希望在初始化时执行的任何错误检查类型.你偏离了这个,因为qq不是(必然)一个数组.这种行为最好保留给外部构造函数.那么,我对构造函数做了什么?
Mixture除了将参数传递给字段之外,内部构造函数并没有真正做任何事情new.这是因为目前我没有需要执行任何错误检查(但我将来可以轻松添加一些错误检查).
如果我要调用此内构造,我需要写类似m = Mixture{MyType}(x),这里x是Vector{MyType}.这有点烦人.所以我的第一个外部构造函数会自动推断出{...}使用的内容eltype(x).由于我的第一个外部构造函数,我现在可以Mixture使用m = Mixture(x)而不是使用m = Mixture{MyType}(x)
我的第二个外部构造函数对应于您的内部构造函数.在我看来,你在这里的行为是在重复的Mixture每个领域中用相同的组件初始化.所以我用循环理解来做这个,只要定义了方法,它就会起作用.如果不存在任何方法,则会出现错误.这种编程称为duck-typing,而在Julia中,使用它通常没有性能损失.componentsKxdeepcopyxdeepcopyNo Method Exists
注意,我的第二个外部构造函数将调用我的第一个外部构造函数K,每次,我的第一个外部构造函数将调用我的内部构造函数.在更复杂的情况下,以这种方式嵌套功能将大大减少代码重复.
对不起,我知道这很重要.希望能帮助到你.