Living with-out
There is a tendency in Elixir to reach for the with macro to handle control flow.
def fetch_token(type, params \\ []) do
with params <- Keyword.merge(required_get_token_params(type), params),
{:ok, client} <- OAuth2.Client.get_token(client(type), params) do
{:ok, client}
else
err -> err
end
end
At first glance, this code looks succinct, clean, and readable. Then you realize two refactors
With returns the unmatched value by default
def fetch_token(type, params \\ []) do
with params <- Keyword.merge(required_get_token_params(type), params),
{:ok, client} <- OAuth2.Client.get_token(client(type), params) do
{:ok, client}
end
end
If there is no else condition, you don’t need to double match on the last clause.
def fetch_token(type, params \\ []) do
with params <- Keyword.merge(required_get_token_params(type), params) do
OAuth2.Client.get_token(client(type), params)
end
end
After these two refactors, you realize that you never needed with
in the first place!
def fetch_token(type, params \\ []) do
params = Keyword.merge(required_get_token_params(type), params)
OAuth2.Client.get_token(client(type), params)
end
Now, this may seem overly pedantic, but many bugs can hang out in the plain sight of verbose code. Eliminating branching in your code is a great strategy for reducing complexity.