Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Anonymous function cannot mix clauses

Tags:

elixir

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.

like image 608
softshipper Avatar asked Feb 17 '16 20:02

softshipper


People also ask

What are the advantages of anonymous functions?

The advantage of an anonymous function is that it does not have to be stored in a separate file. This can greatly simplify programs, as often calculations are very simple and the use of anonymous functions reduces the number of code files necessary for a program.

What is an anonymous function in Elixir?

Just as the name implies, an anonymous function has no name. As we saw in the Enum lesson, these are frequently passed to other functions. To define an anonymous function in Elixir we need the fn and end keywords. Within these we can define any number of parameters and function bodies separated by -> .

How do you define a function in Elixir?

We can define functions with names so we can easily refer to them later. Named functions are defined within a module using the def keyword. Named functions are always defined in a module. To call named functions, we need to reference them using their module name.


2 Answers

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.

like image 137
CoderDennis Avatar answered Sep 23 '22 10:09

CoderDennis


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.

like image 30
Onorio Catenacci Avatar answered Sep 19 '22 10:09

Onorio Catenacci