Initialize AbstractArray?

Is there a way to initialize an array that is a subtype of AbstractArray?
For example, x = [] initializes Vectors, but how can I initialize an object that can be any arbitrary subtype of AbstractArray? is it possible?

Can you give a specific example of what you want to achieve?

I don’t see an interface method here which would allow to do so.

Not sure if I fully understand the question but from the manual section on Abstract Types:

Abstract types cannot be instantiated, and serve only as nodes in the type graph, thereby describing sets of related concrete types: those concrete types which are their descendants.

this combined with

julia> isabstracttype(AbstractArray)
true

makes me think the answer to your question is no, but I might have misunderstood it.

2 Likes

Yes, I understand I cannot instantiate an abstract type. This is what I am trying to do:

function f(x::T) where T <: AbstractArray
    t = typeof(x)
    x0 = t[] # this is meant to be an empty array of type T above
    # some code
    return x0
end

Okay, but doesn’t the function you posted already do what you want then? A shorter version of your function is just:

julia> function f(x::T) where T <: AbstractArray
           T[]
       end
f (generic function with 1 method)

julia> f(rand(2))
Vector{Float64}[]

julia> f(rand(Int, 2))
Vector{Int64}[]

julia> f(5.0)
ERROR: MethodError: no method matching f(::Float64)
Closest candidates are:
  f(::T) where T<:AbstractArray at REPL[43]:1
Stacktrace:
 [1] top-level scope
   @ REPL[46]:100: 

I think T[] creates parametric versions of regular Arrays, not other subtypes of AbstractArray.

It seems like I’m still misunderstanding what you are trying to do. Can you show an example where the function I posted doesn’t do what you need it to do?

This may be a silly example but it illustrates what I am trying to do (and failing):

julia> using LinearAlgebra

julia> function f(x::T) where T <: AbstractArray
       T[]
       end
f (generic function with 1 method)

julia> x = rand(2, 2)
2Ă—2 Matrix{Float64}:
 0.791934  0.93072
 0.450938  0.813264

julia> xt = transpose(x)
2Ă—2 transpose(::Matrix{Float64}) with eltype Float64:
 0.791934  0.450938
 0.93072   0.813264

julia> xt |> typeof
Transpose{Float64, Matrix{Float64}}

julia> xt isa Transpose
true

julia> xt isa AbstractArray
true

julia> f(xt)
Transpose{Float64, Matrix{Float64}}[]

julia> f(xt) |> typeof
Vector{Transpose{Float64, Matrix{Float64}}} (alias for Array{Transpose{Float64, Array{Float64, 2}}, 1})

julia> f(xt) isa AbstractArray
true

julia> f(xt) isa Transpose
false

julia> f(xt) isa Array
true

T[] creates regular arrays whose elements are of type T, rather than an empty “container” of type T. This is the same behavior that creates an array with elements that are floats from Float64[].

I feel like you might be asking for the array to be of the type T, but this code is actually making a new array that contains the type T. Which one is the intended one?

For example UnitRange is a subtype of AbstractArray, but I don’t think initializing one empty makes much sense so I’m not sure this is a good idea in general (in case you asked for the array to be of type T).

EDIT:
Didn’t see you clarification until after I posted, but it seems like you meant the case I brought up. My feeling is there is no general method to create a meaningful empty collection of the type, though I’m not entirely sure.

1 Like

Yes, that is what I want. I am trying to figure out a way for the ParticleSwarm algorithm of Optim to accept ComponentArrays. Line 36 of this
https://github.com/JuliaNLSolvers/Optim.jl/blob/master/src/multivariate/solvers/zeroth_order/particle_swarm.jl#L36
initializes the limits with empty “regular” arrays, I was thinking whether there was a way to generalize that to be empty arrays (read containers) of any given subtype of AbstractArray.

It is not intrinstically true that all AbstractArrays can have empty instances of them created.

but you might be after similar?

2 Likes

I guess it can’t be done then :frowning:

The problem with similar is that it populates the containers.

At least you can give a dims argument to similar. But I understood you are interested in initializing the new array somehow arbitrarily?

1 Like

So am I correct in that you have some ComponentArrays that you want to send as the lower and upper parameters to ParticleSwarm?

Depending on exactly what the goal is it could maybe be done like ParticleSwarm(; lower=collect(lower_component), upper=collect(upper_component)). This converts the ComponentArrays to arrays before sending them.

If you need to send ComponentArrays for some reason I don’t think that is possible since ParticleSwarm is specifically typed to store a vectore here:
https://github.com/JuliaNLSolvers/Optim.jl/blob/master/src/multivariate/solvers/zeroth_order/particle_swarm.jl#L2

1 Like

you can pass in the dims argument to make it of length 0.

2 Likes