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.
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"]
The trick here is that for functions with default arguments the compiler actually generates multiple functions, one for specific number of arguments. So for you func example:
defmodule Example do
def func(p1, p2 \\ 2, p3 \\ 3, p4) do
IO.inspect [p1, p2, p3, p4]
end
end
You will actually get a module which looks something like:
defmodule Example do
def func(p1, p4) do
func(p1, 2, 3, p4)
end
def func(p1, p2, p4) do
func(p1, p2, 3, p4)
end
def func(p1, p2, p3, p4) do
IO.inspect [p1, p2, p3, p4]
end
end
The erlang/elixir system cannot handle functions with multiple number of arguments but it can handle having functions with the same name but a different number of arguments which are actually different functions. When you call a function with that name you get the function which has the same number of arguments as in your call. If there isn’t one you get an error. This is what is happening here.
To see the functions which have been generated try calling the module_info/0 function which the compiler automatically generates, in this case Example.module_info().