I have a data type that stores a vector z
and a list of views to that vector, whose index ranges can be specified by the user, here a
and b
. The views are also accessible via m.a
and m.b
by overloading getproperty
.
Depending on how and where I create those views getproperty
is type stable or not. Please see the following MWE:
import Base.hasproperty, Base.getproperty
struct MyStruct{T, ZT <: AbstractVector{T}, VT <: NamedTuple}
z::ZT
v::VT
# function MyStruct(z::ZT, vars) where {ZT}
# # this is type-stable
# v = ( a = view(z, 1:2), b = view(z, 3) )
# # this is not type-stable
# # v = NamedTuple{keys(vars)}(( view(z, idx_range) for idx_range in vars ))
# new{eltype(z), ZT, typeof(v)}(z, v)
# end
end
function MyStruct(z::ZT, vars) where {ZT}
# this is type-stable
# v = ( a = view(z, 1:2), b = view(z, 3) )
# this is also type-stable
v = NamedTuple{keys(vars)}(( view(z, idx_range) for idx_range in vars ))
MyStruct{eltype(z), ZT, typeof(v)}(z, v)
end
function Base.getproperty(x::MyStruct{T, ZT, VT}, s::Symbol) where {T, ZT, VT}
if hasfield(VT, s)
return getfield(x, :v)[s]
else
return getfield(x, s)
end
end
function test()
m = MyStruct(rand(3), ( a = 1:2, b = 3 ))
@time m.z
@time m.a
@time m.b
end
test();
If I have an inner constructor, creating the views statically leads to a type-stable getproperty
, but creating them dynamically leads to an unstable getproperty
. If I have an outer constructor, both lead to a type-stable getproperty
.
I do not quite understand this behaviour. The type parameter VT
of MyStruct
has the same value in all examples.
I tested this with Julia v1.7.2 and 1.8.0-beta3 on macOS (M1).