Nate
Nate

Reputation: 211

Can I access a struct by name, eg A = field1, get struct.A?

Here's a psuedocode implementation of what I would be looking for within Julia:

struct Example
    field1::Float64
    field2::Float64
end # End struct 

example = Example(1., 2.)

function modifystruct(mystruct, fieldname)
    mystruct.fieldname +=10
    return mystruct
end 

modifystruct(example, field1)
# In this instance I would want to have example.field1 = 11.

How would I actually do this? I want to provide the fieldname as something like a string, and have my struct."whateverfieldname" get modified as such. I should add that I do NOT want to code something in like this:

function modifystruct(mystruct, fieldname)
    if fieldname = "fieldname1"
        mystruct.field1 +=10 
    end
    if fieldname = "fieldname2" 
        mystruct.field2 +=10
    end 
    return mystruct
end 

Largely due to how versatile I want this code to be. I may be using different types of structs for my program, so the closest I can get to directly accessing by the name of the field, the better. Is there any method or implementation that can do this for me?

Upvotes: 2

Views: 847

Answers (2)

phipsgabler
phipsgabler

Reputation: 20950

Sure, that's setproperty!(value, name, x) and getproperty(value, name):

function modifystruct(mystruct, fieldname)
    new_field = getproperty(mystruct, fieldname) + 10
    setproperty!(mystruct, fieldname, new_field)
    return mystruct
end 

As DecowVR rightly notes, this requires mystruct to be mutable.

If you want to do this repeatedly and with nested properties, you might be interested in lenses such as those provided by Setfield.jl.

Upvotes: 5

valcarcexyz
valcarcexyz

Reputation: 622

Firstly, whould be noticed that in order to be able to modify an struct, it needs to be mutable:

julia> mutable struct Example
           field1::Float64
           field2::Float64
       end

julia> example = Example(1., 2.)
Example(1.0, 2.0)

And now, a simple aproach would be to use Julia Symbols. A symbol is nothing else but an expression like :var. Can be used as shown:

julia> example.:field1
1.0

However, if we create a variable that stores the symbol, it won't work:

julia> v = :field1
:field1

julia> example.v
ERROR: type Example has no field v
Stacktrace:
 [1] getproperty(x::Example, f::Symbol)
   @ Base ./Base.jl:42
 [2] top-level scope
   @ REPL[18]:1

This is due to the order in which the Julia Interpreter works. If we want to evaluate firstly the variable, and then the expression, it is as easy as:

julia> @eval example.$v
1.0

So the complete function would be as follows:

julia> function modify_struct(mystruct::Example, fieldname::Symbol)
           @eval $mystruct.$fieldname += 10
       end

Upvotes: 1

Related Questions