I have a simple question, rather esthetic than essential: I need to use CartesianIndex as an integer vector. The code below does work with “collect+Tuple” but collect, Vector alone did not. Do you have any idea?
If you try try to execute collect(CartesianIndex(1,2,3)) the error will say that this is deliberately not supported. My guess would be that conceptually, a CartesianIndex is not really equivalent to a Vector and that supporting this operation would also make certain bugs too easy to accidentally occur.
If this is a big pain point for you, then you could write your own function to do this, e.g.:
car2vec(x::CartesianIndex) = collect(Tuple(x))
Writing your own collect method to do this would be type piracy and therefore not recommended.
To generalize, a composite data structure isn’t necessarily multiple elements semantically, let alone iterable. Complex{T} is a composite of 2 T fields, but we wouldn’t expect to collect it into Vector{T} with 2 elements; Complex is iterable so collect works, but it is 1 element like a typical Number. Of course, anything implemented with multiple elements can be processed to something that is semantically a collection; getfield.(::C, 1:fieldcount(C)) would collect the fields of a struct C, so it works on Complex.
Back to the topic at hand, there’s no cost to Tuple(::CartesianIndex) because it’s just a simple getter for the Tuple that CartesianIndex is built on: Tuple(index::CartesianIndex) = index.I.
Often, the collect in collect(Tuple(...)) is not needed for the subsequent processing:
julia> Tuple(R[10]-R[2])
(-1, 3, 0)
should be enough.
Note that a Vector can have a run-time only known size, while a Tuple has compile-time known size. In this case using a Tuple will preserve this compile-time knowledge and allow better optimization.
If methods only work for Array, then there’s no choice. Many methods work on AbstractArray though, and while Tuple won’t work, SVector from StaticArrays.jl can simply wrap it, keeping all the benefits of immutability and a small compile-time size.
I’d second the recommendation that you consider using the Tuple directly, rather than converting it to a Vector (which has a considerable performance penalty at this size).
edit: the above poster narrowly beat me to the SVector recommendation
If you need to treat the values as a mathematical vector (rather than simply an indexable collection), consider the StaticArrays.jl package’s SVector, which is specially designed for small fixed-size vectors like you’re considering here. These have virtually no performance difference from Tuple (since they basically are one) and support almost all the linear algebra that Vector does (except mutation, for which MVector exists but sometimes has somewhat less performance).
julia> using StaticArrays
julia> SVector(Tuple(CartesianIndex(4,-1,2)))
3-element SVector{3, Int64} with indices SOneTo(3):
4
-1
2