Hi, I am learning Elixir and recently reading the Supervisor source code, and came accross start_link/2 and start_link/3:
# https://github.com/elixir-lang/elixir/blob/v1.20.1/lib/elixir/lib/supervisor.ex#L733
def start_link(children, options) when is_list(children) do
# https://github.com/elixir-lang/elixir/blob/v1.20.1/lib/elixir/lib/supervisor.ex#L976
def start_link(module, init_arg, options \\ []) when is_list(options)
As far as I understand, the default argument in def start_link(module, init_arg, options \\ []) should cause another start_link/2 to be defined and should result in ambiguity ? Does guard helps the compiler reduce ambiguity and thus the compiler treats it as a second clause for start_link/2 ? If so, the two clauses does not need to be grouped together ?
I tried the following:
defmodule A do
def f(a), do: "f(#{inspect(a)})"
def f(a, b \\ []) when is_list(b), do: "f(#{inspect(a)}, #{inspect(b)})"
end
and result in a warning:
β /tmp iex test.ex
Erlang/OTP 27 [erts-15.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
warning: this clause for f/1 cannot match because a previous clause at line 2 always matches
β
4 β def f(a, b \\ []) when is_list(b), do: "f(#{inspect(a)}, #{inspect(b)})"
β ~
β
ββ test.ex:4:7
Interactive Elixir (1.19.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
But if I changed the order of the defβs:
defmodule A do
def f(a, b \\ []) when is_list(b), do: "f(#{inspect(a)}, #{inspect(b)})"
def f(a), do: "f(#{inspect(a)})"
end
it results in an error:
β /tmp iex test.ex
Erlang/OTP 27 [erts-15.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
error: def f/1 conflicts with defaults from f/2
β
4 β def f(a), do: "f(#{inspect(a)})"
β ^
β
ββ test.ex:4:7: A.f/1
** (CompileError) test.ex: cannot compile module A (errors have been logged)
test.ex:4: (module)
Can anybody point me to related documentation about this behavior difference ?






















