在Julia中了解具有可变类型字段的不可变复合类型

Col*_*ers 9 mutable immutability julia

初步说明:我在朱莉娅工作,但这个问题可能适用于许多语言.

设置:我有一个复合类型如下:

type MyType
    x::Vector{String}
end
Run Code Online (Sandbox Code Playgroud)

我写了一些方法来采取行动MyType.例如,我编写了一个允许我插入新元素的方法x,例如function insert!(d::MyType, itemToInsert::String).

问题:应该MyType是可变的还是一成不变的?

我的理解:我已经阅读了关于这个的Julia文档,以及关于Stackoverflow的更一般(和高度投票)的问题(例如这里这里),但我仍然没有很好地处理它意味着什么从实际角度看可变/不可变(特别是对于不可变复合类型的情况,包含可变类型的可变数组!)

尽管如此,这是我的尝试:如果MyType是不可变的,那么这意味着该字段x必须始终指向同一个对象.该对象本身(字符串的向量)是可变的,因此我可以在其中插入新元素.我不允许做的是尝试改变,MyType以便该字段x指向一个完全不同的对象.例如,执行以下操作的方法是可以的:

MyType.x[1] = "NewValue"
push!(MyType.x, "NewElementToAdd")
Run Code Online (Sandbox Code Playgroud)

但是执行以下操作的方法并不合适:

MyType.x = ["a", "different", "string", "array"]
Run Code Online (Sandbox Code Playgroud)

这是正确的吗?另外,是否认为不可变类型字段值被锁定的对象是在构造函数中创建的对象?

最后一点:如果这似乎与SO上的其他问题重复,我道歉.如上所述,我已经仔细研究过,并且无法理解我所追求的.

Iai*_*ing 7

所以这里有一些令人兴奋的事情(至少对我而言):

julia> immutable Foo
         data::Vector{Float64}
       end

julia> x = Foo([1.0, 2.0, 4.0])
Foo([1.0,2.0,4.0])

julia> append!(x.data, x.data); pointer(x.data)
Ptr{Float64} @0x00007ffbc3332018

julia> append!(x.data, x.data); pointer(x.data)
Ptr{Float64} @0x00007ffbc296ac28

julia> append!(x.data, x.data); pointer(x.data)
Ptr{Float64} @0x00007ffbc34809d8
Run Code Online (Sandbox Code Playgroud)

所以data地址实际上随着向量的增长而变化,需要重新分配!但是 - 正如您所指出的那样,您无法自己更改数据.

我不确定是否有100%正确答案.我主要immutable用于简单类型,Complex例如在某些性能危急情况下的文档中的示例,并且我是出于"防御性编程"的原因,例如代码不需要写入此类型的字段,因此我将其设为错误这样做.只要类型是数字的扩展,它们就是IMO的一个很好的选择,例如Complex,RGBColor我用它们代替元组,作为一种命名元组(元组现在似乎与Julia表现不佳)无论如何,不​​可变的类型表现得非常出色).

  • 虽然Julian数组没有在Julia本身中实现,但我认为数组有多个字段(对于维度和指向数据所在内存的指针).`pointer(x.data)`显示内存字段指向的位置......并且它在向量对象内变化*.但是重复你的实验,这次用[`pointer_from_objref(x.data)`](http://docs.julialang.org/en/latest/stdlib/base/?highlight=pointer_from_objref#Base.pointer_from_objref)来显示地址Vector对象本身. (4认同)
  • 参见[julia.h:88-120](https://github.com/JuliaLang/julia/blob/master/src/julia.h#L88-L120)用于阵列对象是如何在存储器布局作为裸C结构. (2认同)