5

I have created a module that looks as follow:

defmodule Sum do

    def sum(x,y) do
        x + y
    end

    def sum(x) do
        x
    end

end

and it works as I expected with pattern matching of course:

iex(2)> Sum.sum(3)
3
iex(3)> Sum.sum(3,5)
8

When I define an anonymous function like:

iex(1)> sum = fn
...(1)>  x, y -> x + y
...(1)>  x -> x
...(1)> end
** (CompileError) iex:1: cannot mix clauses with different arities in function definition

then the compiler complain. Why I can not mix with different arities, the example above with module it works like a charm.

softshipper
  • 32,463
  • 51
  • 192
  • 400

2 Answers2

11

sum/2 and sum/1 are actually 2 different functions. The one that gets executed isn't chosen by pattern matching. The compiler knows which one to call based on how many arguments you specified.

As others have noted, an anonymous function may have different clauses, but they must have the same arity because you are just creating a single function.

Consider the following code:

defmodule Sum do

    def sum(x,y) where is_integer(y) do
        x + y
    end

    def sum(x,_) do
        x
    end

end

This creates 2 clauses of the single sum/2 function and which one is called will be determined by pattern matching and the guard clause like this:

iex> Sum.sum(3,nil)
3
iex> Sum.sum(3,5)
8
iex> Sum.sum(5,:foo)
5

You would be able to do the same thing with an anonymous function.

CoderDennis
  • 13,642
  • 9
  • 69
  • 105
  • I wish I knew what the downvoter was thinking. I'm not saying you should write a function like this `sum/2`. It's purely an example based on what was in the question to make a point. There are also optional parameters, which would probably be better in practice than what's shown here if you needed to use `sum/2` with either one or two arguments, but I felt that would be confusing. – CoderDennis Feb 18 '16 at 16:23
1

Take a look at this prior answer:

https://stackoverflow.com/a/18023790/2820

It discusses exactly your question. You can have multiple clauses in a lambda but the clauses all have to match in arity.

Community
  • 1
  • 1
Onorio Catenacci
  • 14,928
  • 14
  • 81
  • 132