Skip to content

Commit 3fe67c7

Browse files
pieveraplavin
andauthored
Support similar with nonconcrete types (#237)
* support similar() with non-concrete types * unify map_params implementation * update tests * extra unit tests * slight test tweak * streamline tests Co-authored-by: Alexander <[email protected]> Co-authored-by: Alexander Plavin <[email protected]>
1 parent b398788 commit 3fe67c7

File tree

3 files changed

+59
-16
lines changed

3 files changed

+59
-16
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "StructArrays"
22
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
3-
version = "0.6.10"
3+
version = "0.6.11"
44

55
[deps]
66
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"

src/utils.jl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,19 @@ julia> StructArrays.map_params(T -> Complex{T}, Tuple{Int32,Float64})
1818
(Complex{Int32}, Complex{Float64})
1919
```
2020
"""
21-
map_params(f::F, ::Type{NamedTuple{names, types}}) where {F, names, types} =
22-
NamedTuple{names}(map_params(f, types))
21+
map_params(f::F, ::Type{T}) where {F, T<:Tup} = strip_params(T)(map_params_as_tuple(f, T))
2322

24-
function map_params(f::F, ::Type{T}) where {F, T<:Tuple}
23+
function map_params_as_tuple(f::F, ::Type{T}) where {F, T<:Tup}
2524
if @generated
2625
types = fieldtypes(T)
2726
args = map(t -> :(f($t)), types)
2827
Expr(:tuple, args...)
2928
else
30-
map_params_fallback(f, T)
29+
map_params_as_tuple_fallback(f, T)
3130
end
3231
end
3332

34-
map_params_fallback(f, ::Type{T}) where {T<:Tuple} = map(f, fieldtypes(T))
33+
map_params_as_tuple_fallback(f, ::Type{T}) where {T<:Tup} = map(f, fieldtypes(T))
3534

3635
buildfromschema(initializer::F, ::Type{T}) where {F, T} = buildfromschema(initializer, T, staticschema(T))
3736

test/runtests.jl

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,22 @@ end
331331
@test size(s) == (3, 5)
332332
@test s isa StructArray
333333

334+
for ET in (
335+
NamedTuple{(:x,)},
336+
NamedTuple{(:x,), Tuple{NamedTuple{(:y,)}}},
337+
NamedTuple{(:x, :y), Tuple{Int, S}} where S
338+
)
339+
s = similar(t, ET, (3, 5))
340+
@test eltype(s) === ET
341+
@test size(s) == (3, 5)
342+
@test s isa StructArray
343+
end
344+
345+
s = similar(t, Any, (3, 5))
346+
@test eltype(s) == Any
347+
@test size(s) == (3, 5)
348+
@test s isa Array
349+
334350
s = similar(t, (0:2, 5))
335351
@test eltype(s) == NamedTuple{(:a, :b), Tuple{Float64, Bool}}
336352
@test axes(s) == (0:2, 1:5)
@@ -413,6 +429,10 @@ end
413429
@test size(t) == (5,)
414430
@test t == convert(StructVector, v)
415431
@test t == convert(StructVector, t)
432+
433+
t = StructVector([(a=1,), (a=missing,)])::StructVector
434+
@test isequal(t.a, [1, missing])
435+
@test eltype(t) <: NamedTuple{(:a,)}
416436
end
417437

418438
@testset "tuple case" begin
@@ -1118,6 +1138,12 @@ end
11181138
@test t isa Vector
11191139
@test t == [1, 2, 3]
11201140

1141+
t = map(x -> (a=x.a,), StructVector(a=[1, missing]))::StructVector
1142+
@test isequal(t.a, [1, missing])
1143+
@test eltype(t) <: NamedTuple{(:a,)}
1144+
t = map(x -> (a=rand(["", 1, nothing]),), StructVector(a=1:10))::StructVector
1145+
@test eltype(t) <: NamedTuple{(:a,)}
1146+
11211147
t = VERSION >= v"1.7" ? @inferred(map(x -> (a=x.a, b=2), s)) : map(x -> (a=x.a, b=2), s)
11221148
@test t isa StructArray
11231149
@test map(x -> (a=x.a, b=2), s) == [(a=1, b=2), (a=2, b=2), (a=3, b=2)]
@@ -1182,19 +1208,37 @@ end
11821208
@testset "map_params" begin
11831209
v = StructArray(rand(ComplexF64, 2, 2))
11841210
f(T) = similar(v, T)
1211+
11851212
types = Tuple{Int, Float64, ComplexF32, String}
1186-
A = @inferred StructArrays.map_params(f, types)
1187-
B = StructArrays.map_params_fallback(f, types)
1188-
@test typeof(A) === typeof(B)
1213+
namedtypes = NamedTuple{(:a, :b, :c, :d), types}
1214+
A = @inferred StructArrays.map_params_as_tuple(f, types)
1215+
B = StructArrays.map_params_as_tuple_fallback(f, types)
1216+
C = @inferred StructArrays.map_params_as_tuple(f, namedtypes)
1217+
D = StructArrays.map_params_as_tuple_fallback(f, namedtypes)
1218+
@test typeof(A) === typeof(B) === typeof(C) === typeof(D)
1219+
11891220
types = Tuple{Int, Float64, ComplexF32}
1190-
A = @inferred StructArrays.map_params(zero, types)
1191-
B = StructArrays.map_params_fallback(zero, types)
1192-
C = map(zero, fieldtypes(types))
1193-
@test A === B === C
1221+
A = map(zero, fieldtypes(types))
1222+
B = @inferred StructArrays.map_params(zero, types)
1223+
C = StructArrays.map_params_as_tuple(zero, types)
1224+
D = StructArrays.map_params_as_tuple_fallback(zero, types)
1225+
@test A === B === C === D
1226+
11941227
namedtypes = NamedTuple{(:a, :b, :c), types}
1195-
A = @inferred StructArrays.map_params(zero, namedtypes)
1196-
C = map(zero, NamedTuple{(:a, :b, :c)}(map(zero, fieldtypes(types))))
1197-
@test A === C
1228+
A = map(zero, NamedTuple{(:a, :b, :c)}(map(zero, fieldtypes(types))))
1229+
B = @inferred StructArrays.map_params(zero, namedtypes)
1230+
C = StructArrays.map_params_as_tuple(zero, types)
1231+
D = StructArrays.map_params_as_tuple_fallback(zero, types)
1232+
@test A === B
1233+
@test Tuple(A) === C === D
1234+
1235+
nonconcretenamedtypes = NamedTuple{(:a, :b, :c)}
1236+
A = map(f, NamedTuple{(:a, :b, :c)}((Any, Any, Any)))
1237+
B = @inferred StructArrays.map_params(f, nonconcretenamedtypes)
1238+
C = StructArrays.map_params_as_tuple(f, nonconcretenamedtypes)
1239+
D = StructArrays.map_params_as_tuple_fallback(f, nonconcretenamedtypes)
1240+
@test typeof(A) === typeof(B)
1241+
@test typeof(Tuple(A)) === typeof(C) === typeof(D)
11981242
end
11991243

12001244
@testset "OffsetArray zero" begin

0 commit comments

Comments
 (0)