5

I have following elixir code snippet:

defmodule Rectangle do

    def area(a, b) do
        a * b
    end

    def area(a) do
        a * a
    end

end

Then I load the file into iex session as follow:

iex(1)> import_file "rectangle.exs"
{:module, Rectangle,
 <<70, 79, 82, 49, 0, 0, 5, 84, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 204, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 4, 104, 2, ...>>,
 {:area, 1}}

It works fine like I expected

iex(2)> Rectangle.area(9)
81

Now I want to assign the area function with arity 1 to anonymous function like:

iex(3)> fun = Rectangle.area/1
** (UndefinedFunctionError) undefined function Rectangle.area/0
    Rectangle.area()

But when I typed like:

iex(3)> fun = &Rectangle.area/1
&Rectangle.area/1

Then it works. Why do elixir expect & in front of the function name, although Rectangle.area is already a function?

Onorio Catenacci
  • 14,928
  • 14
  • 81
  • 132
softshipper
  • 32,463
  • 51
  • 192
  • 400
  • 1
    It's a just syntax thing - it kind of says to the interpreter a "pointer to a function" is coming up not an algebraic expression (e.g a malformed division by 1). Remember Elixir is doing "acrobatics" to maintain compatibility with Erlang - so a few compromises have to be made - I think. – GavinBrelstaff Feb 16 '16 at 20:59
  • 3
    @GavinBrelstaff This is actually for 2 reasons. The first is because in Elixir syntax, parens are optional, referring to a function will just invoke it, unless you use `&` to denote the named function and arity (the number of arguments it takes). The second reason is that Elixir isn't doing any acrobatics to maintain compatibility with Erlang, it just assumes all of Erlang's semantics. And in the Beam VM, a function is identified by name and arity. The same name with 2 arities is actually 2 different functions. – asonge Feb 16 '16 at 23:17
  • thanks asonge - I'm here to learn too! Still IMO allowing parentheses to be optional where-ever you can is great for us users, but challenging for the guy who maintain the language, "acrobatics" or not. – GavinBrelstaff Feb 17 '16 at 07:07
  • Good explanation about the different kinds of function can look at this [answer](http://stackoverflow.com/questions/18011784/why-are-there-two-kinds-of-functions-in-elixir) – jimmbraddock Feb 17 '16 at 14:12

1 Answers1

8

It is because that's how the compiler parses an anonymous function.

Rectangle.area/1 would parse as a division of Rectangle.area to 1 (hence the undefined function Rectangle.area/0 error).

You can see how an expression is parsed using quote:

iex> quote do &Rectangle.area/1 end
iex> quote do Rectangle.area/1 end
zaboco
  • 2,798
  • 1
  • 20
  • 16
  • What does division means in connection with function? – softshipper Feb 17 '16 at 06:18
  • @zero_coding, that's arity - https://erlangcentral.org/wiki/index.php?title=Arity – arathunku Feb 17 '16 at 06:23
  • @zero_coding, the division is not applied on the function, but on the value returned by the function. In Elixir (like in Ruby), parentheses are optional for no-arg functions: `Rectangle.area` is the same as `Rectangle.area()`. So the compiler tries to find a function `area` with no args in `Rectangle` and apply it. The other form, `&Rectangle.area/1` tells the compiler to search for for a function `Rectangle.area` with one argument, or with arity 1, as @arathunku pointed out. – zaboco Feb 17 '16 at 07:28