# Fix definitions with multiple clauses and optional values that only have 1 param

I have the following code in my GenServer:

``````def init(%State{} = state), do: {:ok, state, 1_000}
def init(opts \\ []) do
state = struct(State, opts)
{:ok, state, 1_000}
end
``````

This code, as some of you may guess will generate the following warning:

definitions with multiple clauses and default values require a header. Instead of:

``````def foo(:first_clause, b \\ :default) do ... end
def foo(:second_clause, b) do ... end
``````

one should write:

``````def foo(a, b \\ :default)
def foo(:first_clause, b) do ... end
def foo(:second_clause, b) do ... end
``````

def init/1 has multiple clauses and defines defaults in one or more clauses

The warning is pretty good, but I don’t see how I can apply it. Mainly because `init` can be called in 3 completely different ways:

1. passing a state
2. with no arguments
3. passing an options keyword list

How can I fix this?

1 Like

Just following the suggestion in the warning, maybe:

``````def init(opts \\ [])
def init(%State{} = state), do: {:ok, state, 1_000}
def init(opts) do
state = struct(State, opts)
{:ok, state, 1_000}
end
``````

This is confusing to me. By doing it that way, I am saying that `state` is actually an `opts`, right ?

The problem is that it’s elixir creating multiple function heads for you here:

``````def init(), do: init([])
def init(%State{} = state), do: …
def init(opts), do: …
``````

So it doesn’t really care about your patter match at all. It just needs to know that the first parameter is optional and shall be passed `[]` if not present. You could do:

``````def init(state_or_opts \\ [])
def init(%State{} = state), do: {:ok, state, 1_000}
def init(opts) do
state = struct(State, opts)
{:ok, state, 1_000}
end
``````
4 Likes

Looking at your code, for me it seems much more like `opts` beeing a listified `%State{}`