Перечислимый — это объект, который может быть перечислен. «Перечислимый» означает подсчитывать членов набора / коллекции / категории один за другим (обычно по порядку, обычно по имени).
Elixir предлагает концепцию перечислимых элементов и модуль Enum для работы с ними. Функции в модуле Enum ограничены, как следует из названия, перечислением значений в структурах данных. Примером перечислимой структуры данных является список, кортеж, карта и т. Д. Модуль Enum предоставляет нам чуть более 100 функций для работы с перечислениями. Мы обсудим несколько важных функций в этой главе.
Все эти функции принимают перечислимый в качестве первого элемента и функцию в качестве второго и работают с ними. Функции описаны ниже.
все?
Когда мы используем все ? функция, вся коллекция должна иметь значение true, в противном случае будет возвращено значение false. Например, чтобы проверить, являются ли все элементы в списке нечетными числами, тогда.
res = Enum.all?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end) IO.puts(res)
Когда вышеуказанная программа запущена, она дает следующий результат —
false
Это потому, что не все элементы этого списка нечетны.
любой?
Как следует из названия, эта функция возвращает true, если какой-либо элемент коллекции оценивается как true. Например —
res = Enum.any?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end) IO.puts(res)
Когда вышеуказанная программа запущена, она дает следующий результат —
true
ломоть
Эта функция делит нашу коллекцию на маленькие порции размера, указанного в качестве второго аргумента. Например —
res = Enum.chunk([1, 2, 3, 4, 5, 6], 2) IO.puts(res)
Когда вышеуказанная программа запущена, она дает следующий результат —
[[1, 2], [3, 4], [5, 6]]
каждый
Может потребоваться перебрать коллекцию без создания нового значения, для этого случая мы используем каждую функцию —
Enum.each(["Hello", "Every", "one"], fn(s) -> IO.puts(s) end)
Когда вышеуказанная программа запущена, она дает следующий результат —
Hello Every one
карта
Чтобы применить нашу функцию к каждому элементу и создать новую коллекцию, мы используем функцию карты. Это одна из самых полезных конструкций в функциональном программировании, так как она довольно выразительна и коротка. Давайте рассмотрим пример, чтобы понять это. Мы удвоим значения, хранящиеся в списке, и сохраним их в новом списке —
res = Enum.map([2, 5, 3, 6], fn(a) -> a*2 end) IO.puts(res)
Когда вышеуказанная программа запущена, она дает следующий результат —
[4, 10, 6, 12]
уменьшить
Функция Reduce помогает нам уменьшить наше перечисляемое значение до единственного значения. Для этого мы поставляем дополнительный аккумулятор (в нашем примере 5) для передачи в нашу функцию; если аккумулятор не указан, используется первое значение —
res = Enum.reduce([1, 2, 3, 4], 5, fn(x, accum) -> x + accum end) IO.puts(res)
Когда вышеуказанная программа запущена, она дает следующий результат —
15
Аккумулятор — это начальное значение, передаваемое в fn . Начиная со второго вызова, значение, возвращаемое предыдущим вызовом, передается как накопленный. Мы также можем использовать уменьшить без аккумулятора —
res = Enum.reduce([1, 2, 3, 4], fn(x, accum) -> x + accum end) IO.puts(res)
Когда вышеуказанная программа запущена, она дает следующий результат —
10
уник
Функция uniq удаляет дубликаты из нашей коллекции и возвращает только набор элементов в коллекции. Например —
res = Enum.uniq([1, 2, 2, 3, 3, 3, 4, 4, 4, 4]) IO.puts(res)
При запуске вышеуказанной программы, она дает следующий результат —
[1, 2, 3, 4]
Стремительная оценка
Все функции в модуле Enum нетерпеливы. Многие функции ожидают перечисления и возвращают список обратно. Это означает, что при выполнении нескольких операций с Enum каждая операция будет генерировать промежуточный список, пока мы не достигнем результата. Давайте рассмотрим следующий пример, чтобы понять это —
odd? = &(odd? = &(rem(&1, 2) != 0) res = 1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(odd?) |> Enum.sum IO.puts(res)
Когда вышеуказанная программа запущена, она дает следующий результат —
7500000000
В приведенном выше примере есть конвейер операций. Мы начнем с диапазона, а затем умножим каждый элемент в диапазоне на 3. Эта первая операция теперь создаст и вернет список из 100_000 элементов. Затем мы сохраняем все нечетные элементы из списка, генерируя новый список, теперь с 50_000 элементами, а затем суммируем все записи.
Символ |>, используемый в приведенном выше фрагменте, является оператором канала : он просто берет вывод из выражения с левой стороны и передает его в качестве первого аргумента в вызов функции с правой стороны. Это похоже на Unix | оператор. Его цель состоит в том, чтобы выделить поток данных, преобразуемых с помощью ряда функций.
Без оператора канала код выглядит сложным —
Enum.sum(Enum.filter(Enum.map(1..100_000, &(&1 * 3)), odd?))
У нас есть много других функций, однако, только несколько важных были описаны здесь.