Elixir: How to deal with optional / default parameters in functions and nil values?
<p>I have a general question about default parameters and nil values. Suppose I have two functions. One calls the other (which is a helper function). Both have an optional parameter. </p>

<p>The helper function just joins a list to a string with a joiner. The joiner is passed to the first function inside an opts keyword list. The passing of the joiner is optional, it defaults to <code>"AND"</code></p>

<pre><code>defmodule ParamTest do
  def func_1(list, opts \\ []) do
    helper(list, opts[:joiner])
    # Do something else with the result
  end

  defp helper(list, joiner \\ "AND") do
    Enum.join(list, " #{joiner} ")
  end
end

# Example 1
["el 1", "el 2"] 
|&gt; ParamTest.func_1(joiner: "AND")
# Result "el 1 AND el 2"

# Example 2
["el 1", "el 2"] 
|&gt; ParamTest.func_1
# Result: "el 1  el 2"
# But it should be also "el 1 AND el 2"
</code></pre>

<p>The problem is: opts[:joiner] will be nil in the second example. But it is still present so the default value will not be used.</p>

<p>One possible solution would be to use <code>case</code>: </p>

<pre><code>defmodule ParamTest do
  def func_1(list, opts \\ []) do
    case is_nil(opts[:joiner]) do
      true -&gt; helper(list)
      false -&gt; helper(list, opts[:joiner])
    end
    # Do something else with the result
  end

  defp helper(list, joiner \\ "AND") do
    Enum.join(list, " #{joiner} ")
  end
end
</code></pre>

<p>Another way would be to use two function definitions for helper and use pattern matching:</p>

<pre><code>defmodule ParamTest do
  def func_1(list, opts \\ []) do
    case is_nil(opts[:joiner]) do
      true -&gt; helper(list)
      false -&gt; helper(list, opts[:joiner])
    end
  end

  defp helper(list, nil) do
    Enum.join(list, " AND ")
  end

  defp helper(list, joiner \\ "AND") do
    Enum.join(list, " #{joiner} ")
  end
end
</code></pre>

<p>But I have the feeling that this is not very elegant and could get messy in more complex situations. </p>

<p>What is a better solution for this scenario?</p>