Search code examples
structjuliafield-names

Variable fieldnames in Julia mutable structs


I would like to able to get fields from a mutable struct in Julia using a variable.

e.g.

mutable struct myType
    my_field1::Int = 1
    my_field2::Int = 2
    my_field3::Int = 3
end

And then let's imagine you declare a particular instance of this struct using struct_instance = myType()

How can you extract the value of a field from an instance of this mutable struct in a variable fashion?

Let's say you want to assign the value of my_struct.field[X] to a variable, using a for-loop, so that the particular field you're currently accessing depends on the variable X:

foo = zeros(Int64, 3)
for X = 1:3
    foo(X) = struct_instance.field[X]
end

I don't know how to actually implement the above for-loop -- what I wrote above is just pseudo-code above. In MATLAB you would use the following notation, for instance:

foo = zeros(1,3)
for x = 1:3
    foo(x) = struct_instance.(sprintf('field%d',x))
end

Thanks in advance.


Solution

  • For the code at the beginning of your example to work you need the Paramaters package, otherwise you are not able to have default values (the code from your example throws an error). I use it very often exactly in situations where I need a struct to use to represent a bunch of variables.

    using Parameters
    
    @with_kw mutable struct MyType
        my_field1::Int = 1
        my_field2::Int = 2
        my_field3::Int = 3
    end
    

    This generates also a set of keyword methods that can be used to set the fields programmatically when creating the object. Have a look at the following code:

    julia> vals = [Symbol("my_field$i") =>10i for i in 2:3 ]
    2-element Array{Pair{Symbol,Int64},1}:
     :my_field2 => 20
     :my_field3 => 30
    
    julia> MyType(;vals...)
    MyType
      my_field1: Int64 1
      my_field2: Int64 20
      my_field3: Int64 30
    

    We have created here a set of field names and now we are using it when creating an object. This approach is particularly useful when you could consider using immutable object instead of mutable ones (immutable objects are always much faster).

    You can mutate the object using setfield!:

    julia> for i in 1:2
               setfield!(m,Symbol("my_field$i"), 20i)
           end
    julia> m
    MyType
      my_field1: Int64 20
      my_field2: Int64 40
      my_field3: Int64 30
    

    I think that when you are coming from Matlab this would be the most convenient way to layout your structs.