【问题标题】:Julia immutable struct with mutable list具有可变列表的 Julia 不可变结构
【发布时间】:2021-09-13 11:46:36
【问题描述】:

这是一些损坏的代码:

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 声明为mutable struct(使一切都是可变的)
  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


其他说明:

【问题讨论】:

    标签: julia immutability


    【解决方案1】:

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

    1. 如果您真的想重新分配字段values::Vector{Int64} 本身,那么您必须使用mutable struct。没有办法解决这个问题,因为当您重新分配该字段时,结构的实际数据会发生变化。
    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 几乎是使不可变结构的字段间接充当可变字段的方法。它的工作原理如下:字段不能更改 which 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])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-09
      • 1970-01-01
      相关资源
      最近更新 更多