vinibrl
Case with multiple values
I refactored a code from:
def do_something(attribute) do
bar = get_bar(attribute)
baz = get_baz(bar)
do_something_else(attribute, bar, baz)
end
defp do_something_else(_first, _second, 12381), do: {:ok, :ignored}
defp do_something_else(_first, second, _third) when length(second) > 100, do: {:ok, :ignored}
defp do_something_else(first, second, third), do: ExternalService.call(first, second, third)
to:
def do_something(attribute) do
bar = get_bar(attribute)
baz = get_baz(bar)
case {attribute, bar, baz} do
{_first, _second, 12381} -> {:ok, :ignored}
{_first, second, _third} when length(second) > 100 -> {:ok, :ignored}
{first, second, third} -> ExternalService.call(first, second, third)
end
end
I replaced the private functions with a case. AFAIK I can’t use multiple values on the case clause, I wrapped them in a tuple. Is this the idiomatic way to do it?
Marked As Solved
yurko
I actually like the original version with private functions better.
Your context module will grow too big no matter how you organize its logic. I’d suggest to only have delegates and documentation in context module and delegate to multiple specific “private” modules that have actual logic, if you do that, then the size of each such module will not be a problem.
Also Liked
hauleth
This is one of the ways to do so, yes. However in case of case you do not need to pass first, so you could do:
case {bar, baz} do
{_, 12381} -> {:ok, :ignored}
{list, _} when length(list) -> {:ok, :ignored}
_ -> ExternalService.call(attributes, bar, baz)
end
Or you could squash the two cases:
case {bar, baz} do
{list, num} when num == 12381 or length(list) > 100 -> {:ok, :ignored}
_ -> ExternalService.call(attributes, bar, baz)
end
However in that case whole pattern matching is needless, so we can do:
cond do
baz == 12381 or length(bar) > 100 -> {:ok, :ignored}
true -> ExternalService.call(attributes, bar, baz)
end
Or you could use if macro if it is clearer for you:
if baz == 12381 or length(bar) > 100,
do: {:ok, :ignored},
else: ExternalService.call(attributes, bar, baz)
EDIT:
@tushar as length(baz) is used only once then it is much better to not cache it, as if baz == 12381 the length(baz) will not be called at all which can save time, as counting length of the list can be needlessly expensive for long lists.
dmkit
But is it ideal to convert it from multi funs to case block / cond block? Or it’s just a matter of preference?







