Updated Solution
I think I have a better understanding on how Keywords can be passed in as function arguments and the benefits. In my original post I was rigid in having my function arguments be in a specific order and named.
But the new solution I think is more idiomatic. I am much happier and learned quite a lot in this thread.
New Approach
defmodule Example do
@doc """
Does a lookup
## Example
iex> Example.lookup("a")
iex> Example.lookup("a", date: "20230131")
iex> Example.lookup("a", date: "20230131", place_id: "b")
iex> Example.lookup("a", date: "20230131", place_id: "b", direction_id: :internal)
"""
def lookup(id, opts \\ []) do
defaults = [date: today_string()]
opts = Keywords.merge(defaults, opts)
results = QuerySomeDB.get(id, opts[:date]) # some querying would happen
do_lookup(results, opts)
end
defp do_lookup(results, opts) do
place_id = opts[:place_id]
company_id = opts[:company_id]
results = if place_id, do: filter_by_place_id(results, place_id), else: results
results = if company_id, do: filter_by_company_id(results, place_id), else: results
results
end
defp filter_by_place_id(results, place_id) do
# ... do some filtering and return the new results
results
end
defp filter_by_company_id(results, company_id) when company_id in [:internal, :external] do
# ... do some filtering and return the new results
results
end
defp today_string() do
#... returns a date string
end
end






















