# Pattern matching on function heads

These are two distinct functions in my code. The first one takes in a map and optionally, a list. The second one takes in a list. I don’t understand where the conflict is.

`def list_recurring_orders(%{subaccount_id: subaccount_id}, opts \\ []) when is_integer(subaccount_id)`

` def list_recurring_orders(opts) when is_list(opts)`

I can’t use them because I get this error:

``````** (CompileError) lib/app_core/orders/recurring_orders.ex:155: def list_recurring_orders/1 conflicts with defaults from list_recurring_orders/2
``````

The issue arises because despite appearances, using default arguments actually creates two function heads - one with arity 1 and one with arity 2. So your code expands to:

``````def list_recurring_orders(%{subaccount_id: subaccount_id}, opts) do
....
end

def list_recurring_orders(%{subaccount_id: subaccount_id} = account) when is_integer(subaccount_id) do
list_recurring_orders(account, [])
end
def list_recurring_orders(opts) when is_list(opts) do
...
end
``````

To resolve this the defaults need to go in a bodiless function head:

``````def list_recurring_orders(account, opts \\ [])
def list_recurring_orders(%{subaccount_id: subaccount_id}, opts) when is_integer(subaccount_id)

def list_recurring_orders(opts) when is_list(opts)
``````
4 Likes

I get this error when I put the bodiless function heads before the functions.

`````` only variables and \\ are allowed as arguments in function head.

If you did not intend to define a function head, make sure your function definition has the proper syntax by wrapping the arguments in parentheses and using the do instruction accordingly:

def add(a, b), do: a + b

a + b
end
``````

I’d need to see what your full definition was, but this certainly compiles fine:

``````defmodule T do

def add(a, b), do: a + b

a + b
end
end
``````
2 Likes
``````def list_recurring_orders(%{subaccount_id: subaccount_id}, opts \\ []) when is_integer(subaccount_id)
def list_recurring_orders(opts) when is_list(opts)
``````

as kip said is just another way of writing

``````def list_recurring_orders(args), do: def list_recurring_orders(args, [])
def list_recurring_orders(%{subaccount_id: subaccount_id}, opts) when is_integer(subaccount_id)
def list_recurring_orders(opts) when is_list(opts)
``````

and now the last definition is unreachable - or in other words conflicting with the defaults.

``````def list_recurring_orders(%{subaccount_id: subaccount_id}, opts) when is_integer(subaccount_id) do
...
end
def list_recurring_orders(opts) when is_list(opts) do
...
end
def list_recurring_orders(%{subaccount_id: subaccount_id}) do
...
end
``````

that would probably work, but it is a little awkward if you ask me.

1 Like

I’m still having issues based on kip’s solution. I added this function head: ` def list_recurring_orders(subaccount_id, opts \\ [])` and it’s not doing the trick.

Are you saying write three functions?

Yes, seems that’s a requirement in this case to remove ambiguity:

``````  def list_recurring_orders(%{subaccount_id: subaccount_id}, opts) when is_integer(subaccount_id) do
# code here
end

def list_recurring_orders(%{subaccount_id: _} = sub_account) do
list_recurring_orders(sub_account, [])
end

def list_recurring_orders(opts) when is_list(opts) do
# code here
end
``````
1 Like

Maybe.

It really depends on what you are trying to achieve. Right now the way I understand your example, I would probably do something like this

``````def list_recurring_orders(args, opts \\ [])

def list_recurring_orders(%{subaccount_id: subaccount_id}, opts) when is_integer(subaccount_id) do
# list all recurring orders for subaccount
end

def list_recurring_orders(:all, opts) do
# list all recurring orders for all accounts (?)
end

iex> list_recurring_orders(:all)
[%Order{}]

iex> list_recurring_orders(%{subaccount_id: 1})
[%Order{}]

This is exactly what I want to do; I’ll try passing in `:all` as a flag.