# The colon punctuation: Why doesn't 5:1 return \[5, 4, 3, 2, 1\]?

**URL:** https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676
**Category:** New to Julia
**Tags:** question, range, unitrange
**Created:** [December 15, 2023, 4:51pm UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676 "2023-12-15T16:51:41Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)
#### Post date: [December 15, 2023, 4:51pm UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676/1 "2023-12-15T16:51:41Z")

</div>

I got surprised by this:

```julia
julia> 1:5 # Expected
1:5

julia> 5:1 # Unexpected
5:4

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

julia> collect(5:1) # Doubly Unexpected
Int64[]

julia> collect(5:-1:1) # Ok, I *think* I get it...
5-element Vector{Int64}:
 5
 4
 3
 2
 1

```

The documentation says:

> `a:b` colons ([`:`](https://docs.julialang.org/en/v1/base/math/#Base.::)) used as a binary infix operator construct a range from `a` to `b` (inclusive) with fixed step size `1`  
> [Punctuation · The Julia Language](https://docs.julialang.org/en/v1/base/punctuation/)

I expected the second output to be `5:1`, ie` [5, 4, 3, 2, 1]`. Ok, I can see that reading carefully the stepsize is 1, when I wanted -1. But why does it say` 5:4`? And why not have it automatically switch the sign if a \> b?

Has adding a note about this to the docs been considered?

---

<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: [December 15, 2023, 4:55pm UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676/2 "2023-12-15T16:55:46Z")

</div>

> [@Tetrakai](#):
>
> But why does it say` 5:4`?

> [@Empty range has first element, bug or feature?](https://discourse.julialang.org/t/empty-range-has-first-element-bug-or-feature/105236/7):
>
> It’s pretty important because it allows you to return useful information from searches where the result is an empty range, because the start of the range tells you the location. For example, searching for word boundaries returns an empty range that has a location: julia\> findnext(r"\b", "foo bar", 2) 4:3

> [@Tetrakai](#):
>
> And why not have it automatically switch the sign if a \> b?

By the same token, if `5:4` meant `5:-1:4` as you suggest, then it would be impossible to express empty ranges.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [December 15, 2023, 5:02pm UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676/3 "2023-12-15T17:02:56Z")

</div>

You pretty much answered your own question on why it’s not equal to `[5,4,3,2,1]`: it’s because that’s not its definition. Yes, that’s tautological. 🙂 Steven has a good motivation for the current behavior, but a different choice could have been made.

> [@Tetrakai](#):
>
> But why does it say` 5:4`

Julia “normalizes” empty ranges such that the end is one step less than the beginning, so that’s why it’s `5:4` and not `5:1`. Why? IIRC it helps with some efficiencies for _all_ ranges, even non-empty ones, if you can assume that.

Could docs be improved? Always!

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [December 16, 2023, 1:05am UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676/4 "2023-12-16T01:05:13Z")

</div>

Take a look at the function `range` and the rules become clearer. If you specify only `start` and `stop` the `step` is assumed to be `1`.

```julia-repl
help?> range
search: range LinRange UnitRange StepRange StepRangeLen

  range(start, stop, length)
  range(start, stop; length, step)
  range(start; length, stop, step)
  range(;start, length, stop, step)

  Construct a specialized array with evenly spaced elements and
  optimized storage (an AbstractRange) from the arguments.
  Mathematically a range is uniquely determined by any three of
  start, step, stop and length. Valid invocations of range are:

    • Call range with any three of start, step, stop,
       length.

    • Call range with two of start, stop, length. In this
       case step will be assumed to be one. If both
       arguments are Integers, a UnitRange will be
       returned.

    • Call range with one of stop or length. start and
       step will be assumed to be one.

```

With the colon syntax, you can specify `start:step:stop`.

---

<div class="post-metadata">

### Author: ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)
#### Post date: [December 16, 2023, 2:06am UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676/5 "2023-12-16T02:06:23Z")

</div>

> <https://github.com/JuliaLang/julia/issues/52195>
>
> See https://github.com/JuliaLang/julia/issues/51793. The issue is to change this… in Julia 2.0. Could introduce \`start(r)\` and \`stop(r)\` only for ranges to do what \`first(r)\` and \`last(r)\` currently do.

---

<div class="post-metadata">

### Author: ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)
#### Post date: [December 16, 2023, 5:42am UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676/6 "2023-12-16T05:42:40Z")

</div>

> [@stevengj](#):
>
> By the same token, if `5:4` meant `5:-1:4` as you suggest, then it would be impossible to express empty ranges.

An empty range could be expressed as `5:1:4` (i.e. by explicitly specifying a positive step size)

I think there are a few different points to this topic.

- Definition/characteristics of ranges (start, length, stop, step)
- Why are empty ranges “normalised”
- What are default values for under-specified ranges, in particular using colon syntax.

In some contexts, I think it would be reasonable to expect differing defaults for when a range is under-specified. When start and stop are explicitly specified with literals (e.g. 3:7, 5:1), I don’t think it is unreasonable to expect a default step size of +/-1 to make a non-empty range.

However, personally I do like the current default step size of +1 (allowing empty ranges), because it simplifies the following type of logic of iterating through 0 or more items:

```julia
# loop is skipped if n <= 0
for i in 1:n
    ...
end

```

---

<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: [December 16, 2023, 1:56pm UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676/7 "2023-12-16T13:56:53Z")

</div>

> [@greg\_plowman](#):
>
> An empty range could be expressed as `5:1:4`

No, because then `m:step:n` would not be [type stable](https://docs.julialang.org/en/v1/manual/faq/#man-type-stability). Julia uses a separate `UnitRange` type to represent `m:n` ranges (in which the step size is implicitly 1), in order to save 1/3 of the storage in this common case and to enable other optimizations.

```julia
julia> typeof(5:4)
UnitRange{Int64}

julia> typeof(5:1:4)
StepRange{Int64, Int64}

```

Similarly, automatically converting `m:n` to `n:-1:m` when `n < m` would not be type stable.

---

<div class="post-metadata">

### Author: ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)
#### Post date: [December 16, 2023, 5:30pm UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676/8 "2023-12-16T17:30:16Z")

</div>

> [@stevengj](#):
>
> No, because then `m:step:n` would not be [type stable](https://docs.julialang.org/en/v1/manual/faq/#man-type-stability). Julia uses a separate `UnitRange` type to represent `m:n` ranges (in which the step size is implicitly 1), in order to save 1/3 of the storage in this common case and to enable other optimizations.

Oh, good point.  
Thanks for pointing this out!

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [December 16, 2023, 6:04pm UTC](https://discourse.julialang.org/t/the-colon-punctuation-why-doesnt-5-1-return-5-4-3-2-1/107676/9 "2023-12-16T18:04:19Z")

</div>

Perhaps we should make `start:Val(step):stop` work.
