具有可变列表的 Julia 不可变结构

标签 julia immutability

这是一些损坏的代码:

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])

我不想做这些中的任何一个:

  1. 我可以将NumberedList 声明为可变结构(使一切 可变)
  2. 我可以用这样的东西替换 set_values!(复制所有值):
function set_values!(list::NumberedList, new_values::Vector{Int64})
  for i in new_values
      push!(list.values, i)
  end
end

但我想使 index 不可变,但允许将 values 分配给。


其他说明:

最佳答案

这取决于你到底想改变什么。

  1. 如果您真的想重新分配字段values::Vector{Int64} 本身,那么您必须使用可变结构。没有办法解决这个问题,因为当您重新分配该字段时,结构的实际数据会发生变化。
  2. 如果您使用带有 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
  1. 您链接的主题讨论了使用 Base.RefBase.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/

相关文章:

Julia:成对距离的嵌套循环真的很慢

loops - 实现循环的快速方法

kotlin - 带有 `val` 修饰符的 `final` 属性的目的是什么?

java - 发布后不可变对象(immutable对象)的可见性

string - 字符串不可变有什么优势?

multithreading - 在 Julia 中使用多线程创建 JuMP 模型

julia - 为命名元组设置索引

javascript - 使用 .map() 使用 FileReader 读取多个文件

function - 如何在 Julia 中创建一个不返回任何内容的函数?

scala - 基于先前值更新 Map 中值的惯用方法