Specialize to vector with specified dimension

In my move to Julia one thing that I go back and forth is on the type annotation of function parameters. One particular case is when a function can accept vectors of any type of numbers, but those vectors must be of a specific dimension. A simple example would be a function that computes the distance between points in three-dimensions:*

function dist(x,y)
   d = zero(eltype(x))
   for i in 1:3
      d += (x[i]-y[i])^2
   end
   sqrt(d)
end

*Of course, in this case, one can write easily the function that does the same for every dimension. But this is not the point, because in my codes I am only dealing with points in 3D space and thus I am referring to every function of my codes, some for which that is simple, some for which that would be cumbersome.

So, my question is: What is the best practice for the type annotation of parameters? Leave it blank (as it is there)?

State at least that they should be vectors:

dist(x::AbstractVector,y::AbstractVector}

Abstract vectors of a given type? AbstractVector{Float64}, although that would limit the function somehow (the fact that AbstractVector{Real} does not work is somewhat unintuitive - I understand why is that, but it is unintuitive noneless; edit: should be AbstractVector{T} where T<:Real to work, wright?).

And, finally, it seems there is no way to declare, at least, that it must be an abstract vector of dimension 3, is it (except if specialized to static arrays, for instance). One thing I already used is

dist(x :: T, y :: T) where T <: MyVectorType

where MyVectorType is a constant global inside my package which defines the type of data I am using (SVector{3,Float64}, for example). But than I took it back to most clean forms.

More generally it could be

dist(x :: AbstractVector{T1},y :: AbstractVector{T1}) where {T1, T2 <: Real}

but seems too bloated… and still does not define the length of the vectors, which is themost important.

What are the recommendations here?

common patter is to define short-hand for (union of) type(s) you use a lot:

const AV = AbstractArray

function dist(x::AV{<:Real}, y::AV{<:Real})
2 Likes

To define the length in the type, take a look at StaticArrays.jl

4 Likes

I did both things. I am still using static arrays in general. My doubts are on the function type annotations, and when they help or become just bloat.

The short hand types I took back after a while, because I felt that the code was less clear at a function level.

@oxinabox wrote an opinionated piece on this which you might find useful: https://www.oxinabox.net/2020/04/19/Julia-Antipatterns.html (check the part on Over-constraining argument types)

6 Likes