使用推!修改不可变的复合类型字段
Using push! to modify immutable composite type fields
以下代码允许修改不可变复合类型的字段,我不确定为什么允许这样做:
struct A
a :: Vector{Int}
function A(a :: Vector{Int})
new(a)
end
end
myA = A([1,2,3])
@show myA.a # myA.a = [1, 2, 3]
push!(myA.a, 4)
@show myA.a # myA.a = [1, 2, 3, 4]
相反,不允许通过类型方法修改它:
struct A
a :: Vector{Int}
function A(a :: Vector{Int})
new(a)
end
end
function changeAa!(myA::A, a::Vector{Int})
myA.a = a
end
myA = A([1,2,3])
changeAa!(myA, [1,2,3,4])
产生:ERROR: LoadError: setfield!: immutable struct of type A cannot be changed
(应该如此)。
查看 this question,似乎需要保留该字段指向的对象(push!
就是这种情况),但我仍然不确定如何自己实现它。有人可以详细说明一下吗?谢谢。
I am still unsure how I could implement that myself.
不清楚您要实现什么。能解释一下吗?
myA.a = a
是不允许的,因为它会修改 myA
变量绑定到的对象,这是不允许的。
现在请注意,在 push!
变体中有以下表达式:
push!(myA.a, 4)
相当于写成例如:
b = myA.a
push!(b, 4)
我写这篇文章是为了告诉你重要的是 Vector
是可变的(相对于 struct
)。该对象绑定到 myA.a
还是 b
并不重要。 push!
函数只是传递了一个值,它是一个 Vector
,因为这个向量是可变的,所以它会改变它。
总而言之:要理解的关键是在 Julia 中你使用的是价值观。值是可变的或不可变的。然后您可以将值绑定到变量名。但是,一个值绑定到什么变量名并不影响这个值的属性。变量名只是一个“标签”,允许您引用值。
这是否澄清了您的疑问?
编辑:
myA
不可变的事实意味着 myA
在内存中的表示不会改变。
myA
在内存中的表示是什么?它只是一个指向数组的指针。不能改变的是指针的值,但是指针指向的内存内容是可以改变的。
你想要的功能可以定义为:
function changeAa!(myA::A, a::Vector{Int})
copy!(myA.a, a)
end
以下代码允许修改不可变复合类型的字段,我不确定为什么允许这样做:
struct A
a :: Vector{Int}
function A(a :: Vector{Int})
new(a)
end
end
myA = A([1,2,3])
@show myA.a # myA.a = [1, 2, 3]
push!(myA.a, 4)
@show myA.a # myA.a = [1, 2, 3, 4]
相反,不允许通过类型方法修改它:
struct A
a :: Vector{Int}
function A(a :: Vector{Int})
new(a)
end
end
function changeAa!(myA::A, a::Vector{Int})
myA.a = a
end
myA = A([1,2,3])
changeAa!(myA, [1,2,3,4])
产生:ERROR: LoadError: setfield!: immutable struct of type A cannot be changed
(应该如此)。
查看 this question,似乎需要保留该字段指向的对象(push!
就是这种情况),但我仍然不确定如何自己实现它。有人可以详细说明一下吗?谢谢。
I am still unsure how I could implement that myself.
不清楚您要实现什么。能解释一下吗?
myA.a = a
是不允许的,因为它会修改 myA
变量绑定到的对象,这是不允许的。
现在请注意,在 push!
变体中有以下表达式:
push!(myA.a, 4)
相当于写成例如:
b = myA.a
push!(b, 4)
我写这篇文章是为了告诉你重要的是 Vector
是可变的(相对于 struct
)。该对象绑定到 myA.a
还是 b
并不重要。 push!
函数只是传递了一个值,它是一个 Vector
,因为这个向量是可变的,所以它会改变它。
总而言之:要理解的关键是在 Julia 中你使用的是价值观。值是可变的或不可变的。然后您可以将值绑定到变量名。但是,一个值绑定到什么变量名并不影响这个值的属性。变量名只是一个“标签”,允许您引用值。
这是否澄清了您的疑问?
编辑:
myA
不可变的事实意味着 myA
在内存中的表示不会改变。
myA
在内存中的表示是什么?它只是一个指向数组的指针。不能改变的是指针的值,但是指针指向的内存内容是可以改变的。
你想要的功能可以定义为:
function changeAa!(myA::A, a::Vector{Int})
copy!(myA.a, a)
end