Spec-Zone.ru › Elixir 1.6

Коллектируемый протокол

Протокол для обхода структур данных.

Функция Enum.into/2 использует этот протокол для вставки перечислимого в коллекцию:

iex> Enum.into([a: 1, b: 2], %{})
%{a: 1, b: 2}

Почему Коллектируемый?

Протокол Enumerable полезен для извлечения значений из коллекции. Для поддержки широкого спектра значений функции, предоставляемые протоколом Enumerable, не сохраняют структуру. Например, передача карты в Enum.map/2 всегда возвращает список.

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

Модуль Collectable был разработан для заполнения пробела, оставленного протоколом Enumerable. into/1 можно рассматривать как противоположность Enumerable.reduce/3. Если Enumerable направлен на извлечение значений, Collectable.into/1 направлен на сбор этих значений в структуру.

Примеры

Чтобы продемонстрировать, как вручную использовать протокол Collectable, давайте посмотрим на его реализацию для MapSet.

iex> {initial_acc, collector_fun} = Collectable.into(MapSet.new())
iex> updated_acc = Enum.reduce([1, 2, 3], initial_acc, fn elem, acc ->
...>   collector_fun.(acc, {:cont, elem})
...> end)
iex> collector_fun.(updated_acc, :done)
#MapSet<[1, 2, 3]>

Чтобы продемонстрировать реализацию протокола, мы можем еще раз взглянуть на реализацию для MapSet. В этой реализации «сбор» элементов просто означает вставку их в множество с помощью MapSet.put/2.

defimpl Collectable do
  def into(original) do
    collector_fun = fn
      set, {:cont, elem} -> MapSet.put(set, elem)
      set, :done -> set
      _set, :halt -> :ok
    end

    {original, collector_fun}
  end
end

Обзор

Типы

command()
t()

Функции

into(collectable)

Возвращает начальный накопитель и функцию «сборщика»

Типы

command()

command() :: {:cont, term()} | :done | :halt

t()

t() :: term()

Функции

into(collectable)

into(t()) :: {term(), (term(), command() -> t() | term())}

Возвращает начальный накопитель и функцию «сборщика».

Возвращаемая функция принимает термин и команду и вставляет термин в коллектируемый объект на каждой {:cont, term} команде.

:done передаётся в качестве команды, когда дальнейшие значения не будут вставлены. Это полезно, когда необходимо закрыть ресурсы или нормализовать значения. Коллектируемый объект должен быть возвращён, когда команда равна :done.

Если вставка внезапно прервана, :halt передаётся, и функция может вернуть любое значение, так как оно не будет использовано.

Примеры использования протокола Collectable и into/1 см. в документации модуля.

© 2012 Plataformatec
Licensed under the Apache License, Version 2.0.
https://hexdocs.pm/elixir/1.6.6/Collectable.html

Spec-Zone.ru

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