I’m extracting many fields from a map using pattern-matching against the function parameter. Sometimes only a single field is missing from the input map. I’m handling this case with Map.merge-ing a default value into the input map and calling the same function again.
However, this feels not quite idiomatic. Can you maybe think of a more idiomatic way of handling this case?
@sigu
This case should not be the cause of using a struct. I mean the decision for a struct should be related to the problem and not to using some special syntax. @PJUllrich
The idiomatic way for me is not to use pattern matching just for the case of extracting values from a map. The pattern matching in the parameters should have always a good reason.
For me foocould be written as:
def foo(data) do
do_something(
Map.get(data, "a"),
Map.get(data, "b"),
Map.get(data, "c"),
Map.get(data, "d"),
Map.get(data, "e", 10)
)
end
I don’t think it’s bad to use Map.merge/2, but the way you use it as a fallback seems weird (and you wouldn’t have a base case if your map didn’t have an "a" key, for example).
Here’s how I would write your module:
defmodule Foobar do
@default_params %{"e" => 10}
def foo(params) do
params = Map.merge(@default_params, params)
do_something(params["a"], params["b"], params["c"], params["d"], params["e"])
end
def do_something(a, b, c, d, e) do
IO.inspect("#{a}-#{b}-#{c}-#{d}-#{e}")
end
end
But that may just be because of how I handle options to functions. I write a lot of single-public-function modules where I’m passing around the options to a lot of private functions and want the defaulting to happen in one place. They’ll look something like this:
defmodule My.Service do
@default_opts %{charlie: true, delta: []}
def call(alpha, bravo, opts \\ []) do
opts = Enum.into(opts, @default_opts)
with :ok <- validate_something(alpha, opts),
{:ok, echo} <- do_something(alpha, bravo, opts) do
{:ok, bravo + echo}
end
end
...
end
I agree with @Marcus. I’d like to keep on using a map instead of having to define a struct for this function only. But if this case would be occurring in more than one function, the struct would actually be the way to go I think, so thanks