# Specifying index without access to array

**URL:** https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693
**Category:** General Usage
**Tags:** indexing
**Created:** [May 23, 2021, 8:42pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693 "2021-05-23T20:42:08Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)
#### Post date: [May 23, 2021, 8:42pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/1 "2021-05-23T20:42:08Z")

</div>

In Python, I can get the the second-to-last value of an array using a nice syntax:

```julia
>>> ix = -2
>>> lst = [10, 20, 30, 40]
>>> lst[ix]
30

```

but I can’t do this in Julia:

```julia
julia> lst = [10, 20, 30, 40];
julia> ix = end - 2
ERROR: syntax: unexpected "end"
julia> lst[ix]

```

which means I need access to the array in order to specify the index location that I want.

I can do

```julia
julia> lastbutn(n) = a-> a[end-n]
julia> lastbutn(1)(lst)
30

```

but this is awkward.

It looks like the `end-1` syntax only works inside of square brackets. Is there a way to make this easier?

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [May 23, 2021, 11:00pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/2 "2021-05-23T23:00:11Z")

</div>

`lastindex(a)-2` is the equivalent to `end-2` outside of an indexing expression.

---

<div class="post-metadata">

### Author: ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)
#### Post date: [May 23, 2021, 11:05pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/3 "2021-05-23T23:05:27Z")

</div>

You can do it without needing a reference to `a` by making a struct called `Last` or something, and defining the appropriate methods (`Base.to_indices` among others). This is how Base’s `Colon()` works as well as [InvertedIndices.jl](https://github.com/mbauman/InvertedIndices.jl)’s `Not`. I played around with this a couple of years ago to make [ModularIndices.jl](https://github.com/ericphanson/ModularIndices.jl) which provides a `Mod` struct to do wrap-around indexing:

```julia
julia> using ModularIndices

julia> A = rand(3)
3-element Array{Float64,1}:
 0.523471984061487
 0.3975791533002422
 0.3230510641200286

julia> A[Mod(4)]
0.523471984061487

julia> A[4]
ERROR: BoundsError: attempt to access 3-element Array{Float64,1} at index [4]
Stacktrace:
 [1] getindex(::Array{Float64,1}, ::Int64) at ./array.jl:729
 [2] top-level scope at none:0

```

This is not very useful because as I later learned you can do `A[mod1(4, end)]` without a package to get this kind of behavior! (Although of course that syntax is only valid within the indexing expression, so the advantage of the package is that you can do `ind = Mod(4)` without a reference to the array, same as in the question here). But anyway, you could do the same thing with a `Last` struct so that say `Last(n)` would give `v[Last(n)] == v[end - n]`.

edit: I said the methods needed were “`Base.to_indices` among others”, but after looking again at the source code of ModularIndices, it looks like that’s the only method needed! Though probably `Base.checkbounds` is good to define too, to say when the access is inbounds or not. It’s only a [few lines of code](https://github.com/ericphanson/ModularIndices.jl/blob/a87a62c316c97a6408d6caf0005298da1f4cf068/src/ModularIndices.jl#L33-L57) so I think it should be pretty easy to define your own. InvertedIndices is a bit longer and more complicated because it’s doing a more complicated operation.

---

<div class="post-metadata">

### Author: ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)
#### Post date: [May 23, 2021, 11:20pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/4 "2021-05-23T23:20:18Z")

</div>

> [@stevengj](#):
>
> `lastindex(a)-2` is the equivalent to `end-2` outside of an indexing expression.

Unfortunately this needs a reference to `a` which isn’t always available. (In Python I can specify “next-to-last index” without needing that reference – just `ix = -2`.)

---

<div class="post-metadata">

### Author: ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)
#### Post date: [May 23, 2021, 11:27pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/5 "2021-05-23T23:27:12Z")

</div>

> [@ericphanson](#):
>
> But anyway, you could do the same thing with a `Last` struct so that say `Last(n)` would give `v[Last(n)] == v[end - n]` .

This seems like the right solution.

Maybe something like

```julia
struct LastBut{T}
n::T
end

getindex(a::AbstractArray, lb::LastBut) = a[lastindex(a) - lb.n]

```

---

<div class="post-metadata">

### Author: ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)
#### Post date: [May 23, 2021, 11:27pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/6 "2021-05-23T23:27:40Z")

</div>

> [@ericphanson](#):
>
> you could do the same thing with a `Last` struct

The package [EndpointRanges.jl](https://github.com/JuliaArrays/EndpointRanges.jl) does exactly this. Plus methods to allow things like `iend-2` to adjust what’s stored. (Although maybe it was written before Base handled this? Certainly before `begin` worked.)

---

<div class="post-metadata">

### Author: ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)
#### Post date: [May 23, 2021, 11:28pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/7 "2021-05-23T23:28:53Z")

</div>

Yeah, exactly. `Base.to_indices` is just a way to intercept indexing at a different level to be able to make it work for e.g. any dimension of a multidimensional array.

---

<div class="post-metadata">

### Author: ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)
#### Post date: [May 23, 2021, 11:33pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/8 "2021-05-23T23:33:04Z")

</div>

I think it would be nice for Julia to move away from being “indexed from 1” toward “abstract” indexing: currently people usually use `a[3]` even when they mean more generally `a[begin+2]`. I wonder if there’s a way to encourage index-generic programming like this.

---

<div class="post-metadata">

### Author: ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)
#### Post date: [May 24, 2021, 3:43pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/9 "2021-05-24T15:43:25Z")

</div>

Abstract indexing works completely if you want to use it, doesn’t it?

For convenience it is still nice to use numbers, but in packages it would be nice if we stick to the generic way.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [May 25, 2021, 2:35pm UTC](https://discourse.julialang.org/t/specifying-index-without-access-to-array/61693/10 "2021-05-25T14:35:31Z")

</div>

> [@jzr](#):
>
> way to encourage index-generic programming like this

It is up to the coder at this point; I imagine that older code will be updated on demand (by someone making a PR when they need it), but pretty much all new code should the relevant generic constructs.
