Need help with adding Composite types to Arrays


#1

Hello, I am new to Julia and need some help please.
I want to use Composite types and add them to an Array.
The following is a simple example:

type State
  x::Int64
end

s=State(1)
data = Array{State}(1)
data[1]=s
println(data[1].x)

for i=2:5
  s.x=i
  push!(data,s)
  println(data[i].x)
end

Run it in Julia:

julia> include("test2.jl")
1
2
3
4
5

So it seems to work.
But if i now enter data[2].x (or data[1].x, data[3].x…) in the command line:

julia> data[2].x
5

or another example:

julia> data
5-element Array{State,1}:
 State(5)
 State(5)
 State(5)
 State(5)
 State(5)

I don’t understand why data is filled correctly during the for-loop but afterwards the data Arrays only contains the last State with x=5
I would appreciate any help. thanks in advance


#2

You kept mutating and adding the same type. If you want different instances of State, you need to either construct different instances of state like

for i=2:5
  s = State(i)
  push!(data,s)
  println(data[i].x)
end

or copy and mutate

for i=2:5
  s_tmp = copy(s) # might need to deepcopy depending on what the type holds
  s_tmp.x=i
  push!(data,s_tmp)
  println(data[i].x)
end

Yes, these will allocate but you have to allocate if you want a different object (no magic will get around that limitation)!


#3

ah okay. I thought i could change State by just using s.x=i and add it to the array as a new State
I tried your first suggestion and it’s running perfectly now.
Thank you very much for your quick help!


#4

Even though you didn’t ask, here is a further bit of advice. When building an array of composite objects in which each object is a relatively small ‘bits’ type item, an immutable rather than a type is usually preferred for the objects. The immutable would typically give better performance because there is one fewer level of indirection. Furthermore, there is no possibility that two array entries with different indices would actually be the same object (as in your original code), thus making it simpler to reason about code correctness.


#5

Thanks for your advice. I will try using immutable instead of type.