# Range (Elixir v1.13.0-dev) View Source

Ranges represent a sequence of zero, one or many, ascending or descending integers with a common difference called step.

Ranges are always inclusive and they may have custom steps.
The most common form of creating and matching on ranges is
via the `first..last`

and `first..last//step`

notations, auto-imported from `Kernel`

:

```
iex> Enum.to_list(1..3)
[1, 2, 3]
iex> Enum.to_list(1..3//2)
[1, 3]
iex> Enum.to_list(3..1//-1)
[3, 2, 1]
```

Ranges may also have a single element:

```
iex> Enum.to_list(1..1)
[1]
iex> Enum.to_list(1..1//2)
[1]
```

Or even no elements at all:

```
iex> Enum.to_list(10..0//1)
[]
iex> Enum.to_list(0..10//-1)
[]
```

When defining a range without a step, the step will be
defined based on the first and last position of the
range, If `first >= last`

, it will be an increasing range
with a step of 1. Otherwise, it is a decreasing range.
Note however implicitly decreasing ranges are deprecated.
Therefore, if you need a decreasing range from `3`

to `1`

,
prefer to write `3..1//-1`

instead.

## Definition

An increasing range `first..last//step`

is a range from
`first`

to `last`

increasing by `step`

where `step`

must be a positive
integer and all values `v`

must be `first <= v and v <= last`

. Therefore, a range
`10..0//1`

is an empty range because there is no value `v`

that is `10 <= v and v <= 0`

.

Similarly, a decreasing range `first..last//step`

is a range
from `first`

to `last`

decreasing by `step`

where `step`

must be a negative
integer and values `v`

must be `first >= v and v >= last`

. Therefore, a range
`0..10//-1`

is an empty range because there is no value `v`

that is `0 >= v and v >= 10`

.

## Representation

Internally, ranges are represented as structs:

```
iex> range = 1..9//2
1..9//2
iex> first..last//step = range
iex> first
1
iex> last
9
iex> step
2
iex> range.step
2
```

You can access the range fields (`first`

, `last`

, and `step`

)
directly but you should not modify nor create ranges by hand.
Instead use the proper operators or `new/2`

and `new/3`

.

A range implements the `Enumerable`

protocol, which means
functions in the `Enum`

module can be used to work with
ranges:

```
iex> range = 1..10
1..10
iex> Enum.reduce(range, 0, fn i, acc -> i * i + acc end)
385
iex> Enum.count(range)
10
iex> Enum.member?(range, 11)
false
iex> Enum.member?(range, 8)
true
```

Such function calls are efficient memory-wise no matter the
size of the range. The implementation of the `Enumerable`

protocol uses logic based solely on the endpoints and does
not materialize the whole list of integers.

# Link to this section Summary

## Functions

Checks if two ranges are disjoint.

Creates a new range.

Creates a new range with `step`

.

Returns the size of `range`

.

# Link to this section Types

## Specs

limit() :: integer()

## Specs

step() :: pos_integer() | neg_integer()

## Specs

## Specs

t(first, last) :: %Range{first: first, last: last, step: step()}

# Link to this section Functions

## Specs

Checks if two ranges are disjoint.

## Examples

```
iex> Range.disjoint?(1..5, 6..9)
true
iex> Range.disjoint?(5..1, 6..9)
true
iex> Range.disjoint?(1..5, 5..9)
false
iex> Range.disjoint?(1..5, 2..7)
false
```

Steps are also considered when computing the ranges to be disjoint:

```
iex> Range.disjoint?(1..10//2, 2..10//2)
true
# First element in common in all below is 29
iex> Range.disjoint?(2..100//3, 9..100//5)
false
iex> Range.disjoint?(101..2//-3, 99..9//-5)
false
iex> Range.disjoint?(1..100//14, 8..100//21)
false
iex> Range.disjoint?(57..-1//-14, 8..100//21)
false
iex> Range.disjoint?(1..100//14, 51..8//-21)
false
# If 29 is out of range
iex> Range.disjoint?(1..28//14, 8..28//21)
true
iex> Range.disjoint?(2..28//3, 9..28//5)
true
```

## Specs

Creates a new range.

If `first`

is less than `last`

, the range will be increasing from
`first`

to `last`

. If `first`

is equal to `last`

, the range will contain
one element, which is the number itself.

If `first`

is greater than `last`

, the range will be decreasing from `first`

to `last`

, albeit this behaviour is deprecated. Therefore, it is advised to
explicitly list the step with `new/3`

.

## Examples

```
iex> Range.new(-100, 100)
-100..100
```

## Specs

Creates a new range with `step`

.

## Examples

```
iex> Range.new(-100, 100, 2)
-100..100//2
```

Returns the size of `range`

.

## Examples

```
iex> Range.size(1..10)
10
iex> Range.size(1..10//2)
5
iex> Range.size(1..10//3)
4
iex> Range.size(1..10//-1)
0
iex> Range.size(10..1)
10
iex> Range.size(10..1//-1)
10
iex> Range.size(10..1//-2)
5
iex> Range.size(10..1//-3)
4
iex> Range.size(10..1//1)
0
```