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

时间:2014-12-09 03:53:09

标签: immutability julia mutable

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

设置:我的复合类型如下:

type MyType
    x::Vector{String}
end

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

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

我的理解:我已经阅读了关于此问题的Julia docs,以及关于Stackoverflow的更一般(以及高度投票)的问题(例如here或{ {3}}),但从实际角度来看,我仍然没有很好地处理可变/不可变的含义(特别是对于不可变复合类型的情况,包含可变类型的可变数组!)

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

MyType.x[1] = "NewValue"
push!(MyType.x, "NewElementToAdd")

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

MyType.x = ["a", "different", "string", "array"]

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

最后一点:如果这似乎与SO上的其他问题重复,我道歉。如上所述,我已经查看了它们,并且无法理解我所追求的。

1 个答案:

答案 0 :(得分:6)

所以这里有一些需要考虑的事情(至少对我而言):

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

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

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