Default Parameters

When you define a named function, you can give a default value to any of its parameters by using the syntax param \\ value. When you call a function that is defined with default parameters, Elixir compares the number of arguments you are passing with the number of required parameters for the function. If you’re passing fewer arguments than the number of required parameters, then there’s no match. If the two numbers are equal, then the required parameters take the values of the passed arguments, and the other parameters take their default values. If the count of passed arguments is greater than the number of required parameters, Elixir uses the excess to override the default values of some or all parameters. Parameters are matched left to right.

mm/default_params.exs
 defmodule​ Example ​do
 def​ func(p1, p2 \\ 2, p3 \\ 3, p4) ​do
  IO.inspect [p1, p2, p3, p4]
 end
 end
 
 Example.func(​"​​a"​, ​"​​b"​) ​# => ["a",2,3,"b"]
 Example.func(​"​​a"​, ​"​​b"​, ​"​​c"​) ​# => ["a","b",3,"c"]
 Example.func(​"​​a"​, ​"​​b"​, ​"​​c"​, ​"​​d"​) ​# => ["a","b","c","d"]

Default arguments can behave surprisingly when Elixir does pattern matching. For example, compile the following:

 def​ func(p1, p2 \\ 2, p3 \\ 3, p4) ​do
  IO.inspect [p1, p2, p3, p4]
 end
 
 def​ func(p1, p2) ​do
  IO.inspect [p1, p2]
 end

and you’ll get this error:

 ** (CompileError) default_params.exs:7: def func/2 conflicts with
  defaults from def func/4

That’s because the first function definition (with the default parameters) matches any call with two, three, or four arguments.

There’s one more thing with default parameters. Here’s a function with multiple heads that also has a default parameter:

mm/default_params1.exs
 defmodule​ DefaultParams1 ​do
 
 def​ func(p1, p2 \\ 123) ​do
  IO.inspect [p1, p2]
 end
 
 def​ func(p1, 99) ​do
  IO.puts ​"​​you said 99"
 end
 
 end

If you compile this, you’ll get an error:

 warning: definitions with multiple clauses and default values require a
 function head. Instead of this:
 
  def foo(:first_clause, b \\ :default) do ... end
  def foo(:second_clause, b) do ... end
 
 one should write this:
 
  def foo(a, b \\ :default)
  def foo(:first_clause, b) do ... end
  def foo(:second_clause, b) do ... end
 
 def func/2 has multiple clauses and defines defaults in a clause with a body
  code/mm/default_params1.exs:8
 
 warning: variable p1 is unused
  code/mm/default_params1.exs:8
 
 warning: this clause cannot match because a previous clause at
  line 4 always matches code/mm/default_params1.exs:8

The intent is to reduce confusion that can arise with defaults. Add a function head with no body that contains the default parameters, and use regular parameters for the rest. The defaults will apply to all calls to the function.

mm/default_params2.exs
 defmodule​ Params ​do
 
 def​ func(p1, p2 \\ 123)
 
 def​ func(p1, p2) ​when​ is_list(p1) ​do
 "​​You said ​​#{​p2​}​​ with a list"
 end
 
 def​ func(p1, p2) ​do
 "​​You passed in ​​#{​p1​}​​ and ​​#{​p2​}​​"
 end
 
 end
 
 IO.puts Params.func(99) ​# You passed in 99 and 123
 IO.puts Params.func(99, ​"​​cat"​) ​# You passed in 99 and cat
 IO.puts Params.func([99]) ​# You said 123 with a list
 IO.puts Params.func([99], ​"​​dog"​) ​# You said dog with a list