Hi!
I have this structure:
struct Workspace{T}
x::Vector{T}
s_i::Vector{T}
s_b::Vector{T}
end
I would like to overload getproperty
and getindex
so that s.JD
is x[1]
and s.w
is view(x,2:4)
. Following the same approach as LabelledArrays, I did the following:
mutable struct Workspace{T}
x::Vector{T}
s_i::Vector{T}
s_b::Vector{T}
end
# Functions to translate the state-vector into variables.
function Base.getproperty(a::Workspace, f::Symbol)
if (f β [:JD, :w])
return getindex(a, Val(f))
else
return getfield(a,f)
end
end
function Base.getindex(a::Workspace, s::Val)
return __getindex(a,s)
end
function __getindex(a::Workspace, ::Val{:JD})
return a.x[1]
end
function __getindex(a::Workspace, ::Val{:w})
return view(a.x, 2:4)
end
This works fine and I can access those virtual fields without type-instabilities:
julia> w = Workspace(zeros(10), zeros(3), zeros(3))
Workspace{Float64}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0])
julia> function test(w)
w.JD
end
test (generic function with 1 method)
julia> @code_warntype test(w)
Variables
#self#::Core.Compiler.Const(test, false)
w::Workspace{Float64}
Body::Float64
1 β %1 = Base.getproperty(w, :JD)::Float64
βββ return %1
However, if a have another type of variable, like a Bool
, then the same code has a type instability:
mutable struct Workspace{T}
x::Vector{T}
eclipse::Bool
s_i::Vector{T}
s_b::Vector{T}
end
# Functions to translate the state-vector into variables.
function Base.getproperty(a::Workspace, f::Symbol)
if (f β [:JD, :w])
return getindex(a, Val(f))
else
return getfield(a,f)
end
end
function Base.getindex(a::Workspace, s::Val)
return __getindex(a,s)
end
function __getindex(a::Workspace, ::Val{:JD})
return a.x[1]
end
function __getindex(a::Workspace, ::Val{:w})
return view(a.x, 2:4)
end
julia> w = Workspace(zeros(10), false, zeros(3), zeros(3))
Workspace{Float64}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], false, [0.0, 0.0, 0.0], [0.0, 0.0, 0.0])
julia> function test(w)
w.JD
end
test (generic function with 1 method)
julia> @code_warntype test(w)
Variables
#self#::Core.Compiler.Const(test, false)
w::Workspace{Float64}
Body::Any
1 β %1 = Base.getproperty(w, :JD)::Any
βββ return %1
Is there any way to avoid that?