Question about range operator (":")

I was testing some code and noticed something that seemed odd to me when trying to use the range operator (“:”).

julia> 1:5
1:5

but

julia> 5:1
5:4

I don’t see anything in the help for : that suggests different behavior if a<b or a>b for a:b, although in the help for range I do see this statement: If length is not specified and stop - start is not an integer multiple of step, a range that ends before stop will be produced.

So I guess that the issue is that a range that goes from a larger number to a smaller is giving a negative number, and is not considered an integer multiple of step? Is this expected behavior? I’d sort of expect to be able to create a range from a larger number to a smaller.

Note the part about step defaulting to 1.

help?> :
search: : :: ?: >: <:

  (:)(start, [step], stop)

  Range operator. a:b constructs a range from a to b with a step
  size equal to 1, which produces:

    •  a UnitRange when a and b are integers, or

    •  a StepRange when a and b are characters, or

    •  a StepRangeLen when a and/or b are floating-point.

  a:s:b is similar but uses a step size of s (a StepRange or
  StepRangeLen). See also range for more control.

  The operator : is also used in indexing to select whole
  dimensions, e.g. in A[:, 1].

  : is also used to quote code, e.g. :(x + y) isa Expr and :x isa
  Symbol. Since :2 isa Int, it does not create a range in indexing:
  v[:2] == v[2] != v[begin:2].

This is the expected and documented behavior. If you want to go backwards, you need a step of -1.

julia> r = 5:1
5:4

julia> step(r)
1

julia> typeof(r)
UnitRange{Int64}

julia> r = 5:-1:1
5:-1:1

julia> step(r)
-1

julia> typeof(r)
StepRange{Int64, Int64}

julia> collect(r)
5-element Vector{Int64}:
 5
 4
 3
 2
 1
2 Likes

Ah, I see. So 5:-1:1 works just fine. I guess in my head, I only ever think of step sizes as magnitudes, not directions. Guess I’m still used to how R does it.

Anyway, thanks for the help!

1 Like

here some more thoughts on the topic

here the code

  ifelse(stop >= start, stop, convert(T,start-oneunit(stop-start)))

See also related discussions:

2 Likes

You can also do reverse(1:5) which i think is more readable than 5:-1:1.

1 Like

Ah, I like that one, thanks. :slight_smile:

You know, this is a common enough error that it would probably be worth explicitly calling out in the docstring.

PR: Explicitly call out reverse ranges in `:` docstring by BioTurboNick · Pull Request #53626 · JuliaLang/julia · GitHub

3 Likes