當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Elixir Collectable用法及代碼示例


Elixir語言中 Collectable 相關用法介紹如下。

一種遍曆數據結構的協議。

Enum.into/2 函數使用此協議將可枚舉插入到集合中:

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

為什麽要收藏?

Enumerable 協議對於從集合中取出值很有用。為了支持廣泛的值, Enumerable 協議提供的函數不保持形狀。例如,將映射傳遞給 Enum.map/2 總是返回一個列表。

這種設計是故意的。 Enumerable 旨在支持無限集合、資源和其他具有固定形狀的結構。例如,將值插入 Range 是沒有意義的,因為它具有固定的形狀,其中僅存儲範圍限製和步長。

Collectable 模塊旨在填補 Enumerable 協議留下的空白。 Collectable.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 的簡化實現。在此實現中,"collecting" 元素僅意味著通過 MapSet.put/2 將它們插入集合中。

defimpl Collectable, for: MapSet do
  def into(map_set) do
    collector_fun = fn
      map_set_acc, {:cont, elem} ->
        MapSet.put(map_set_acc, elem)

      map_set_acc, :done ->
        map_set_acc

      _map_set_acc, :halt ->
        :ok
    end

    initial_acc = map_set

    {initial_acc, collector_fun}
  end
end

所以現在我們可以調用 Enum.into/2

iex> Enum.into([1, 2, 3], MapSet.new())
#MapSet<[1, 2, 3]>

相關用法


注:本文由純淨天空篩選整理自elixir-lang.org大神的英文原創作品 Collectable。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。