Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Just to clarify the naming, they are both functions. One is a named function and the other is an anonymous one. But you are right, they work somewhat differently and I am going to illustrate why they work like that.</p> <p>Let's start with the second, <code>fn</code>. <code>fn</code> is a closure, similar to a <code>lambda</code> in Ruby. We can create it as follows:</p> <pre><code>x = 1 fun = fn y -&gt; x + y end fun.(2) #=&gt; 3 </code></pre> <p>A function can have multiple clauses too:</p> <pre><code>x = 1 fun = fn y when y &lt; 0 -&gt; x - y y -&gt; x + y end fun.(2) #=&gt; 3 fun.(-2) #=&gt; 3 </code></pre> <p>Now, let's try something different. Let's try to define different clauses expecting a different number of arguments:</p> <pre><code>fn x, y -&gt; x + y x -&gt; x end ** (SyntaxError) cannot mix clauses with different arities in function definition </code></pre> <p>Oh no! We get an error! We cannot mix clauses that expects a different number of arguments. A function always has a fixed arity.</p> <p>Now, let's talk about the named functions:</p> <pre><code>def hello(x, y) do x + y end </code></pre> <p>As expected, they have a name and they can also receive some arguments. However, they are not closures:</p> <pre><code>x = 1 def hello(y) do x + y end </code></pre> <p>This code will fail to compile because every time you see a <code>def</code>, you get an empty variable scope. That is an important difference between them. I particularly like the fact each named function starts with a clean slate and you don't get the variables of different scopes all mixed up together. You have a clear boundary.</p> <p>We could retrieve the named hello function above as an anonymous function. You mentioned about it yourself:</p> <pre><code>other_function(&amp;hello(&amp;1)) </code></pre> <p>And then you asked, why I cannot simply pass it as <code>hello</code> as in other languages? That's because functions in Elixir are identified by name <strong>and</strong> arity. So a function that expects two arguments is a different function than one that expects three, even if they had the same name. So if we simply passed <code>hello</code>, we would have no idea which <code>hello</code> you actually meant. The one with two, three or four arguments? This is exactly the same reason why we can't create an anonymous function with clauses with different arities.</p> <p>Since Elixir v0.10.1, we have a syntax to capture named functions:</p> <pre><code>&amp;hello/1 </code></pre> <p>That will capture the local named function hello with arity 1. Throughout the language and its documentation, it is very common to identify functions in this <code>hello/1</code> syntax.</p> <p>This is also why Elixir uses a dot for calling anonymous functions. Since you can't simply pass <code>hello</code> around as a function, instead you need to explicitly capture it, there is a natural distinction between named and anonymous functions and a distinct syntax for calling each makes everything a bit more explicit (Lispers would be familiar with this due to the Lisp 1 vs. Lisp 2 discussion).</p> <p>Overall, those are the reasons why we have two functions and why they behave differently.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload