# OffsetArrays methods for querying dimensions?

**URL:** https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507
**Category:** New to Julia
**Created:** [August 4, 2023, 10:27pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507 "2023-08-04T22:27:41Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)
#### Post date: [August 4, 2023, 10:27pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/1 "2023-08-04T22:27:41Z")

</div>

From some light reading, I understand that OffsetArrays ahs been a source of a lot of errors, some stemming from use of conventional Array methods like `length` and `size`.

Why is it not possible to write a package that overloads these methods to behave “intuitively” so that you can write code that is agnostic with respect to the array indices? If I understand correctly, there is not a problem when Fortran allows user-defined array indices so it must be possible.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [August 4, 2023, 10:35pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/2 "2023-08-04T22:35:17Z")

</div>

I’ve heard of methods hitting integer overflows with extremely offset indices, but never about errors with `length` and `size`. It’s not clear what errors you’re referring to or how you’d overload those methods to fix them.

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [August 4, 2023, 10:40pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/3 "2023-08-04T22:40:16Z")

</div>

The correct way to write code for generic arrays is to

1. forget `1:length(a)` and `1:size(a, k)`
2. replace them with `eachindex(a)` and `axes(a, k)`

But this list is non exhaustive: there are more things that you need to watch out for (I’m not even sure where to find a list, perhaps someone can help). That’s why many people don’t bother for their own projects. The end result is that there is plenty of code out there which

- accepts any `AbstractArray` in theory (for instance because the developer wants it to work on dense _and_ sparse arrays)
- fails in practice when given an `OffsetArray`

I think this is a decent price to pay for Julia’s composability, but some people disagree.

---

<div class="post-metadata">

### Author: ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)
#### Post date: [August 4, 2023, 10:52pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/4 "2023-08-04T22:52:28Z")

</div>

I also don’t have first-hand experience but it seems like it is/was a common problem, like said [here](https://news.ycombinator.com/item?id=31401490) and in the docs/tutorials.

---

<div class="post-metadata">

### Author: ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)
#### Post date: [August 4, 2023, 10:53pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/5 "2023-08-04T22:53:55Z")

</div>

I guess my question is why cannot `length` and `size` be overloaded with `eachindex` and `axes` when OffsetArrays are used so they behave with minimal code differences with using standard Arrays?

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [August 4, 2023, 10:56pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/6 "2023-08-04T22:56:57Z")

</div>

Because that’s not what `length` and `size` are for. If I apply `length` to a vector with indices `1:5` versus another vector with indices `0:4`, I expect the same answer 5. It’s fundamentally infeasible to index both vectors with `1:length(a)`, I’d be missing index 0 for the latter vector, no matter what `length` does.

> [@gdalle](#):
>
> I think this is a decent price to pay for Julia’s composability, but some people disagree.

There are algorithms that don’t fundamentally need `Base.require_one_based_indexing` and can be patched to accommodate offset indices, but that requires work and testing, and for a feature that isn’t as demanded as other things right now.

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [August 4, 2023, 10:58pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/7 "2023-08-04T22:58:17Z")

</div>

For OffsetArrays, `length` and `size` are correct: they return the total length and the size without offset. The only issue is that you should not use them to iterate

---

<div class="post-metadata">

### Author: ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)
#### Post date: [August 4, 2023, 11:00pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/8 "2023-08-04T23:00:23Z")

</div>

Yeah that makes sense. I guess it is idiomatic MATLAB to iterate over `1:length(a)`. In R, you would iterate over `seq_along(a)` and so it makes sense that the indices could be retrieved directly rather than generating them. I suppose that’s what `eachindex(a)` does.

---

<div class="post-metadata">

### Author: ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)
#### Post date: [August 4, 2023, 11:02pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/9 "2023-08-04T23:02:18Z")

</div>

Nowadays it is idiomatic Julia to iterate with `eachindex`, and the VSCode extension will even scream at you if you don’t. But that doesn’t mean everyone does it, and there’s tons of older code still running

---

<div class="post-metadata">

### Author: ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)
#### Post date: [August 4, 2023, 11:06pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/10 "2023-08-04T23:06:04Z")

</div>

That is good to hear. On the one hand, idiomatic Julia now makes it easier to use OffsetArrays, but you mention there are more things to watch out for:

> [@gdalle](#):
>
> But this list is non exhaustive: there are more things that you need to watch out for (I’m not even sure where to find a list, perhaps someone can help).

So using `eachindex` and `axes` doesn’t guarantee that introducing an OffsetArray will necessarily work in a function that you’ve written for a standard Array.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [August 4, 2023, 11:12pm UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/11 "2023-08-04T23:12:16Z")

</div>

> [@gdalle](#):
>
> Nowadays it is idiomatic Julia to iterate with `eachindex`

Big exception is unusual indices selections, like “start from 1/3 into the vector, end at 2/3 into the vector, aim for 10 elements”. There isn’t really a guide for using generic index methods for that so I see people stick to 1-based `Array`s and compute the indices from `1` and `length`. I’m sure there is some math for best practices but again, not much in demand.

> [@hatmatrix](#):
>
> So using `eachindex` and `axes` doesn’t guarantee that introducing an OffsetArray will necessarily work in a function that you’ve written for a standard Array.

Simple example is any function that has a matrix multiplication step. It’s feasible to match offset axes in matrices and do the usual multiplication, it’s just not implemented yet.

---

<div class="post-metadata">

### Author: ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)
#### Post date: [August 5, 2023, 10:36am UTC](https://discourse.julialang.org/t/offsetarrays-methods-for-querying-dimensions/102507/12 "2023-08-05T10:36:55Z")

</div>

> So using `eachindex` and `axes` doesn’t guarantee that introducing an OffsetArray will necessarily work in a function that you’ve written for a standard Array.

There is a guide:

[https://docs.julialang.org/en/v1/devdocs/offset-arrays/](https://docs.julialang.org/en/v1/devdocs/offset-arrays/)

I think if you follow that advice you’re pretty much set. And indeed using `eachindex` and `axes` is all you need the majority of the time.

However, it was written before we could address the question:

> Big exception is unusual indices selections, like “start from 1/3 into the vector, end at 2/3 into the vector, aim for 10 elements”

I’m not quite sure what you mean by “aim for 10 elements” or which should “win” if the start and end points are in conflict with having 10 elements, but here’s one guess at what you wanted:

```julia
ndiv3 = length(a) ÷ 3
a[begin + ndiv3 : min(end - ndiv3, 10)]

```

Aside from using `begin` rather than `1`, this is essentially identical to what this might look like if they were plain arrays.

Bottom line, we have all the tools to easily write generic-indexing code. It took a while for the word to get out to packages, but now that we have linting we’re in pretty good shape. Yuri’s post has been widely read but these things do get outdated. It’s now a bit like complaining that a lot of Python packages are still stuck between Python 2 and Python 3; it was a problem once, but has long since been fixed.
