Sophie

Sophie

distrib > Mageia > 7 > i586 > media > core-release > by-pkgid > 016232f1d9a3f7bee85855d35a2bca58 > files > 150

elixir-doc-1.7.2-1.mga7.noarch.rpm

<!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>Typespecs – Elixir v1.7.2</title>
    <link rel="stylesheet" href="dist/app-240d7fc7e5.css" />
      <link rel="canonical" href="https://hexdocs.pm/elixir/v1.7/typespecs.html" />
    <script src="dist/sidebar_items-cdf4e58b19.js"></script>
    
  </head>
  <body data-type="extras">
    <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>Typespecs</h1>
<p>Elixir comes with a notation for declaring types and specifications. Elixir is a dynamically typed language, and as such, type specifications are never used by the compiler to optimize or modify code. Still, using type specifications is useful because</p>
<ul>
<li>they provide documentation (for example, tools such as <a href="https://github.com/elixir-lang/ex_doc">ExDoc</a> show type specifications in the documentation)
</li>
<li>they’re used by tools such as <a href="http://www.erlang.org/doc/man/dialyzer.html">Dialyzer</a>, that can analyze code with typespec to find type inconsistencies and possible bugs
</li>
</ul>
<p>Type specifications (sometimes referred to as <em>typespecs</em>) are defined in different contexts using the following attributes:</p>
<ul>
<li><code class="inline">@type</code>
</li>
<li><code class="inline">@opaque</code>
</li>
<li><code class="inline">@typep</code>
</li>
<li><code class="inline">@spec</code>
</li>
<li><code class="inline">@callback</code>
</li>
<li><code class="inline">@macrocallback</code>
</li>
</ul>
<p>See the “User-defined types” and “Defining a specification” sub-sections below for more information on defining types and typespecs.</p>
<h2 id="a-simple-example" class="section-heading">
  <a href="#a-simple-example" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  A simple example
</h2>

<pre><code class="nohighlight makeup elixir"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">StringHelpers</span><span class="w"> </span><span class="k" data-group-id="5168328396-1">do</span><span class="w">
  </span><span class="na">@type</span><span class="w"> </span><span class="n">word</span><span class="p" data-group-id="5168328396-2">(</span><span class="p" data-group-id="5168328396-2">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="nc">String</span><span class="o">.</span><span class="n">t</span><span class="p" data-group-id="5168328396-3">(</span><span class="p" data-group-id="5168328396-3">)</span><span class="w">

  </span><span class="na">@spec</span><span class="w"> </span><span class="n">long_word?</span><span class="p" data-group-id="5168328396-4">(</span><span class="n">word</span><span class="p" data-group-id="5168328396-5">(</span><span class="p" data-group-id="5168328396-5">)</span><span class="p" data-group-id="5168328396-4">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">boolean</span><span class="p" data-group-id="5168328396-6">(</span><span class="p" data-group-id="5168328396-6">)</span><span class="w">
  </span><span class="kd">def</span><span class="w"> </span><span class="nf">long_word?</span><span class="p" data-group-id="5168328396-7">(</span><span class="n">word</span><span class="p" data-group-id="5168328396-7">)</span><span class="w"> </span><span class="ow">when</span><span class="w"> </span><span class="n">is_binary</span><span class="p" data-group-id="5168328396-8">(</span><span class="n">word</span><span class="p" data-group-id="5168328396-8">)</span><span class="w"> </span><span class="k" data-group-id="5168328396-9">do</span><span class="w">
    </span><span class="nc">String</span><span class="o">.</span><span class="n">length</span><span class="p" data-group-id="5168328396-10">(</span><span class="n">word</span><span class="p" data-group-id="5168328396-10">)</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">8</span><span class="w">
  </span><span class="k" data-group-id="5168328396-9">end</span><span class="w">
</span><span class="k" data-group-id="5168328396-1">end</span></code></pre>
<p>In the example above, this happens:</p>
<ul>
<li><p>we declare a new type (<code class="inline">word()</code>) that is equivalent to the string type (<code class="inline">String.t()</code>);</p>
</li>
<li><p>we specify that the <code class="inline">long_word?/1</code> function takes an argument of type <code class="inline">word()</code> and
returns a boolean (<code class="inline">boolean()</code>), that is, either <code class="inline">true</code> or <code class="inline">false</code>.</p>
</li>
</ul>
<h2 id="types-and-their-syntax" class="section-heading">
  <a href="#types-and-their-syntax" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Types and their syntax
</h2>

<p>The syntax Elixir provides for type specifications is similar to <a href="http://www.erlang.org/doc/reference_manual/typespec.html">the one in Erlang</a>. Most of the built-in types provided in Erlang (for example, <code class="inline">pid()</code>) are expressed in the same way: <code class="inline">pid()</code> (or simply <code class="inline">pid</code>). Parameterized types (such as <code class="inline">list(integer)</code>) are supported as well and so are remote types (such as <code class="inline">Enum.t</code>). Integers and atom literals are allowed as types (e.g., <code class="inline">1</code>, <code class="inline">:atom</code>, or <code class="inline">false</code>). All other types are built out of unions of predefined types. Some shorthands are allowed, such as <code class="inline">[...]</code>, <code class="inline">&lt;&lt;&gt;&gt;</code>, and <code class="inline">{...}</code>.</p>
<p>The notation to represent the union of types is the pipe <code class="inline">|</code>. For example, the typespec <code class="inline">type :: atom() | pid() | tuple()</code> creates a type <code class="inline">type</code> that can be either an <code class="inline">atom</code>, a <code class="inline">pid</code>, or a <code class="inline">tuple</code>. This is usually called a <a href="https://en.wikipedia.org/wiki/Tagged_union">sum type</a> in other languages</p>
<h3 id="basic-types" class="section-heading">
  <a href="#basic-types" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Basic types
</h3>

<pre><code class="nohighlight makeup elixir"><span class="n">type</span><span class="w"> </span><span class="o">::</span><span class="w">
      </span><span class="n">any</span><span class="p" data-group-id="8201257888-1">(</span><span class="p" data-group-id="8201257888-1">)</span><span class="w">                     </span><span class="c1"># the top type, the set of all terms</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">none</span><span class="p" data-group-id="8201257888-2">(</span><span class="p" data-group-id="8201257888-2">)</span><span class="w">                  </span><span class="c1"># the bottom type, contains no terms</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">atom</span><span class="p" data-group-id="8201257888-3">(</span><span class="p" data-group-id="8201257888-3">)</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">map</span><span class="p" data-group-id="8201257888-4">(</span><span class="p" data-group-id="8201257888-4">)</span><span class="w">                   </span><span class="c1"># any map</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">pid</span><span class="p" data-group-id="8201257888-5">(</span><span class="p" data-group-id="8201257888-5">)</span><span class="w">                   </span><span class="c1"># process identifier</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">port</span><span class="p" data-group-id="8201257888-6">(</span><span class="p" data-group-id="8201257888-6">)</span><span class="w">                  </span><span class="c1"># port identifier</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">reference</span><span class="p" data-group-id="8201257888-7">(</span><span class="p" data-group-id="8201257888-7">)</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">struct</span><span class="p" data-group-id="8201257888-8">(</span><span class="p" data-group-id="8201257888-8">)</span><span class="w">                </span><span class="c1"># any struct</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">tuple</span><span class="p" data-group-id="8201257888-9">(</span><span class="p" data-group-id="8201257888-9">)</span><span class="w">                 </span><span class="c1"># tuple of any size</span><span class="w">

                                </span><span class="c1">## Numbers</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">float</span><span class="p" data-group-id="8201257888-10">(</span><span class="p" data-group-id="8201257888-10">)</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">integer</span><span class="p" data-group-id="8201257888-11">(</span><span class="p" data-group-id="8201257888-11">)</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">neg_integer</span><span class="p" data-group-id="8201257888-12">(</span><span class="p" data-group-id="8201257888-12">)</span><span class="w">           </span><span class="c1"># ..., -3, -2, -1</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">non_neg_integer</span><span class="p" data-group-id="8201257888-13">(</span><span class="p" data-group-id="8201257888-13">)</span><span class="w">       </span><span class="c1"># 0, 1, 2, 3, ...</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">pos_integer</span><span class="p" data-group-id="8201257888-14">(</span><span class="p" data-group-id="8201257888-14">)</span><span class="w">           </span><span class="c1"># 1, 2, 3, ...</span><span class="w">

                                                    </span><span class="c1">## Lists</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">list</span><span class="p" data-group-id="8201257888-15">(</span><span class="n">type</span><span class="p" data-group-id="8201257888-15">)</span><span class="w">                                  </span><span class="c1"># proper list ([]-terminated)</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">nonempty_list</span><span class="p" data-group-id="8201257888-16">(</span><span class="n">type</span><span class="p" data-group-id="8201257888-16">)</span><span class="w">                         </span><span class="c1"># non-empty proper list</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">maybe_improper_list</span><span class="p" data-group-id="8201257888-17">(</span><span class="n">type1</span><span class="p">,</span><span class="w"> </span><span class="n">type2</span><span class="p" data-group-id="8201257888-17">)</span><span class="w">           </span><span class="c1"># proper or improper list</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">nonempty_improper_list</span><span class="p" data-group-id="8201257888-18">(</span><span class="n">type1</span><span class="p">,</span><span class="w"> </span><span class="n">type2</span><span class="p" data-group-id="8201257888-18">)</span><span class="w">        </span><span class="c1"># improper list</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="n">nonempty_maybe_improper_list</span><span class="p" data-group-id="8201257888-19">(</span><span class="n">type1</span><span class="p">,</span><span class="w"> </span><span class="n">type2</span><span class="p" data-group-id="8201257888-19">)</span><span class="w">  </span><span class="c1"># non-empty proper or improper list</span><span class="w">

      </span><span class="o">|</span><span class="w"> </span><span class="nc">Literals</span><span class="w">                </span><span class="c1"># Described in section &quot;Literals&quot;</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="nc">Builtin</span><span class="w">                 </span><span class="c1"># Described in section &quot;Built-in types&quot;</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="nc">Remotes</span><span class="w">                 </span><span class="c1"># Described in section &quot;Remote types&quot;</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="nc">UserDefined</span><span class="w">             </span><span class="c1"># Described in section &quot;User-defined types&quot;</span></code></pre>
<h3 id="literals" class="section-heading">
  <a href="#literals" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Literals
</h3>

<p>The following literals are also supported in typespecs:</p>
<pre><code class="nohighlight makeup elixir"><span class="n">type</span><span class="w"> </span><span class="o">::</span><span class="w">                               </span><span class="c1">## Atoms</span><span class="w">
      </span><span class="ss">:atom</span><span class="w">                           </span><span class="c1"># atoms: :foo, :bar, ...</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="no">true</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">false</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="no">nil</span><span class="w">            </span><span class="c1"># special atom literals</span><span class="w">

                                      </span><span class="c1">## Bitstrings</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-1">&lt;&lt;</span><span class="p" data-group-id="3826411047-1">&gt;&gt;</span><span class="w">                          </span><span class="c1"># empty bitstring</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-2">&lt;&lt;</span><span class="bp">_</span><span class="o">::</span><span class="n">size</span><span class="p" data-group-id="3826411047-2">&gt;&gt;</span><span class="w">                   </span><span class="c1"># size is 0 or a positive integer</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-3">&lt;&lt;</span><span class="bp">_</span><span class="o">::</span><span class="bp">_</span><span class="o">*</span><span class="n">unit</span><span class="p" data-group-id="3826411047-3">&gt;&gt;</span><span class="w">                 </span><span class="c1"># unit is an integer from 1 to 256</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-4">&lt;&lt;</span><span class="bp">_</span><span class="o">::</span><span class="n">size</span><span class="p">,</span><span class="w"> </span><span class="bp">_</span><span class="o">::</span><span class="bp">_</span><span class="o">*</span><span class="n">unit</span><span class="p" data-group-id="3826411047-4">&gt;&gt;</span><span class="w">

                                      </span><span class="c1">## (Anonymous) Functions</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-5">(</span><span class="o">-&gt;</span><span class="w"> </span><span class="n">type</span><span class="p" data-group-id="3826411047-5">)</span><span class="w">                     </span><span class="c1"># 0-arity, returns type</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-6">(</span><span class="n">type1</span><span class="p">,</span><span class="w"> </span><span class="n">type2</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">type</span><span class="p" data-group-id="3826411047-6">)</span><span class="w">        </span><span class="c1"># 2-arity, returns type</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-7">(</span><span class="n">...</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">type</span><span class="p" data-group-id="3826411047-7">)</span><span class="w">                 </span><span class="c1"># any arity, returns type</span><span class="w">

                                      </span><span class="c1">## Integers</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="mi">1</span><span class="w">                             </span><span class="c1"># integer</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="mi">1</span><span class="o">.</span><span class="o">.</span><span class="mi">10</span><span class="w">                         </span><span class="c1"># integer from 1 to 10</span><span class="w">

                                      </span><span class="c1">## Lists</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-8">[</span><span class="n">type</span><span class="p" data-group-id="3826411047-8">]</span><span class="w">                        </span><span class="c1"># list with any number of type elements</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-9">[</span><span class="p" data-group-id="3826411047-9">]</span><span class="w">                            </span><span class="c1"># empty list</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-10">[</span><span class="n">...</span><span class="p" data-group-id="3826411047-10">]</span><span class="w">                         </span><span class="c1"># shorthand for nonempty_list(any())</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-11">[</span><span class="n">type</span><span class="p">,</span><span class="w"> </span><span class="n">...</span><span class="p" data-group-id="3826411047-11">]</span><span class="w">                   </span><span class="c1"># shorthand for nonempty_list(type)</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-12">[</span><span class="ss">key</span><span class="p">:</span><span class="w"> </span><span class="n">value_type</span><span class="p" data-group-id="3826411047-12">]</span><span class="w">             </span><span class="c1"># keyword list with key :key of value_type</span><span class="w">

                                              </span><span class="c1">## Maps</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-13">%{</span><span class="p" data-group-id="3826411047-13">}</span><span class="w">                                   </span><span class="c1"># empty map</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-14">%{</span><span class="ss">key</span><span class="p">:</span><span class="w"> </span><span class="n">value_type</span><span class="p" data-group-id="3826411047-14">}</span><span class="w">                    </span><span class="c1"># map with required key :key of value_type</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-15">%{</span><span class="n">required</span><span class="p" data-group-id="3826411047-16">(</span><span class="n">key_type</span><span class="p" data-group-id="3826411047-16">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">value_type</span><span class="p" data-group-id="3826411047-15">}</span><span class="w">   </span><span class="c1"># map with required pairs of key_type and value_type</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-17">%{</span><span class="n">optional</span><span class="p" data-group-id="3826411047-18">(</span><span class="n">key_type</span><span class="p" data-group-id="3826411047-18">)</span><span class="w"> </span><span class="o">=</span><span class="o">&gt;</span><span class="w"> </span><span class="n">value_type</span><span class="p" data-group-id="3826411047-17">}</span><span class="w">   </span><span class="c1"># map with optional pairs of key_type and value_type</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-19">%</span><span class="nc" data-group-id="3826411047-19">SomeStruct</span><span class="p" data-group-id="3826411047-19">{</span><span class="p" data-group-id="3826411047-19">}</span><span class="w">                         </span><span class="c1"># struct with all fields of any type</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-20">%</span><span class="nc" data-group-id="3826411047-20">SomeStruct</span><span class="p" data-group-id="3826411047-20">{</span><span class="ss">key</span><span class="p">:</span><span class="w"> </span><span class="n">value_type</span><span class="p" data-group-id="3826411047-20">}</span><span class="w">          </span><span class="c1"># struct with required key :key of value_type</span><span class="w">

                                      </span><span class="c1">## Tuples</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-21">{</span><span class="p" data-group-id="3826411047-21">}</span><span class="w">                            </span><span class="c1"># empty tuple</span><span class="w">
      </span><span class="o">|</span><span class="w"> </span><span class="p" data-group-id="3826411047-22">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="n">type</span><span class="p" data-group-id="3826411047-22">}</span><span class="w">                   </span><span class="c1"># two-element tuple with an atom and any type</span></code></pre>
<h3 id="built-in-types" class="section-heading">
  <a href="#built-in-types" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Built-in types
</h3>

<p>The following types are also provided by Elixir as shortcuts on top of the basic and literal types described above.</p>
<table>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th style="text-align: left">Built-in type</th><th style="text-align: left">Defined as</th>
</tr>
</thead>
<tr>
<td style="text-align: left"><code class="inline">term()</code></td><td style="text-align: left"><code class="inline">any()</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">arity()</code></td><td style="text-align: left"><code class="inline">0..255</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">as_boolean(t)</code></td><td style="text-align: left"><code class="inline">t</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">binary()</code></td><td style="text-align: left"><code class="inline">&lt;&lt;_::_*8&gt;&gt;</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">bitstring()</code></td><td style="text-align: left"><code class="inline">&lt;&lt;_::_*1&gt;&gt;</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">boolean()</code></td><td style="text-align: left"><code class="inline">false</code> | <code class="inline">true</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">byte()</code></td><td style="text-align: left"><code class="inline">0..255</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">char()</code></td><td style="text-align: left"><code class="inline">0..0x10FFFF</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">charlist()</code></td><td style="text-align: left"><code class="inline">[char()]</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">nonempty_charlist()</code></td><td style="text-align: left"><code class="inline">[char(), ...]</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">fun()</code></td><td style="text-align: left"><code class="inline">(... -&gt; any)</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">function()</code></td><td style="text-align: left"><code class="inline">fun()</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">identifier()</code></td><td style="text-align: left"><code class="inline">pid()</code> | <code class="inline">port()</code> | <code class="inline">reference()</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">iodata()</code></td><td style="text-align: left"><code class="inline">iolist()</code> | <code class="inline">binary()</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">iolist()</code></td><td style="text-align: left"><code class="inline">maybe_improper_list(byte() | binary() | iolist(), binary() | [])</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">keyword()</code></td><td style="text-align: left"><code class="inline">[{atom(), any()}]</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">keyword(t)</code></td><td style="text-align: left"><code class="inline">[{atom(), t}]</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">list()</code></td><td style="text-align: left"><code class="inline">[any()]</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">nonempty_list()</code></td><td style="text-align: left"><code class="inline">nonempty_list(any())</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">maybe_improper_list()</code></td><td style="text-align: left"><code class="inline">maybe_improper_list(any(), any())</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">nonempty_maybe_improper_list()</code></td><td style="text-align: left"><code class="inline">nonempty_maybe_improper_list(any(), any())</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">mfa()</code></td><td style="text-align: left"><code class="inline">{module(), atom(), arity()}</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">module()</code></td><td style="text-align: left"><code class="inline">atom()</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">no_return()</code></td><td style="text-align: left"><code class="inline">none()</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">node()</code></td><td style="text-align: left"><code class="inline">atom()</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">number()</code></td><td style="text-align: left"><code class="inline">integer()</code> | <code class="inline">float()</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">struct()</code></td><td style="text-align: left"><code class="inline">%{:__struct__ =&gt; atom(), optional(atom()) =&gt; any()}</code></td>
</tr>
<tr>
<td style="text-align: left"><code class="inline">timeout()</code></td><td style="text-align: left"><code class="inline">:infinity</code> | <code class="inline">non_neg_integer()</code></td>
</tr>
</table>
<h3 id="remote-types" class="section-heading">
  <a href="#remote-types" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Remote types
</h3>

<p>Any module is also able to define its own types and the modules in Elixir are no exception. For example, the <a href="Range.html"><code class="inline">Range</code></a> module defines a <code class="inline">t/0</code> type that represents a range: this type can be referred to as <a href="Range.html#t:t/0"><code class="inline">Range.t/0</code></a>. In a similar fashion, a string is <a href="String.html#t:t/0"><code class="inline">String.t/0</code></a>, any enumerable can be <a href="Enum.html#t:t/0"><code class="inline">Enum.t/0</code></a>, and so on.</p>
<h3 id="maps" class="section-heading">
  <a href="#maps" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Maps
</h3>

<p>The key types in maps are allowed to overlap, and if they do, the leftmost key takes precedence.
A map value does not belong to this type if it contains a key that is not in the allowed map keys.</p>
<p>If you want to denote that keys that were not previously defined in the map are allowed,
it is common to end a map type with <code class="inline">optional(any) =&gt; any</code>.</p>
<p>Notice that the syntactic representation of <code class="inline">map()</code> is <code class="inline">%{optional(any) =&gt; any}</code>, not <code class="inline">%{}</code>. The notation <code class="inline">%{}</code> specifies the singleton type for the empty map.</p>
<h3 id="user-defined-types" class="section-heading">
  <a href="#user-defined-types" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  User-defined types
</h3>

<p>The <code class="inline">@type</code>, <code class="inline">@typep</code>, and <code class="inline">@opaque</code> module attributes can be used to define new types:</p>
<pre><code class="nohighlight makeup elixir"><span class="na">@type</span><span class="w"> </span><span class="n">type_name</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">type</span><span class="w">
</span><span class="na">@typep</span><span class="w"> </span><span class="n">type_name</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">type</span><span class="w">
</span><span class="na">@opaque</span><span class="w"> </span><span class="n">type_name</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">type</span></code></pre>
<p>A type defined with <code class="inline">@typep</code> is private. An opaque type, defined with <code class="inline">@opaque</code> is a type where the internal structure of the type will not be visible, but the type is still public.</p>
<p>Types can be parameterized by defining variables as parameters; these variables can then be used to define the type.</p>
<pre><code class="nohighlight makeup elixir"><span class="na">@type</span><span class="w"> </span><span class="n">dict</span><span class="p" data-group-id="1184363239-1">(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">value</span><span class="p" data-group-id="1184363239-1">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="p" data-group-id="1184363239-2">[</span><span class="p" data-group-id="1184363239-3">{</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">value</span><span class="p" data-group-id="1184363239-3">}</span><span class="p" data-group-id="1184363239-2">]</span></code></pre>
<h2 id="defining-a-specification" class="section-heading">
  <a href="#defining-a-specification" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Defining a specification
</h2>

<p>A specification for a function can be defined as follows:</p>
<pre><code class="nohighlight makeup elixir"><span class="na">@spec</span><span class="w"> </span><span class="n">function_name</span><span class="p" data-group-id="0967484576-1">(</span><span class="n">type1</span><span class="p">,</span><span class="w"> </span><span class="n">type2</span><span class="p" data-group-id="0967484576-1">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">return_type</span></code></pre>
<p>Guards can be used to restrict type variables given as arguments to the function.</p>
<pre><code class="nohighlight makeup elixir"><span class="na">@spec</span><span class="w"> </span><span class="n">function</span><span class="p" data-group-id="4840555988-1">(</span><span class="n">arg</span><span class="p" data-group-id="4840555988-1">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="p" data-group-id="4840555988-2">[</span><span class="n">arg</span><span class="p" data-group-id="4840555988-2">]</span><span class="w"> </span><span class="ow">when</span><span class="w"> </span><span class="ss">arg</span><span class="p">:</span><span class="w"> </span><span class="n">atom</span></code></pre>
<p>If you want to specify more than one variable, you separate them by a comma.</p>
<pre><code class="nohighlight makeup elixir"><span class="na">@spec</span><span class="w"> </span><span class="n">function</span><span class="p" data-group-id="7605829973-1">(</span><span class="n">arg1</span><span class="p">,</span><span class="w"> </span><span class="n">arg2</span><span class="p" data-group-id="7605829973-1">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="p" data-group-id="7605829973-2">{</span><span class="n">arg1</span><span class="p">,</span><span class="w"> </span><span class="n">arg2</span><span class="p" data-group-id="7605829973-2">}</span><span class="w"> </span><span class="ow">when</span><span class="w"> </span><span class="ss">arg1</span><span class="p">:</span><span class="w"> </span><span class="n">atom</span><span class="p">,</span><span class="w"> </span><span class="ss">arg2</span><span class="p">:</span><span class="w"> </span><span class="n">integer</span></code></pre>
<p>Type variables with no restriction can also be defined.</p>
<pre><code class="nohighlight makeup elixir"><span class="na">@spec</span><span class="w"> </span><span class="n">function</span><span class="p" data-group-id="4928453743-1">(</span><span class="n">arg</span><span class="p" data-group-id="4928453743-1">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="p" data-group-id="4928453743-2">[</span><span class="n">arg</span><span class="p" data-group-id="4928453743-2">]</span><span class="w"> </span><span class="ow">when</span><span class="w"> </span><span class="ss">arg</span><span class="p">:</span><span class="w"> </span><span class="n">var</span></code></pre>
<p>You can also name your arguments in a typespec using <code class="inline">arg_name :: arg_type</code> syntax. This is particularly useful in documentation as a way to differentiate multiple arguments of the same type (or multiple elements of the same type in a type definition):</p>
<pre><code class="nohighlight makeup elixir"><span class="na">@spec</span><span class="w"> </span><span class="n">days_since_epoch</span><span class="p" data-group-id="3193970778-1">(</span><span class="n">year</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">integer</span><span class="p">,</span><span class="w"> </span><span class="n">month</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">integer</span><span class="p">,</span><span class="w"> </span><span class="n">day</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">integer</span><span class="p" data-group-id="3193970778-1">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">integer</span><span class="w">
</span><span class="na">@type</span><span class="w"> </span><span class="n">color</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="p" data-group-id="3193970778-2">{</span><span class="n">red</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">integer</span><span class="p">,</span><span class="w"> </span><span class="n">green</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">integer</span><span class="p">,</span><span class="w"> </span><span class="n">blue</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">integer</span><span class="p" data-group-id="3193970778-2">}</span></code></pre>
<p>Specifications can be overloaded just like ordinary functions.</p>
<pre><code class="nohighlight makeup elixir"><span class="na">@spec</span><span class="w"> </span><span class="n">function</span><span class="p" data-group-id="7891682296-1">(</span><span class="n">integer</span><span class="p" data-group-id="7891682296-1">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">atom</span><span class="w">
</span><span class="na">@spec</span><span class="w"> </span><span class="n">function</span><span class="p" data-group-id="7891682296-2">(</span><span class="n">atom</span><span class="p" data-group-id="7891682296-2">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">integer</span></code></pre>
<h2 id="behaviours" class="section-heading">
  <a href="#behaviours" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Behaviours
</h2>

<p>Behaviours in Elixir (and Erlang) are a way to separate and abstract the generic part of a component (which becomes the <em>behaviour module</em>) from the specific part (which becomes the <em>callback module</em>).</p>
<p>A behaviour module defines a set of functions and macros (referred to as <em>callbacks</em>) that callback modules implementing that behaviour must export. This “interface” identifies the specific part of the component. For example, the <a href="GenServer.html"><code class="inline">GenServer</code></a> behaviour and functions abstract away all the message-passing (sending and receiving) and error reporting that a “server” process will likely want to implement from the specific parts such as the actions that this server process has to perform.</p>
<p>To define a behaviour module, it’s enough to define one or more callbacks in that module. To define callbacks, the <code class="inline">@callback</code> and <code class="inline">@macrocallback</code> module attributes can be used (for function callbacks and macro callbacks respectively).</p>
<pre><code class="nohighlight makeup elixir"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">MyBehaviour</span><span class="w"> </span><span class="k" data-group-id="4820744073-1">do</span><span class="w">
  </span><span class="na">@callback</span><span class="w"> </span><span class="n">my_fun</span><span class="p" data-group-id="4820744073-2">(</span><span class="n">arg</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">any</span><span class="p" data-group-id="4820744073-2">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">any</span><span class="w">
  </span><span class="na">@macrocallback</span><span class="w"> </span><span class="n">my_macro</span><span class="p" data-group-id="4820744073-3">(</span><span class="n">arg</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">any</span><span class="p" data-group-id="4820744073-3">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="nc">Macro</span><span class="o">.</span><span class="n">t</span><span class="w">
</span><span class="k" data-group-id="4820744073-1">end</span></code></pre>
<p>As seen in the example above, defining a callback is a matter of defining a specification for that callback, made of:</p>
<ul>
<li>the callback name (<code class="inline">my_fun</code> or <code class="inline">my_macro</code> in the example)
</li>
<li>the arguments that the callback must accept (<code class="inline">arg :: any</code> in the example)
</li>
<li>the <em>expected</em> type of the callback return value
</li>
</ul>
<h3 id="optional-callbacks" class="section-heading">
  <a href="#optional-callbacks" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Optional callbacks
</h3>

<p>Optional callbacks are callbacks that callback modules may implement if they want to, but are not required to. Usually, behaviour modules know if they should call those callbacks based on configuration, or they check if the callbacks are defined with <a href="Kernel.html#function_exported?/3"><code class="inline">function_exported?/3</code></a> or <a href="Kernel.html#macro_exported?/3"><code class="inline">macro_exported?/3</code></a>.</p>
<p>Optional callbacks can be defined through the <code class="inline">@optional_callbacks</code> module attribute, which has to be a keyword list with function or macro name as key and arity as value. For example:</p>
<pre><code class="nohighlight makeup elixir"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">MyBehaviour</span><span class="w"> </span><span class="k" data-group-id="2971682302-1">do</span><span class="w">
  </span><span class="na">@callback</span><span class="w"> </span><span class="n">vital_fun</span><span class="p" data-group-id="2971682302-2">(</span><span class="p" data-group-id="2971682302-2">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">any</span><span class="w">
  </span><span class="na">@callback</span><span class="w"> </span><span class="n">non_vital_fun</span><span class="p" data-group-id="2971682302-3">(</span><span class="p" data-group-id="2971682302-3">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">any</span><span class="w">
  </span><span class="na">@macrocallback</span><span class="w"> </span><span class="n">non_vital_macro</span><span class="p" data-group-id="2971682302-4">(</span><span class="n">arg</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">any</span><span class="p" data-group-id="2971682302-4">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="nc">Macro</span><span class="o">.</span><span class="n">t</span><span class="w">
  </span><span class="na">@optional_callbacks</span><span class="w"> </span><span class="ss">non_vital_fun</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="ss">non_vital_macro</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="w">
</span><span class="k" data-group-id="2971682302-1">end</span></code></pre>
<p>One example of optional callback in Elixir’s standard library is <a href="GenServer.html#c:format_status/2"><code class="inline">GenServer.format_status/2</code></a>.</p>
<h3 id="implementing-behaviours" class="section-heading">
  <a href="#implementing-behaviours" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  Implementing behaviours
</h3>

<p>To specify that a module implements a given behaviour, the <code class="inline">@behaviour</code> attribute must be used:</p>
<pre><code class="nohighlight makeup elixir"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">MyBehaviour</span><span class="w"> </span><span class="k" data-group-id="4372280087-1">do</span><span class="w">
  </span><span class="na">@callback</span><span class="w"> </span><span class="n">my_fun</span><span class="p" data-group-id="4372280087-2">(</span><span class="n">arg</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">any</span><span class="p" data-group-id="4372280087-2">)</span><span class="w"> </span><span class="o">::</span><span class="w"> </span><span class="n">any</span><span class="w">
</span><span class="k" data-group-id="4372280087-1">end</span><span class="w">

</span><span class="kd">defmodule</span><span class="w"> </span><span class="nc">MyCallbackModule</span><span class="w"> </span><span class="k" data-group-id="4372280087-3">do</span><span class="w">
  </span><span class="na">@behaviour</span><span class="w"> </span><span class="nc">MyBehaviour</span><span class="w">
  </span><span class="kd">def</span><span class="w"> </span><span class="nf">my_fun</span><span class="p" data-group-id="4372280087-4">(</span><span class="n">arg</span><span class="p" data-group-id="4372280087-4">)</span><span class="p">,</span><span class="w"> </span><span class="ss">do</span><span class="p">:</span><span class="w"> </span><span class="n">arg</span><span class="w">
</span><span class="k" data-group-id="4372280087-3">end</span></code></pre>
<p>If a callback module that implements a given behaviour doesn’t export all the functions and macros defined by that behaviour, the user will be notified through warnings during the compilation process (no errors will happen).</p>
<p>Elixir’s standard library contains a few frequently used behaviours such as <a href="GenServer.html"><code class="inline">GenServer</code></a>, <a href="Supervisor.html"><code class="inline">Supervisor</code></a>, and <a href="Application.html"><code class="inline">Application</code></a>.</p>
<h2 id="the-string-type" class="section-heading">
  <a href="#the-string-type" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
  The <code class="inline">string()</code> type
</h2>

<p>Elixir discourages the use of the <code class="inline">string()</code> type. The <code class="inline">string()</code> type refers to Erlang strings, which are known as “charlists” in Elixir. They do not refer to Elixir strings, which are UTF-8 encoded binaries. To avoid confusion, if you attempt to use the type <code class="inline">string()</code>, Elixir will emit a warning. You should use <code class="inline">charlist()</code>, <code class="inline">binary()</code> or <code class="inline">String.t()</code> accordingly.</p>
<p>Note <code class="inline">String.t()</code> and <code class="inline">binary()</code> are equivalent to analysis tools. Although, for those reading the documentation, <code class="inline">String.t()</code> implies it is a UTF-8 encoded binary.</p>
      <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>