Parametric Field Names

Personally I’am not a huge friend of storing redundant data, and you can avoid any illegal instance by just storing the essential information once. Found this originally here and meanwhile using this quite extensively:

mutable struct Square
    side
end

# Acutally not strictly needed just for completeness
# see https://docs.julialang.org/en/v1/base/base/#Base.propertynames   
propertynames(p::Square,private=true) = begin
    fields = fieldnames(typeof(p))    
    (fields...,:area,:diagonal)
end

#Dispatch the gets
Base.getproperty(p::Square,n::Symbol) = getproperty(p::Square,Val{n}())
Base.getproperty(p::Square,::Val{S}) where {S} = getfield(p,S)  #generic fallback
Base.getproperty(p::Square,::Val{:area}) = p.side^2
Base.getproperty(p::Square,::Val{:diagonal}) = √2*p.side

#Dispatch the sets
Base.setproperty!(p::Square,n::Symbol,x) = setproperty!(p,Val{n}(),x)
Base.setproperty!(p::Square,::Val{S},x) where {S} = setfield!(p,S,x)     #generic fallback
Base.setproperty!(p::Square, ::Val{:area},x) = setfield!(p,:side,√x)
Base.setproperty!(p::Square, ::Val{:diagonal},x) = setfield!(p,:side,x/√2)



julia> s = Square(√2)
Square(1.4142135623730951)

julia> s = Square(√2)^C

julia> s.diagonal
2.0000000000000004

julia> s.area=4
4

julia> s.diagonal
2.8284271247461903

julia> 

It is also easier to maintain this way and you can easily add up more implicit properties without stressing your memory too much.

2 Likes