<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="generator" content="ExDoc v0.19.1"> <title>Collectable – Elixir v1.7.2</title> <link rel="stylesheet" href="dist/app-240d7fc7e5.css" /> <link rel="canonical" href="https://hexdocs.pm/elixir/v1.7/Collectable.html" /> <script src="dist/sidebar_items-cdf4e58b19.js"></script> </head> <body data-type="modules"> <script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script> <div class="main"> <button class="sidebar-button sidebar-toggle"> <span class="icon-menu" aria-hidden="true"></span> <span class="sr-only">Toggle Sidebar</span> </button> <button class="sidebar-button night-mode-toggle"> <span class="icon-theme" aria-hidden="true"></span> <span class="sr-only">Toggle Theme</span> </button> <section class="sidebar"> <a href="http://elixir-lang.org/docs.html" class="sidebar-projectLink"> <div class="sidebar-projectDetails"> <h1 class="sidebar-projectName"> Elixir </h1> <h2 class="sidebar-projectVersion"> v1.7.2 </h2> </div> <img src="assets/logo.png" alt="Elixir" class="sidebar-projectImage"> </a> <form class="sidebar-search" action="search.html"> <button type="submit" class="search-button"> <span class="icon-search" aria-hidden="true"></span> </button> <input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" /> </form> <ul class="sidebar-listNav"> <li><a id="extras-list" href="#full-list">Pages</a></li> <li><a id="modules-list" href="#full-list">Modules</a></li> <li><a id="exceptions-list" href="#full-list">Exceptions</a></li> </ul> <div class="gradient"></div> <ul id="full-list" class="sidebar-fullList"></ul> </section> <section class="content"> <div class="content-outer"> <div id="content" class="content-inner"> <h1> <small class="visible-xs">Elixir v1.7.2</small> Collectable <small>protocol</small> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/collectable.ex#L1" title="View Source" class="view-source" rel="help"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> </h1> <section id="moduledoc"> <p>A protocol to traverse data structures.</p> <p>The <a href="Enum.html#into/2"><code class="inline">Enum.into/2</code></a> function uses this protocol to insert an enumerable into a collection:</p> <pre><code class="nohighlight makeup elixir"><span class="gp unselectable">iex> </span><span class="nc">Enum</span><span class="o">.</span><span class="n">into</span><span class="p" data-group-id="1914926035-1">(</span><span class="p" data-group-id="1914926035-2">[</span><span class="ss">a</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="ss">b</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p" data-group-id="1914926035-2">]</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="1914926035-3">%{</span><span class="p" data-group-id="1914926035-3">}</span><span class="p" data-group-id="1914926035-1">)</span><span class="w"> </span><span class="p" data-group-id="1914926035-4">%{</span><span class="ss">a</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="ss">b</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="p" data-group-id="1914926035-4">}</span></code></pre> <h2 id="module-why-collectable" class="section-heading"> <a href="#module-why-collectable" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Why Collectable? </h2> <p>The <a href="Enumerable.html"><code class="inline">Enumerable</code></a> protocol is useful to take values out of a collection. In order to support a wide range of values, the functions provided by the <a href="Enumerable.html"><code class="inline">Enumerable</code></a> protocol do not keep shape. For example, passing a map to <a href="Enum.html#map/2"><code class="inline">Enum.map/2</code></a> always returns a list.</p> <p>This design is intentional. <a href="Enumerable.html"><code class="inline">Enumerable</code></a> was designed to support infinite collections, resources and other structures with fixed shape. For example, it doesn’t make sense to insert values into a range, as it has a fixed shape where just the range limits are stored.</p> <p>The <a href="Collectable.html#content"><code class="inline">Collectable</code></a> module was designed to fill the gap left by the <a href="Enumerable.html"><code class="inline">Enumerable</code></a> protocol. <a href="#into/1"><code class="inline">into/1</code></a> can be seen as the opposite of <a href="Enumerable.html#reduce/3"><code class="inline">Enumerable.reduce/3</code></a>. If <a href="Enumerable.html"><code class="inline">Enumerable</code></a> is about taking values out, <a href="Collectable.html#into/1"><code class="inline">Collectable.into/1</code></a> is about collecting those values into a structure.</p> <h2 id="module-examples" class="section-heading"> <a href="#module-examples" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a> Examples </h2> <p>To show how to manually use the <a href="Collectable.html#content"><code class="inline">Collectable</code></a> protocol, let’s play with its implementation for <a href="MapSet.html"><code class="inline">MapSet</code></a>.</p> <pre><code class="nohighlight makeup elixir"><span class="gp unselectable">iex> </span><span class="p" data-group-id="1753321125-1">{</span><span class="n">initial_acc</span><span class="p">,</span><span class="w"> </span><span class="n">collector_fun</span><span class="p" data-group-id="1753321125-1">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Collectable</span><span class="o">.</span><span class="n">into</span><span class="p" data-group-id="1753321125-2">(</span><span class="nc">MapSet</span><span class="o">.</span><span class="n">new</span><span class="p" data-group-id="1753321125-3">(</span><span class="p" data-group-id="1753321125-3">)</span><span class="p" data-group-id="1753321125-2">)</span><span class="w"> </span><span class="gp unselectable">iex> </span><span class="n">updated_acc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Enum</span><span class="o">.</span><span class="n">reduce</span><span class="p" data-group-id="1753321125-4">(</span><span class="p" data-group-id="1753321125-5">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p" data-group-id="1753321125-5">]</span><span class="p">,</span><span class="w"> </span><span class="n">initial_acc</span><span class="p">,</span><span class="w"> </span><span class="k" data-group-id="1753321125-6">fn</span><span class="w"> </span><span class="n">elem</span><span class="p">,</span><span class="w"> </span><span class="n">acc</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="gp unselectable">...> </span><span class="w"> </span><span class="n">collector_fun</span><span class="o">.</span><span class="p" data-group-id="1753321125-7">(</span><span class="n">acc</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="1753321125-8">{</span><span class="ss">:cont</span><span class="p">,</span><span class="w"> </span><span class="n">elem</span><span class="p" data-group-id="1753321125-8">}</span><span class="p" data-group-id="1753321125-7">)</span><span class="w"> </span><span class="gp unselectable">...> </span><span class="k" data-group-id="1753321125-6">end</span><span class="p" data-group-id="1753321125-4">)</span><span class="w"> </span><span class="gp unselectable">iex> </span><span class="n">collector_fun</span><span class="o">.</span><span class="p" data-group-id="1753321125-9">(</span><span class="n">updated_acc</span><span class="p">,</span><span class="w"> </span><span class="ss">:done</span><span class="p" data-group-id="1753321125-9">)</span><span class="w"> </span><span class="p" data-group-id="1753321125-10">#</span><span class="nc" data-group-id="1753321125-10">MapSet</span><span class="p" data-group-id="1753321125-10"><</span><span class="p" data-group-id="1753321125-11">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p" data-group-id="1753321125-11">]</span><span class="p" data-group-id="1753321125-10">></span></code></pre> <p>To show how the protocol can be implemented, we can take again a look at the implementation for <a href="MapSet.html"><code class="inline">MapSet</code></a>. In this implementation “collecting” elements simply means inserting them in the set through <a href="MapSet.html#put/2"><code class="inline">MapSet.put/2</code></a>.</p> <pre><code class="nohighlight makeup elixir"><span class="kd">defimpl</span><span class="w"> </span><span class="nc">Collectable</span><span class="w"> </span><span class="k" data-group-id="8080708269-1">do</span><span class="w"> </span><span class="kd">def</span><span class="w"> </span><span class="nf">into</span><span class="p" data-group-id="8080708269-2">(</span><span class="n">original</span><span class="p" data-group-id="8080708269-2">)</span><span class="w"> </span><span class="k" data-group-id="8080708269-3">do</span><span class="w"> </span><span class="n">collector_fun</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k" data-group-id="8080708269-4">fn</span><span class="w"> </span><span class="n">set</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="8080708269-5">{</span><span class="ss">:cont</span><span class="p">,</span><span class="w"> </span><span class="n">elem</span><span class="p" data-group-id="8080708269-5">}</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">MapSet</span><span class="o">.</span><span class="n">put</span><span class="p" data-group-id="8080708269-6">(</span><span class="n">set</span><span class="p">,</span><span class="w"> </span><span class="n">elem</span><span class="p" data-group-id="8080708269-6">)</span><span class="w"> </span><span class="n">set</span><span class="p">,</span><span class="w"> </span><span class="ss">:done</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="n">set</span><span class="w"> </span><span class="c">_set</span><span class="p">,</span><span class="w"> </span><span class="ss">:halt</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="ss">:ok</span><span class="w"> </span><span class="k" data-group-id="8080708269-4">end</span><span class="w"> </span><span class="p" data-group-id="8080708269-7">{</span><span class="n">original</span><span class="p">,</span><span class="w"> </span><span class="n">collector_fun</span><span class="p" data-group-id="8080708269-7">}</span><span class="w"> </span><span class="k" data-group-id="8080708269-3">end</span><span class="w"> </span><span class="k" data-group-id="8080708269-1">end</span></code></pre> </section> <section id="summary" class="details-list"> <h1 class="section-heading"> <a class="hover-link" href="#summary"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this section</span> </a> Summary </h1> <div class="summary-types summary"> <h2> <a href="#types">Types</a> </h2> <div class="summary-row"> <div class="summary-signature"> <a href="#t:command/0">command()</a> </div> </div> <div class="summary-row"> <div class="summary-signature"> <a href="#t:t/0">t()</a> </div> </div> </div> <div class="summary-functions summary"> <h2> <a href="#functions">Functions</a> </h2> <div class="summary-row"> <div class="summary-signature"> <a href="#into/1">into(collectable)</a> </div> <div class="summary-synopsis"><p>Returns an initial accumulator and a “collector” function</p> </div> </div> </div> </section> <section id="types" class="details-list"> <h1 class="section-heading"> <a class="hover-link" href="#types"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this section</span> </a> Types </h1> <div class="types-list"> <div class="detail" id="t:command/0"> <div class="detail-header"> <a href="#t:command/0" class="detail-link" title="Link to this type"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this type</span> </a> <span class="signature">command()</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/collectable.ex#L58" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>command() :: {:cont, <a href="typespecs.html#built-in-types">term</a>()} | :done | :halt</pre> </div> </div> <section class="docstring"> </section> </div> <div class="detail" id="t:t/0"> <div class="detail-header"> <a href="#t:t/0" class="detail-link" title="Link to this type"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this type</span> </a> <span class="signature">t()</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/collectable.ex#L1" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> <div class="specs"> <pre>t() :: <a href="typespecs.html#built-in-types">term</a>()</pre> </div> </div> <section class="docstring"> </section> </div> </div> </section> <section id="functions" class="details-list"> <h1 class="section-heading"> <a class="hover-link" href="#functions"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this section</span> </a> Functions </h1> <div class="detail" id="into/1"> <div class="detail-header"> <a href="#into/1" class="detail-link" title="Link to this function"> <span class="icon-link" aria-hidden="true"></span> <span class="sr-only">Link to this function</span> </a> <span class="signature">into(collectable)</span> <a href="https://github.com/elixir-lang/elixir/blob/v1.7.2/lib/elixir/lib/collectable.ex#L77" class="view-source" rel="help" title="View Source"> <span class="icon-code" aria-hidden="true"></span> <span class="sr-only">View Source</span> </a> </div> <section class="docstring"> <p>Returns an initial accumulator and a “collector” function.</p> <p>The returned function receives a term and a command and injects the term into the collectable on every <code class="inline">{:cont, term}</code> command.</p> <p><code class="inline">:done</code> is passed as a command when no further values will be injected. This is useful when there’s a need to close resources or normalizing values. A collectable must be returned when the command is <code class="inline">:done</code>.</p> <p>If injection is suddenly interrupted, <code class="inline">:halt</code> is passed and the function can return any value as it won’t be used.</p> <p>For examples on how to use the <a href="Collectable.html#content"><code class="inline">Collectable</code></a> protocol and <a href="#into/1"><code class="inline">into/1</code></a> see the module documentation.</p> </section> </div> </section> <footer class="footer"> <p> <span class="line"> Built using <a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" target="_blank" rel="help noopener">ExDoc</a> (v0.19.1), </span> <span class="line"> designed by <a href="https://twitter.com/dignifiedquire" target="_blank" rel="noopener" title="@dignifiedquire">Friedel Ziegelmayer</a>. </span> </p> </footer> </div> </div> </section> </div> <script src="dist/app-a0c90688fa.js"></script> </body> </html>