Search code examples
juliastructure

Change one parameter value in structure does not affect related parameters


I have a mutable structure in Julia

@with_kw mutable struct Param
x::Float64 = 0.1
y::Float64 = 1/x
end

Now I want to change x to 0.2, so I set para = Param() and para.x = 0.2. However, para.y does not change. But what I want is to change y automatically, is there any way in Julia to do this?


Solution

  • For now, Julia isn't so flexible in updating attributes based on other ones. But, gladfully, it's possible to simulate the expected behavior. For this, you need to define a custom getproperty function. Suppose I have defined a mutable composite type as follows:

    julia> Base.@kwdef mutable struct Param
               x::Float64=0.1
           end
    Param
    

    Now I want to settle the situation to simulate the expected behavior. For this, I go for defining a custom getproperty function specifically for Param:

    julia> function Base.getproperty(the_type::Param, prop::Symbol)
               if prop == :y
                   return 1/the_type.x
               end
               return getfield(the_type, prop)
           end
    

    Now I create an instance of type Param holding the default value:

    julia> instance = Param()
    Param(0.1)
    

    The output shows just the value of one field (x). But meanwhile, we can have the y property as we defined our custom getproperty function recently:

    julia> instance.y
    10.0
    

    Now let's update the x field and observe if the y field gets updated automatically or not:

    julia> instance.x = 0.2
    0.2
    
    julia> instance.y
    5.0
    

    Yes, it does!


    Further setting

    But still, I can't utilize the autocomplete ability of the REPL by hitting the Tab key to write instance.y. For this, I can define a custom propertynames function specifically for my composite type Param:

    julia> Base.propertynames(the_type::Param) = (:x, :y)
    
    julia> instance. #Hit Tab
    x  y
    

    Now I can benefit from the autocomplete option in the REPL for y as well.