# Erlang and Elixir, Part 3: Functions

Elixir is built on Erlang, and in both Erlang and Elixir a function is not just identified by its name, but by its name and arity.  Remember: Everything in Elixir is an expression.

## Erlang and Elixir, Part 3: Functions

To give you a clear example of this, below we have four functions, but all defined with different arity.

``````def sum, do: 0
def sum(a), do: a
def sum(a, b), do: a + b
def sum(a, b, c), do: a + b + c``````

To provide a concise way to work with data, we can use guard expressions like so:

``````def sum(a, b) when is_integer(a) and is_integer(b) do
a + b
end

def sum(a, b) when is_list(a) and is_list(b) do
a ++ b
end

def sum(a, b) when is_binary(a) and is_binary(b) do
a <> b
end

sum 1, 2
#=> 3

sum , 
#=> [1, 2]

sum "a", "b"
#=> "ab"``````

Guard expressions such as `when is_binary(a)` allow us to check for the correct type before performing an operation.

Unlike Erlang, Elixir allows for default values in its functions via usage of the `\` syntax like so:

``````def mul_by(x, n \ 2) do
x * n
end

mul_by 4, 3 #=> 12
mul_by 4    #=> 8``````

## Anonymous Functions

In the previous part, we discussed anonymous functions briefly as a data type. To elaborate on this further, take this example:

``````sum = fn(a, b) -> a + b end
sum.(4, 3)
#=> 7

square = fn(x) -> x * x end
Enum.map [1, 2, 3, 4], square
#=> [1, 4, 9, 16]``````

We see this powerful shorthand here on the first line `fn(a, b) -> a + b end`. With this we are able to produce a basic operation `sum.(4, 3)` and get the output in just two lines of code.

Now, looking to the square method, `fn(x) -> x * x end`, can it really be any simpler? Working now with the `map`, we can perform the square anonymous function over the whole map—again in just two lines of code!

## Pattern Matching

Arithmetic is all fun and good, but let’s see what we can do with text.

``````f = fn
{:simon} = tuple ->
IO.puts "Good morning Sir #{inspect tuple}"
{:kate} = tuple ->
IO.puts "Lovely day #{inspect tuple}"
[] ->
"Empty"
end

f.([])
#=> "Empty"

f.({:simon})
#=> "Good morning Sir {:simon}"

f.({:kate})
#=> "Lovely day {:kate}"``````

Here, with pattern matching we can define several outcomes in our control flow, again in hardly any code. Elixir’s syntax is rapid to work with and mightily powerful, as we will see in the next example.

## First-Class Functions

The anonymous functions we just covered are first-class values. This means that they can be passed as arguments to other functions and also can serve as a return value themselves. There is a special syntax to work with named functions in the same way:

``````defmodule Math do
def square(x) do
x * x
end
end

Enum.map [1, 2, 3], &Math.square/1
#=> [1, 4, 9]``````

Here we define a `Math` module with `defmodule` and define the square function. Then we can use this in conjunction with the map method demonstrated earlier and the `Math` module we just defined. We use the same operator `&`, allowing us to pass our function `Math.square/1` to capture the square function’s output for each entry in our list.

That’s a whole lot of power for just one line. This is referred to as a partial function capture in Elixir.

## Control Flow

We use the constructs `if` and `case` to control flow in Elixir. Like everything in Elixir, `if` and `case` are expressions.

For pattern matching, we use `case`:

``````case {x, y} do
{:a, :b} -> :ok
{:b, :c} -> :good
other -> other
end``````

And for comparison logic, we use `if`:

``````test_fun = fn(x) ->
cond do
x > 10 ->
:greater_than_ten
x < 10 and x > 0 ->
:less_than_ten_positive
x < 0 or x === 0 ->
:zero_or_negative
true ->
:exactly_ten
end
end

test_fun.(44)
#=> :greater_than_ten

test_fun.(0)
#=> :zero_or_negative

test_fun.(10)
#=> :exactly_ten``````

For ease of use, Elixir also provides an `if` function that resembles many other languages and is useful when you need to check if one clause is true or false:

``````if x > 10 do
:greater_than_ten
else
:not_greater_than_ten
end``````

## Dynamic Functions

This is possible in Elixir via usage of the `unquote` method mentioned earlier. For example, to check some hard-coded Admins in our system, we can do the following:

``````defmodule Admins do
[:manager, :super] |> Enum.each fn level ->
def unquote(:"check_#{level}")() do
IO.inspect("Access Level: #{unquote(level)}")
end
end
end

Admins.check_manager  # => "Access Level: manager"
Admins.check_super    # => "Access Level: super"``````

Here we have created the methods `Admins.check_manager` and `Admins.check_super` from the atom names.

## Conclusion

Everything is an expression in Elixir, and that means we can get a whole heap of power out of writing very little code.

For me, Elixir looks similar to CoffeeScript, Ruby, Python or any minimalist syntax as the form is so direct and to the point, but Elixir is far more powerful than these languages due to the meta-programming aspect.

Going forward, we will see how to utilise control flow and functions more to create interactivity in our app.