Implement AbstractArray so that custom type is returned

I’d like to implement a 3-D vector type like the following:

struct Vector3D
    x::Int
    y::Int
    z::Int
end

Julia has a rich collection of Array operations already defined that I’d love to take advantage of, so I’ll make my Vector a subtype of AbstractVector{Int}

struct Vector3D <: AbstractVector{Int}
    x::Int
    y::Int
    z::Int
end

Base.size(::Vector3D) = (3,)
Base.getindex(v::Vector3D, i::Integer) = i == 1 ? v.x : i == 2 ? v.y : v.z

But when I perform the following operation, an Array type is returned rather than my Vector3D type.

julia> typeof(Vector3D(1, 2, 3) .+ 4)
Array{Int64,1}

What do I need to do so that Vector3D(1, 2, 3) .+ 4 returns a Vector3D type instead?

You need to implement the broadcast interface for Vector3D. I always find that interface to be a bit of a pain, and the most reliable way is to start with the ArrayAndChar example and modify it one step at a time.

Good luck!

3 Likes

Unless you are doing this for your own education you should check out StaticArrays.jl, where all of this is already implemented.

6 Likes

To expand on the StaticArrays suggestion, here is an example:

julia> using StaticArrays

julia> struct Vector3D <: FieldVector{3,Int}
       x :: Int
       y :: Int
       z :: Int
       end

julia> Vector3D(1,2,3)
3-element Vector3D with indices SOneTo(3):
 1
 2
 3

julia> Vector3D(1,2,3) .+ 1
3-element Vector3D with indices SOneTo(3):
 2
 3
 4
3 Likes