【发布时间】:2018-11-19 15:05:49
【问题描述】:
我有一个可变复合类型,
mutable struct MyType
x::Array{Float64}
end
我有一个函数,我想修改它,
function f(z::MyType)
newx = z.x + 1
z.x = newx
return z
end
这似乎不适用于更新 z。我错过了什么?
【问题讨论】:
标签: julia
我有一个可变复合类型,
mutable struct MyType
x::Array{Float64}
end
我有一个函数,我想修改它,
function f(z::MyType)
newx = z.x + 1
z.x = newx
return z
end
这似乎不适用于更新 z。我错过了什么?
【问题讨论】:
标签: julia
z.x 是一个数组,所以必须写 z.x .+ 1(注意多余的点)来表示逐元素添加。
function f(z::MyType)
newx = z.x .+ 1
z.x = newx
return z
end
这个函数确实更新z:
julia> z = MyType(rand(1:10, 4))
MyType([10.0, 7.0, 2.0, 2.0])
julia> f(z)
MyType([11.0, 8.0, 3.0, 3.0])
julia> z
MyType([11.0, 8.0, 3.0, 3.0])
julia> @btime f($z);
886.115 ns (4 allocations: 208 bytes)
分配是(至少)从它分配一个新数组newx(z.x 的副本,其中每个元素都增加一个)这一事实来理解的,然后将其设置为分配给@的新数组987654328@。之前分配给 z.x 的原始数组现在已丢失(并将被 gc'ed)。
您大概想要做的是在不创建中间数组的情况下就地修改分配给z.x 的数组。这可以通过编写来实现
function f(z::MyType)
z.x .= z.x .+ 1 # or equivalently z.x .+= 1
return z
end
注意 .= 而不是 = 就地分配(您可以考虑按元素分配)。这给了
julia> @btime f($z);
372.284 ns (2 allocations: 48 bytes)
请注意,您也可以写得更短
f(z::MyType) = (z.x .+= 1; z)
【讨论】:
z。这样做的效率更高。