julia> a=1:1:2
1:1:2
julia> reverse!(a)
ERROR: setindex! not defined for StepRange{Int64,Int64}
Stacktrace:
[1] error(::String, ::Type) at ./error.jl:42
[2] error_if_canonical_setindex(::IndexLinear, ::StepRange{Int64,Int64}, ::Int64) at ./abstractarray.jl:1082
[3] setindex! at ./abstractarray.jl:1073 [inlined]
[4] reverse!(::StepRange{Int64,Int64}, ::Int64, ::Int64) at ./array.jl:1524
[5] reverse!(::StepRange{Int64,Int64}) at ./array.jl:1515
[6] top-level scope at REPL[49]:1
Ranges are not mutable types, so there’s no in-place reverse! for them:
julia> typeof(1:1:2).mutable
false
If you’re trying to use the same code on both ranges and vectors, you might be interested in BangBang.jl instead, but it doesn’t yet have a reverse!! method. (Maybe someone want’s to write a PR?)
This is a case where you probably don’t need to worry about in-place operations anyway. Ranges are so light (they are like what? 3 numbers?) that it shouldn’t really make a performance difference anyway
Note that constructing a range is not always for free or elided, even when constant propagation would normally apply. range is much more of a hefty operation than you might think:
julia> foo() = range(1, 10, length=30)
foo (generic function with 1 method)
julia> @btime foo()
116.499 ns (0 allocations: 0 bytes)
1.0:0.3103448275862069:10.0
julia> bar() = 1:0.01:10
bar (generic function with 1 method)
julia> @btime bar()
166.943 ns (0 allocations: 0 bytes)
1.0:0.01:10.0
You sort of proved my point by trying to disprove it, but I do applaud the correction. I’m not saying it is free to construct a range, but I doubt that this is something most people need to worry about eliminating from their code. Operations that are non-allocating and with timings on the nanosecond scale are generally not the first place to go looking for performance improvements.