 # Lazy subranges or `1:end` as entity

Sometimes I’d like to be able to write

``````r = 1:End()-1
x[r] .= y[r]
``````

Is this a good idea and how to achieve this?

Are you concerned by the cost of building the `1:end - 1` range in:

``````x[1:end - 1] .= y[1:end - 1]
``````

?

No, not at all, just for readability in expressions like

``````sk=10; plot([first.(y[1:sk:end]) for y in ys[1:sk:end]],[last.(y[1:sk:end,end]) for y in ys[1:sk:end]])
``````

vs

``````r=1:10:End()
plot([first.(y[r, end]) for y in ys[r]], [last.(y[r,end]) for y in ys[r]])
``````

You could define

1. an `End` type, eg describing `end + a`,
2. arithmetic on it,
3. a `Base.colon` method, that emits another custom type which can contains ranges with this kind of endpoints,
4. `Base.getindex` and `Base.setindex` method for this custom type.

I don’t think it is worth it though. If in the above example you don’t want `End` to resolve differently for `x` and `y` and they have the same indexes, you could use something like

``````r = indices(x, 1)[1:(end-1)]
x[r] .= y[r]
``````

Otherwise, I think that `x[1:(end-1)] .= y[1:(end-1)]` is just more readable.

2 Likes

I once (in Julia 0.2 or 0.3) made such an `End` type: https://bitbucket.org/maurow/ragged.jl/src/ebbd1cdfd796ef626e9c5193dc75b6494fe8b21f/src/Ragged.jl#lines-13
But I’m sure there are better ways to go about it. But it’s not trivial, that is why Julia opted for a syntax approach to the problem.

1 Like

I could also image to define something along the lines

``````struct Formula{T} f::T end
farg(args, symb) = last(args[findlast(x->first(x)==symb, args)])
import Base.getindex
(f::Formula)(;args...) = f.f(;args...)
getindex(a::AbstractArray, f::Formula) = a[f(END=length(a))]
``````

so that for

``````r = Formula((;args...)->1:farg(args, :END)-1)
``````
``````julia> rand(10)[r]
9-element Array{Float64,1}:
0.355413
0.26395
0.260973
0.0454235
0.860611
0.958574
0.912541
0.812007
0.500342
``````

and then define a macro `@formula` giving syntactic sugar to `r = Formula((;args...)->1:farg(args, :END)-1)`