Elixir Functions

Welcome to a tutorial on Elixir. Here you will learn about Functions in Elixir.

In general, a function is a set of statements organized together to perform a specific task. Programming functions are similar in action to functions in math. When you give functions input they generate output based on the input provided.

 

In Elixir, there are two types of functions.

  • Anonymous function: This type of function defined by using the fn..end construct are anonymous functions. Also, these functions are sometimes called lambdas and are used by assigning them to variable names.
  • Named function: These functions defined by using the def keyword are named functions. They are native functions provided in Elixir.

Now let’s discuss these functions in detail with examples.

 

Anonymous Functions

These functions are anonymous functions, meaning that they don't have a name. They are frequently passed to other functions. 

In order to define an anonymous function in Elixir, the fn and end keywords are needed. Also, within these, we can define any number of parameters and function bodies separated by ->. Check out the example below.

sum = fn (a, b) -> a + b end
IO.puts(sum.(1, 5))

The output is:

6

NOTE: These functions are not called like the named functions, as there is a '.' between the function name and its arguments.

 

Using the Capture Operator

Also, we can define these functions using the capture operator. It is an easier method to create functions. After which we will define the above sum function using the capture operator, as shown below

sum = &(&1 + &2) 
IO.puts(sum.(1, 2))

The output is:

3

In the shorthand version, our parameters are not named but are available to us as &1, &2, &3, etc.

 

Pattern Matching Functions

In Elixir, Pattern matching is not only limited to variables and data structures, as we can use pattern matching to make our functions polymorphic. For instance, we can declare a function that can either take 1 or 2 inputs (within a tuple) and print them to the console, as shown below.

handle_result = fn
   {var1} -> IO.puts("#{var1} found in a tuple!")
   {var_2, var_3} -> IO.puts("#{var_2} and #{var_3} found!")
end
handle_result.({"Hey people"})
handle_result.({"Hello", "World"})

The output is:

Hey people found in a tuple!
Hello and World found!

 

Named Functions

In this case, we can define functions with names to easily refer to them later. Named functions are defined within a module by making use of the def keyword. Also, they are always defined in a module. To call named functions, we need to reference them by just making use of their module name.

The syntax for named functions is:

def function_name(argument_1, argument_2) do   

   #code to be executed when function is called

end

 

Now, let’s define our named function sum within the Math module.

defmodule Math do
   def sum(a, b) do
      a + b
   end
end

IO.puts(Math.sum(5, 6))

The output is:

11

For 1-liner functions, we have a shorthand notation to define these functions, using do:. Check out the example below:

defmodule Math do
   def sum(a, b), do: a + b
end
IO.puts(Math.sum(5, 6))

The output is:

11

 

Private Functions

Elixir provides developers the ability to define private functions that can be accessed from within the module in which they are defined. The  defp function is used to define a private function, rather than the def function. Check out the example below.

defmodule Greeter do
   def hello(name), do: phrase <> name
   defp phrase, do: "Hello "
end

Greeter.hello("world")

The output is:

Hello world

But if we try to explicitly call the phrase function, by using the Greeter.phrase() function, an error will be raised.

 

Default arguments

In this case, if we want a default value for an argument, the argument value is used. The syntax is shown below.

defmodule Greeter do
   def hello(name, country  "en") do
      phrase(country) <> name
   end

   defp phrase("en"), do: "Hello, "
   defp phrase("es"), do: "Hola, "
end

Greeter.hello("Alex", "en")
Greeter.hello("Justin")
Greeter.hello("Mike", "es")

And when the above code is run, the output is:

Hello, Alex
Hello, Justin
Hola, Mike