Last active
November 30, 2016 08:41
-
-
Save kblake/b04e85c8e625ba650e1690f6f240d6f4 to your computer and use it in GitHub Desktop.
Thought experiment where I want to short circuit the processing of a list of operations if one of them fails.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ExpensiveOperationWorker do | |
# recursion and pattern matching | |
def process([head | tail]) do | |
operation_passed?(head) && process(tail) | |
end | |
def process([]), do: true | |
# Enum.reduce_while | |
def process_operations(operations) do | |
Enum.reduce_while(operations, true, fn number, acc -> | |
if operation_passed?(number) do | |
{:cont, acc} | |
else | |
{:halt, acc} | |
end | |
end) | |
end | |
# Enum.reduce | |
def another_way_to_process(operations) do | |
Enum.reduce(operations, true, &(&2 && operation_passed?(&1))) | |
end | |
# Contrived, expensive operation :) | |
defp operation_passed?(number) do | |
rem(number,2) != 0 | |
end | |
end | |
# 7 and 9 do not get evaluated | |
# because processing short-circuits at 6 | |
expensive_operations = [1,3,5,6,7,9] | |
ExpensiveOperationWorker.process(expensive_operations) | |
ExpensiveOperationWorker.process_operations(expensive_operations) | |
ExpensiveOperationWorker.another_way_to_process(expensive_operations) | |
#processes all since none are even | |
expensive_operations = [1,3,5,7,9,11] | |
ExpensiveOperationWorker.process(expensive_operations) | |
ExpensiveOperationWorker.process_operations(expensive_operations) | |
ExpensiveOperationWorker.another_way_to_process(expensive_operations) |
@gausby I like the guard approach!
How about:
def process(operations) do
Enum.drop_while(operations, &operation_passed?/1)
end
It has the added benefit of giving you a [failed|rest]
result.
If you want to collect the results you can use Enum.split_while/2
which will return {passed, [failed|rest]}
.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How about moving the private
operation_passed?/1
into a guard clause and replacing the if-expression with a multihead function:The continuation style looks less magical to me.