Spec-Zone.ru › Elixir 1.13

Диапазон

Диапазоны представляют собой последовательность нуля, одного или нескольких возрастающих или убывающих целых чисел с общим разностью, называемой шагом.

Диапазоны всегда включают крайние значения и могут иметь пользовательские шаги. Наиболее распространённый способ создания и сопоставления диапазонов — с помощью обозначений first..last и first..last//step, автоматически импортируемых из 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]

Диапазоны также могут содержать единственный элемент:

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

Или даже не содержать элементов вовсе:

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

При определении диапазона без шага, шаг определяется на основе первого и последнего значения диапазона. Если first >= last, это будет возрастающий диапазон с шагом 1. В противном случае, это убывающий диапазон. Однако неявные убывающие диапазоны устарели. Поэтому, если вам нужен убывающий диапазон от 3 до 1, предпочтительнее использовать 3..1//-1.

Определение

Возрастающий диапазон first..last//step — это диапазон от first до last с шагом step, где step должно быть положительным целым числом, а все значения v должны быть first <= v and v <= last. Таким образом, диапазон 10..0//1 является пустым диапазоном, так как нет значения v, которое бы 10 <= v and v <= 0.

Аналогично, убывающий диапазон first..last//step — это диапазон от first до last с шагом step, где step должно быть отрицательным целым числом, а значения v должны быть first >= v and v >= last. Таким образом, диапазон 0..10//-1 является пустым диапазоном, так как нет значения v, которое бы 0 >= v and v >= 10.

Представление

Внутренне диапазоны представлены как структуры:

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

Вы можете напрямую получить доступ к полям диапазона (first, last, и step), но не должны изменять или создавать диапазоны вручную. Вместо этого используйте соответствующие операторы или new/2 и new/3.

Диапазон реализует протокол Enumerable, что означает, что функции в модуле Enum могут быть использованы для работы с диапазонами:

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

Такие вызовы функций являются эффективными с точки зрения памяти, независимо от размера диапазона. Реализация протокола Enumerable использует логику, основанную только на конечных значениях, и не материализует весь список целых чисел.

Сводка

Типы

limit()
шаг()
t()
t(первое, последнее)

Функции

disjoint?(диапазон1, диапазон2)

Проверяет, являются ли два диапазона непересекающимися.

new(первое, последнее)

Создаёт новый диапазон.

new(первое, последнее, шаг)

Создаёт новый диапазон со step.

size(диапазон)

Возвращает размер range.

Типы

limit()Источник

@type limit() :: integer()

шаг()Источник

@type step() :: pos_integer() | neg_integer()

t()Источник

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

t(первое, последнее)Источник

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

Функции

disjoint?(диапазон1, диапазон2)Источник

@spec disjoint?(t(), t()) :: boolean()

Проверяет, являются ли два диапазона непересекающимися.

Примеры

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

Шаги также учитываются при вычислении того, являются ли диапазоны непересекающимися:

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(первое, последнее)Источник

@spec new(limit(), limit()) :: t()

Создаёт новый диапазон.

Если first меньше, чем last, диапазон будет возрастающим от first до last. Если first равно last, диапазон будет содержать один элемент — это число само по себе.

Если first больше, чем last, диапазон будет убывающим от first до last, хотя это поведение устарело. Поэтому рекомендуется явно указывать шаг с помощью new/3.

Примеры

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

new(первое, последнее, шаг)Источник

@spec new(limit(), limit(), step()) :: t()

Создаёт новый диапазон со step.

Примеры

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

size(диапазон)Источник

Возвращает размер range.

Примеры

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.13.4/Range.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API