links: Functions in Elixir


Default Arguments

Named functions in Elixir supports default arguments

defmodule Concat do
  def join(a, b, sep \\ " ") do
    a <> sep <> b
  end
end
 
IO.puts Concat.join("Hello", "world")      #=> Hello world
IO.puts Concat.join("Hello", "world", "_") #=> Hello_world

Any expression is allowed to serve as a default value, but it won’t be evaluated during the function definition. Every time the function is invoked and any of it’s default values have to be used, the expression for that default value will be evaluated

defmodule Test do
  def dowork(x \\ "hello") do
    x
  end
end
 
IO.puts Test.dowork #=> hello
IO.puts Test.dowork 123 #=> 123
IO.puts Test.dowork #=> hello

If a function with multiple clauses has default values, it is required to create a function head(a function definition without a body) for declaring defaults

defmodule Concat do
  # A function head declaring defaults
  def join(a, b \\ nil, sep \\ " ")
 
  def join(a, b, _sep) when is_nil(b) do
    a
  end
 
  def join(a, b, sep) do
    a <> sep <> b
  end
end
 
IO.puts Concat.join("Hello", "world")      #=> Hello world
IO.puts Concat.join("Hello", "world", "_") #=> Hello_world
IO.puts Concat.join("Hello")               #=> Hello

When using default values, one must be careful to avoid overlapping function definitions. consider the following example:

defmodule Concat do
  def join(a, b) do
    IO.puts "***First join"
    a <> b
  end
 
  def join(a, b, sep \\ " ") do
    IO.puts "***Second join"
    a <> sep <> b
  end
end

Elixir will emit the following warning

concat.ex:7: warning: this clause cannot match because a previous clause at line 2 always matches

The compiler is telling us that invoking the join function with two arguments will always choose the first definition of join whereas the second one is only invoked when three arguments are passed.

Removing the default argument, in this case, will fix the warning.

  • Any expression can serve as the default value
  • Anonymous functions cannot have the default arguments

tags: elixir function sources: