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)
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
def add(a, b) do
a + b
end
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.
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.
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
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{}]
iex> list_recurring_orders(%{subaccount_id: 1}, with_preloads: [:items])
[%Order{items: [%Item{}]}]
I think the problem here is that you want to define 2 default values, which is possible but is not the best option for code readabilty imo.