Heady Functions

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.