So, here it suggest writing functions without heads

for default arguments.

But, understandably, Dialyzer complains.

Is it or should it be preferable to default by say

``````def a(b), do: a b, 2
def a(b,c), do: ...``````
1 Like

I don’t believe the getting started guide suggests that it’s preferable to not use default arguments, if I understand your question correctly.

Dialyzer seemed okay with this (silly) function, which has an optional argument that may be one of multiple types:

``````@type int_string :: integer() | binary()

@spec increment(integer(), int_string()) :: integer()
def increment(number, by \\ 1)
def increment(number, by) when is_integer(by) do
number + 1
end
def increment(number, by) when is_binary(by) do
number + 1
end

def runit() do
increment(1)
increment(1, 4)
increment(1, "4")
end
``````

As to whether it’s clearer or more idiomatic to expose two functions with different arities instead, I don’t know. I’m curious what others think.

1 Like

In fact the first example is only a sugared version of the second:

``````# 1. version
def foo(a, b \\ 0)
def foo(a, b), do: a + b

# 2. version
def foo(a), do: foo(a, 0)
def foo(a, b), do: a + b
``````

So I do prefer to use the first version in most of the cases, but only iff I really want to expose both aritys. Lets consider another function, which operates on a list and builds up another list. It is common to write one function taking one list and a function taking two lists, where the second function does all the work and the first does just call the second. In this case I want to have `*/2`-version of the function private and only the first version exposed.