Range
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 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.
Summary
Types
Functions
- disjoint?(range1, range2)
Checks if two ranges are disjoint.
- new(first, last)
Creates a new range.
- new(first, last, step)
Creates a new range with
step
.- size(range)
Returns the size of
range
.
Types
Functions
disjoint?(range1, range2)Source
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)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)Source
Specs
new(limit(), limit(), step()) :: t()
Creates a new range with step
.
Examples
iex> Range.new(-100, 100, 2) -100..100//2
size(range)Source
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
© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.12.0/Range.html