Skip to content

Commit 0b9c8eb

Browse files
Merge pull request #425 from jlchan/jc/VoA_StructArray_setindex
Specialize `setindex!` for `VectorOfArray{StructArray}`
2 parents 451c79d + 107fe3c commit 0b9c8eb

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

ext/RecursiveArrayToolsStructArraysExt.jl

+22-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,25 @@ module RecursiveArrayToolsStructArraysExt
33
import RecursiveArrayTools, StructArrays
44
RecursiveArrayTools.rewrap(::StructArrays.StructArray, u) = StructArrays.StructArray(u)
55

6-
end
6+
using RecursiveArrayTools: VectorOfArray
7+
using StructArrays: StructArray
8+
9+
const VectorOfStructArray{T, N} = VectorOfArray{T, N, <:StructArray}
10+
11+
# Since `StructArray` lazily materializes struct entries, the general `setindex!(x, val, I)`
12+
# operation `VA.u[I[end]][Base.front(I)...]` will only update a lazily materialized struct
13+
# entry of `u`, but will not actually mutate `x::StructArray`. See the StructArray documentation
14+
# for more details:
15+
#
16+
# https://juliaarrays.github.io/StructArrays.jl/stable/counterintuitive/#Modifying-a-field-of-a-struct-element
17+
#
18+
# To avoid this, we can materialize a struct entry, modify it, and then use `setindex!`
19+
# with the modified struct entry.
20+
function Base.setindex!(VA::VectorOfStructArray{T, N}, v,
21+
I::Int...) where {T, N}
22+
u_I = VA.u[I[end]]
23+
u_I[Base.front(I)...] = v
24+
return VA.u[I[end]] = u_I
25+
end
26+
27+
end

test/basic_indexing.jl

+9
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,12 @@ num_allocs = @allocations foo!(u_matrix)
262262

263263
# issue 354
264264
@test VectorOfArray(ones(1))[:] == ones(1)
265+
266+
# check VectorOfArray indexing for a StructArray of mutable structs
267+
using StructArrays
268+
using StaticArrays: MVector
269+
x = VectorOfArray(StructArray{MVector{1, Float64}}(ntuple(_ -> [1.0, 2.0], 1)))
270+
271+
# check VectorOfArray assignment
272+
x[1, 1] = 10
273+
@test x[1, 1] == 10

0 commit comments

Comments
 (0)