这是一些损坏的代码:
struct NumberedList
index::Int64
values::Vector{Int64}
NumberedList(i) = new(i, Int64[])
end
function set_values!(list::NumberedList, new_values::Vector{Int64})
list.values = new_values
end
# ---
mylist = NumberedList(1)
set_values!(mylist, [1, 2, 3])
我不想做这些中的任何一个:
- 我可以将
NumberedList
声明为可变结构
(使一切 可变) - 我可以用这样的东西替换
set_values!
(复制所有值):
function set_values!(list::NumberedList, new_values::Vector{Int64})
for i in new_values
push!(list.values, i)
end
end
但我想使 index
不可变,但允许将 values
分配给。
其他说明:
- 主题来自 Discourse:“Mutable field in immutable type ”,但这不适用于此设置中的矢量。
最佳答案
这取决于你到底想改变什么。
- 如果您真的想重新分配字段
values::Vector{Int64}
本身,那么您必须使用可变结构
。没有办法解决这个问题,因为当您重新分配该字段时,结构的实际数据会发生变化。 - 如果您使用带有
values::Vector{Int64}
字段的不可变结构,这意味着您无法更改包含哪个数组,但数组本身是可变的并且可以改变它的元素(不存储在结构中)。在这种情况下,您确实必须将值从外部数组复制到它,就像您的示例代码一样(尽管我会指出您的代码没有将数组重置为空数组)。我个人认为这会更干净:
function set_values!(list::NumberedList, new_values::Vector{Int64})
empty!(list.values) # reset list.values to Int64[]
append!(list.values, new_values)
end
- 您链接的主题讨论了使用
Base.Ref
。Base.Ref
几乎是使不可变结构的字段间接充当可变字段的方法。它是这样工作的:该字段不能更改包含RefValue{Vector{Int64}}
实例的哪个,但实例本身是可变的并且可以更改其引用(同样,不是存储在结构中)到任何Int64
数组。不过,您必须使用索引values[]
来访问数组:
struct NumberedList
index::Int64
values::Ref{Vector{Int64}}
NumberedList(i) = new(i, Int64[])
end
function set_values!(list::NumberedList, new_values::Vector{Int64})
list.values[] = new_values # "reassign" different array to Ref
end
# ---
mylist = NumberedList(1)
set_values!(mylist, [1, 2, 3])
关于具有可变列表的 Julia 不可变结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69156101/