Type changes based on declaration

Why aren’t F and V below of the same type? How can I write a function that will handle both of them (but not also any generic vector)?

using SparseArrays

F = Vector{SparseVector}()
push!(F, sparse([1, -1, 5, -5]))
push!(F, sparse([4, -4, -3, 3]))
push!(F, sparse([3, -3, 1, -4]))
push!(F, sparse([8, -8, 1, -1]))

V = [
    sparse([1, -1, 5, -5]),
    sparse([4, -4, -3, 3]),
    sparse([3, -3, 1, -4]),
    sparse([8, -8, 1, -1])
]

typeof(F) # Vector{SparseVector}
typeof(V) # Vector{SparseVector{Int64, Int64}}

So, for example, this function

function foo(V::Vector{SparseVector})
    println("My function 'tis of thee.")
end

only works on F, and this function

function foo(V::Vector{SparseVector{Int,Int}})
    println("Sweet Int of Int I see.")
end

only works on V. I’d like to write a function that will work on both.

function foo(V::Vector{<:SparseVector})
    println("My function 'tis of thee.")
end

It’s called “invariance”, have a search through the manual to find out what it is.

2 Likes

Ah! I was so close… I tried

function foo(v<:Vector{SparseVector})

and

function foo(v::T) where T<:Vector{SparseVector}

but now I see why those were wrong. THANKS!

2 Likes

Not sure if this maters anymore, but when you declared F you made if type Vector{SparseVector}() but when you declared V you let Julia figure out the type, so it was able to identify the types in the SparseVector object.

So for F you could have done:

F = Vector{SparseVector{Int64, Int64}}()

And both would be the same…

1 Like

Thanks! I figured it was something like that, but when I was playing around with Vector{SparseVector{Any,Int}} and things like that,

Vector{SparseVector{Int,Int}} <: Vector{SparseVector}
Vector{SparseVector{Int,Int}} <: Vector{SparseVector{Any,Int}}

are both false, and I couldn’t quite figure out how to make it work. The placement of <: is what I needed.