# Implement getindex for array indexing and range indexing

**URL:** <https://discourse.julialang.org/t/implement-getindex-for-array-indexing-and-range-indexing/94369>\
**Category:** General Usage\
**Tags:** question\
**Created:** [February 9, 2023, 6:23pm UTC](https://discourse.julialang.org/t/implement-getindex-for-array-indexing-and-range-indexing/94369 "2023-02-09T18:23:25Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [February 9, 2023, 6:23pm UTC](https://discourse.julialang.org/t/implement-getindex-for-array-indexing-and-range-indexing/94369/1 "2023-02-09T18:23:25Z")

</div>

I have a struct which should behave like a matrix. I want to have all the standard indexing methods `julia` has, like `A[:, j]`, `A[1:3, j]`, `A[[1,3,4], j]` and so on.

Currently I have the following (simplified)

```julia
function Base.getindex(A::myMatrix, i::Int, j::Int)
    #Doing some stuff
    A(i, j)
end

```

Should I implement `Base.getindex(A::myMatrix, I::Vector, j::Int)` and `Base.getindex(A::myMatrix, I::Range, j::Int)` and the similar versions for `j`?  
Or is there a simple way to make the standard indexing available for a custom struct?

Thank you.

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [February 9, 2023, 7:25pm UTC](https://discourse.julialang.org/t/implement-getindex-for-array-indexing-and-range-indexing/94369/2 "2023-02-09T19:25:07Z")

</div>

[Check the section on the `AbstractArray` interface.](https://docs.julialang.org/en/v1/manual/interfaces/#man-interface-array) So long as `myMatrix <: AbstractArray` (or in your case, likely `<: AbstractMatrix`), the interface page tells you that you’ll get array/range indexing automatically. This will be implemented by looping over the scalar indexing you already defined.

If there are significant performance savings to be had from batching these multi-index accesses, you may consider implementing specialized methods for doing so. Exactly what to implement and for what input types is up to you and depends on the sort of savings you’re after.

If such batching efficiencies truly exist, I’d start with adding a `Base.getindex(A::myMatrix, i, j)` method with untyped `i` and `j` and write it generically for that. You can continue to add increasingly specialized methods from there, until you decide there’s no longer significant benefit. In very few cases will the types of `i` or `j` need to be more specialized than `AbstractVector`.

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [February 9, 2023, 8:36pm UTC](https://discourse.julialang.org/t/implement-getindex-for-array-indexing-and-range-indexing/94369/3 "2023-02-09T20:36:50Z")

</div>

Thank you! I got the following

```julia
struct myMatrix <: AbstractMatrix{Float64}
    # definitions
    m::Int
    n::Int
end
Base.size(M::myMatrix) = (M.m, M.n)
Base.getindex(M::myMatrix, i::Int, j::Int) = #some stuff

```

This seems to work. The manual mentions `Base.IndexStyle()`. What is this for? Is necessary to implement this?

---

<div class="post-metadata">

**Author:** ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)\
**Post date:** [February 9, 2023, 9:54pm UTC](https://discourse.julialang.org/t/implement-getindex-for-array-indexing-and-range-indexing/94369/4 "2023-02-09T21:54:14Z")

</div>

> [@linwaytin](#):
>
> The manual mentions `Base.IndexStyle()`. What is this for? Is necessary to implement this?

An `AbstractArray` in Julia is allowed to have one of two preferred indexing schemes: Cartesian or Linear. `IndexLinear()` is efficient when applicable and applies to normal Julia `Array` types because of the way they’re stored in memory (the memory is snaked through the columns to form the array), but `IndexCartesian()` is more general.

```julia-repl
julia> collect(CartesianIndices(zeros(2,3)))
2×3 Matrix{CartesianIndex{2}}:
 CartesianIndex(1, 1) CartesianIndex(1, 2) CartesianIndex(1, 3)
 CartesianIndex(2, 1) CartesianIndex(2, 2) CartesianIndex(2, 3)

julia> collect(LinearIndices(zeros(2,3)))
2×3 Matrix{Int64}:
 1 3 5
 2 4 6

```

As you can see, the `LinearIndices` of an array are of the form `a:b` (but snake through the columns) while the `CartesianIndices` represent each coordinate explicitly.

Julia tries to access arrays using their preferred mode (since one is usually more efficient than the other). `IndexCartesian()` arrays implement `getindex(x,coordinate1,coordinate2,coordinate3...)` while `IndexLinear()` arrays implement `getindex(x,linearindex)`. Julia will transform indexing operations to the preferred modality.

Since you wrote the method `Base.getindex(::myMatrix, ::Int, ::Int)`, it sounds like you want `Base.IndexStyle(::Type{<:myMatrix}) = IndexCartesian()`. The reason you didn’t have write this is that it’s the default.

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [February 9, 2023, 10:17pm UTC](https://discourse.julialang.org/t/implement-getindex-for-array-indexing-and-range-indexing/94369/5 "2023-02-09T22:17:38Z")

</div>

Thank you for such a detailed explanation! I learned a lot.
