10

Initial note: I'm working in Julia, but this question probably applies to many languages.

Setup: I have a composite type as follows:

type MyType
    x::Vector{String}
end

I write some methods to act on MyType. For example, I write a method that allows me to insert a new element in x, e.g. function insert!(d::MyType, itemToInsert::String).

Question: Should MyType be mutable or immutable?

My understanding: I've read the Julia docs on this, as well as more general (and highly upvoted) questions on Stackoverflow (e.g. here or here), but I still don't really have a good handle on what it means to be mutable/immutable from a practical perspective (especially for the case of an immutable composite type, containing a mutable array of immutable types!)

Nonetheless, here is my attempt: If MyType is immutable, then it means that the field x must always point to the same object. That object itself (a vector of Strings) is mutable, so it is perfectly okay for me to insert new elements into it. What I am not allowed to do is try and alter MyType so that the field x points to an entirely different object. For example, methods that do the following are okay:

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

But methods that do the following are not okay:

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

Is this right? Also, is the idea that the object that an immutable types field values are locked to are those that are created within the constructor?

Final Point: I apologise if this appears to duplicate other questions on SO. As stated, I have looked through them and wasn't able to get the understanding that I was after.

Community
  • 1
  • 1
Colin T Bowers
  • 18,106
  • 8
  • 61
  • 89

1 Answers1

7

So here is something mind bending to consider (at least to me):

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

So the data address is actually changing as the vector grows and needs to be reallocated! But - you can't change data yourself, as you point out.

I'm not sure there is a 100% right answer is really. I primarily use immutable for simple types like the Complex example in the docs in some performance critical situations, and I do it for "defensive programming" reasons, e.g. the code has no need to write to the fields of this type so I make it an error to do so. They are a good choice IMO whenever the type is a sort of an extension of a number, e.g. Complex, RGBColor, and I use them in place of tuples, as a kind of named tuple (tuples don't seem to perform well with Julia right now anyway, wheres immutable types perform excellently).

IainDunning
  • 11,546
  • 28
  • 43
  • 4
    While Julian arrays aren't implemented in Julia itself, I think of an array has having multiple fields (for the dimensionality and the pointer to the memory where the data resides). `pointer(x.data)` shows where that memory field points… and that it changes *within* the vector object. But repeat your experiment, this time with [`pointer_from_objref(x.data)`](http://docs.julialang.org/en/latest/stdlib/base/?highlight=pointer_from_objref#Base.pointer_from_objref) to show the address of the Vector object itself. – mbauman Dec 09 '14 at 15:29
  • 2
    See [julia.h:88-120](https://github.com/JuliaLang/julia/blob/master/src/julia.h#L88-L120) for how the array objects are laid out in memory as a bare C struct. – mbauman Dec 09 '14 at 15:42
  • Ah that makes more sense – IainDunning Dec 09 '14 at 16:01
  • Thanks for responding. I must admit this discussion is going a little over my head (I'm from a Matlab background, so I've never had to think about pointers before). Any chance you could dumb it down a bit for me? Thanks either way - I'll think on what you've said. – Colin T Bowers Dec 09 '14 at 23:51
  • is ``immutable Foo`` the same as (in 2021 parlance) ``struct Foo`` ? Thanks. – PatrickT Apr 16 '21 at 00:15
  • 1
    @PatrickT Yes. `struct` is immutable, and `mutable struct` is mutable (in 2021 parlance) – Colin T Bowers Nov 21 '21 at 04:37