# Range (Elixir v1.12.2) 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)

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

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 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 all 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`.

# limit()

View Source

## Specs

`limit() :: integer()`

# step()

View Source

## Specs

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

# t()

View Source

## Specs

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

# t(first, last)

View Source

## Specs

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

# disjoint?(range1, range2)

View Source (since 1.8.0)

## Specs

`disjoint?(t(), t()) :: boolean()`

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``````

# new(first, last)

View Source

## Specs

`new(limit(), limit()) :: t()`

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``````

# new(first, last, step)

View Source (since 1.12.0)

## Specs

`new(limit(), limit(), step()) :: t()`

Creates a new range with `step`.

## Examples

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

# size(range)

View Source (since 1.12.0)

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``````