Access StaticArray fields in a StructArray

StaticArrays defines properties x, y, z on SVector{3}:

using StaticArrays

v = SA[1,2,3]
v.x # returns 1

However these accessors don’t work on StructArrays:

using StructArrays

A = StructArray([v, 2v])
A.x # gives ERROR: type Tuple has no field x

I thought this was because propertynames(v) returns (:data,) so I defined

Base.propertynames(x::SVector{3}) = (:x, :y, :z)

but I still get the same error with A.x. How can I get this to work, and can we get this to work by default?

It requires special handling, by default StructArrays accesses fields and not properties. See my PR to add this feature – support named properties in StructArray{SVector} by aplavin · Pull Request #277 · JuliaArrays/StructArrays.jl · GitHub. Created last June, and unfortunately got no response from StructArrays devs at all.

1 Like

If you are willing to define methods on types you do not own, you could just define Base.getproperty for Vector{<: SVector}.

julia> function Base.getproperty(v::Vector{<: SVector{3}}, s::Symbol)
           hasproperty(first(v), s) ?
               getproperty.(v, s) :
               getproperty(v, s)
       end

julia> A = [v, 2v]
2-element Vector{SVector{3, Int64}}:
 [1, 2, 3]
 [2, 4, 6]

julia> A.x
2-element Vector{Int64}:
 1
 2

julia> A.y
2-element Vector{Int64}:
 2
 4

julia> A.z
2-element Vector{Int64}:
 3
 6

Thanks but I’m trying to understand how to make it work with StructArrays…

@aplavin I wonder why it doesn’t use properties… But even with fields, the following should work no?

Base.fieldnames(::Type{<:SVector{3}}) = (:x, :y, :z)

v = SA[1,2,3]
fieldnames(typeof(v)  # returns (:x, :y, :z) as expected

but I still get the same error.

It would be great to have your PR merged but I wonder if there’s not a larger fix to make here. It seems to me that this should “just work” using properties (or maybe fields) for any type that is unwrapped by StructArray.

A major point of StructArrays is efficiency – there, accessing a column like arr.x is free. This is difficult to achieve with arr::Vector.
But should be possible with stuff like view and reinterpret, would be a nice excercise btw!

It’s impossible (?) to do generically. How would a StructArray look like, if its elements have computed properties? Even for StructArray{SVector} – there are both data and x, y, z properties that refer to the same data.

Currently, StructArray stores each field of its content separately: all a fields go to one array, all b fields go to another, etc. With fields, it’s unambiguous.

Whew, I can imagine this definition breaking some fundamental assumptions in Julia… (:
Changing fieldnames this way doesn’t change the fact that the only actual field of an SVector is data.

1 Like

That was just a test to try and understand how StructArrays works, I’m not saying that StaticArrays should overload fieldnames :). But I do wonder why the overload makes no difference… maybe because static arrays are special cased?

I see that now. We don’t want the redundancy of storing the properties in addition to the fields, and we cannot in general reconstruct the fields from the properties.