diff --git a/Project.toml b/Project.toml index 79640a4a..747a7ff3 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ComponentArrays" uuid = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" authors = ["Jonnie Diegelman <47193959+jonniedie@users.noreply.github.com>"] -version = "0.13.14" +version = "0.13.15" [deps] ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" diff --git a/src/componentarray.jl b/src/componentarray.jl index 975f3e8e..6469c6ec 100644 --- a/src/componentarray.jl +++ b/src/componentarray.jl @@ -132,6 +132,10 @@ const AbstractComponentMatrix = Union{ComponentMatrix, AdjOrTransComponentMatrix ## Constructor helpers +allocate_numeric_container(x) = allocate_numeric_container(recursive_eltype(x)) +allocate_numeric_container(::Type{T}) where {T<:Number} = T[] +allocate_numeric_container(::Type) = [] + # For making ComponentArrays from named tuples make_carray_args(::NamedTuple{(), Tuple{}}) = (Any[], FlatAxis()) make_carray_args(::Type{T}, ::NamedTuple{(), Tuple{}}) where {T} = (T[], FlatAxis()) @@ -142,8 +146,7 @@ function make_carray_args(nt) end make_carray_args(::Type{T}, nt) where {T} = make_carray_args(Vector{T}, nt) function make_carray_args(A::Type{<:AbstractArray}, nt) - T = recursive_eltype(nt) - init = isbitstype(T) ? T[] : [] + init = allocate_numeric_container(nt) data, idx = make_idx(init, nt, 0) return (A(data), Axis(idx)) end @@ -153,8 +156,8 @@ function make_idx(data, nt::Union{NamedTuple, AbstractDict}, last_val) len = recursive_length(nt) kvs = [] lv = 0 - for (k,v) in zip(keys(nt), values(nt)) - (_,val) = make_idx(data, v, lv) + for (k, v) in pairs(nt) + (_, val) = make_idx(data, v, lv) push!(kvs, k => val) lv = val end @@ -170,14 +173,14 @@ make_idx(data, x, last_val) = ( ViewAxis(last_index(last_val) + 1) ) make_idx(data, x::ComponentVector, last_val) = ( - pushcat!(data, x), + append!(data, x), ViewAxis( last_index(last_val) .+ (1:length(x)), getaxes(x)[1] ) ) function make_idx(data, x::AbstractArray, last_val) - pushcat!(data, x) + append!(data, x) out = last_index(last_val) .+ (1:length(x)) return (data, ViewAxis(out, ShapedAxis(size(x)))) end @@ -186,7 +189,7 @@ function make_idx(data, x::A, last_val) where {A<:AbstractArray{<:Union{NamedTup if eltype(x) |> isconcretetype out = () for elem in x - (_,out) = make_idx(data, elem, last_val) + _, out = make_idx(data, elem, last_val) end return ( data, @@ -222,8 +225,6 @@ function _update_field(x, pair) return x_copy end -pushcat!(a, b) = reduce((x1,x2) -> push!(x1,x2), b; init=a) - # Reshape ComponentArrays with ShapedAxis axes maybe_reshape(data, ::NotShapedOrPartitionedAxis...) = data function maybe_reshape(data, axs::AbstractAxis...) diff --git a/src/utils.jl b/src/utils.jl index 2926ee5e..7a600005 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -39,14 +39,14 @@ filter_by_type(::Type{T}, part::Tuple, ax::T, args...) where T = filter_by_type( # Flat length of an arbitrarily nested named tuple recursive_length(x) = length(x) recursive_length(a::AbstractArray{T,N}) where {T<:Number,N} = length(a) -recursive_length(a::AbstractArray) = recursive_length.(a) |> sum -recursive_length(nt::NamedTuple) = values(nt) .|> recursive_length |> sum +recursive_length(a::AbstractArray) = mapreduce(recursive_length, +, a; init=0) +recursive_length(nt::NamedTuple) = mapreduce(recursive_length, +, values(nt); init=0) recursive_length(::Union{Nothing, Missing}) = 1 recursive_length(nt::NamedTuple{(), Tuple{}}) = 0 # Find the highest element type recursive_eltype(nt::NamedTuple) = isempty(nt) ? Base.Bottom : mapreduce(recursive_eltype, promote_type, nt) -recursive_eltype(x::Vector{Any}) = isempty(x) ? Base.Bottom : mapreduce(recursive_eltype, promote_type, x) +recursive_eltype(x::AbstractArray{<:Any}) = isempty(x) ? Base.Bottom : mapreduce(recursive_eltype, promote_type, x) recursive_eltype(x::Dict) = isempty(x) ? Base.Bottom : mapreduce(recursive_eltype, promote_type, values(x)) recursive_eltype(::AbstractArray{T,N}) where {T<:Number, N} = T recursive_eltype(x) = typeof(x) diff --git a/test/runtests.jl b/test/runtests.jl index 22d43f2a..1df2784b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -132,7 +132,10 @@ end @test ComponentArray(a = Any[one(Int32)], b=T[]) == ComponentVector{T}(a = [one(T)], b = T[]) end @test ComponentArray(NamedTuple()) == ComponentVector{Any}() - @test_broken ComponentArray(a=[]) + @test ComponentArray(a=[]).a == [] + + # Make sure type promotion works correctly with StaticArrays of NamedTuples + @test ComponentVector(a=SA[(a=2, b=true)], b=false) isa ComponentVector{Int} end @testset "Attributes" begin