🎓 A1Learner
🔍
0 of 48 lessons completed

Julia Abstract Containers

An abstract container is a list whose item type is left open, such as Vector{Any}. It can hold any kind of item, but that freedom costs extra work.

The two lists report different item types

eltype reports the item type of each list. The open list reports Any, and the other reports Int64.

va = Any[1, 2, 3]
vi = [1, 2, 3]
println(eltype(va))
println(eltype(vi))

Doubling the open list allocates more

doubled is warmed up for each list. The open list allocates 112 bytes, and the whole-number list allocates 80 bytes.

function doubled(a)
    return [x * 2 for x in a]
end
va = Any[1, 2, 3]
vi = [1, 2, 3]
doubled(va)
doubled(vi)
println(@allocated doubled(va))
println(@allocated doubled(vi))

Adding to a decimal total also allocates more

total_plus is warmed up for each list. The open list allocates 48 bytes, and the whole-number list allocates 16 bytes.

function total_plus(a)
    total = 0.0
    for x in a
        total += x
    end
    return total
end
va = Any[1, 2, 3]
vi = [1, 2, 3]
total_plus(va)
total_plus(vi)
println(@allocated total_plus(va))
println(@allocated total_plus(vi))

Example

function doubled(a)
    return [x * 2 for x in a]
end
va = Any[1, 2, 3]
vi = [1, 2, 3]
doubled(va)
doubled(vi)
println(doubled(vi))
println(@allocated doubled(va))
println(@allocated doubled(vi))

Key points

  • Vector{Int}: a Vector{Int} holds whole numbers only.
  • Vector{Any}: a Vector{Any} holds items of any kind.
  • Element type: eltype reports the item type of a list.
  • Open container cost: an open container can make a matching operation allocate more memory.
  • Use Vector{Int} to hold whole numbers when every item is a whole number.

In this example, doubled is warmed up for both lists, the doubled whole-number list prints first, and the two counts show the open list allocating more.

Note

Any is the most open type, so Vector{Any} accepts every value.

Try it Yourself

Edit the code, then press Run.

Running is simulated · JuliaHub

Exercise

Why does code over Vector{Any} sometimes allocate more than code over Vector{Int}?