Home

Awesome

Railway oriented programming

Implementation of module described here: http://zohaib.me/railway-programming-pattern-in-elixir/

Same thing can be achieved using Error monad: http://zohaib.me/monads-in-elixir-2/

tl;dr

Instead of |> we can use >>> to pipe {:ok, val} | {:error, error} returning functions.

Usage

As written in test/rop_test.exs:

use Rop

Using Rop defines >>> operator.

test "Count to 3" do
  assert (ok(0) >>> ok >>> ok) == {:ok, 3}
end

We increase 0 three times to end up with {:ok, 3}.

test "Error" do
  assert (ok(0) >>> error) == {:error, "Error at 1"}
end

Error function always return error.

test "Error propagation" do
  assert (ok(0) >>> error >>> ok) == {:error, "Error at 1"}
end

Error was propagated and second ok was not called.

test "First error is returned" do
  assert (ok(0) >>> error >>> error) == {:error, "Error at 1"}
end

Only first error is returned, since next error is never called.

defp ok(cnt) do
  {:ok, cnt + 1}
end

ok/1 function takes value and increases it, returning standard {:ok, val} response.

defp error(cnt) do
  {:error, "Error at #{cnt}"}
end

error/1 function takes value and returns standard {:error, string} that identifies where error was called.