ex_flow v0.1.1 ExFlow

Module to make life with workflows easier

Helps to compose functions with |> to not handle errors explicitly but just to bypass them.

If you hate making names for variables with Kernel.SpecialForms.with/1 this module is for you

  defmodule MyModule do
    import ExFlow

    def action do
      workflow do
        validate_input_data(params)
        ~> save_user
        ~> generate_plans(2)
        ~>> send_confirmation
        ~> redirect_to_user_page
      end
    end
  end

Operations in previous example might be anything. It's a bogus code to show how to to pipe operations inside workflows and not care about failures. ~> is for operations which transform data and ~>> is for operations which don't transform data and can be built manually without metaprogramming with the help of ExFlow.bind/1, ExFlow.bind/2, ExFlow.then/1 and ExFlow.then/2.

Link to this section Summary

Functions

Binds an argument and produces one-argument function

Binds an argument and produces one-argument function which ignores function return value

Creates workflow

Link to this section Functions

Link to this function

bind(fun)

(since 0.1.0)

Binds an argument and produces one-argument function

Returns new anonymous function which either returns input parameter if it looks like error or calls the function being bound with that parameter. Inspired by >>= in Haskell.

Parameter is considered to be error if it is equal to :error or a tuple which first element is :error.

Helps to compose functions with |> to not handle errors explicitly but just to bypass them.

## Examples

iex> ExFlow.bind(fn _ -> 42 end).({:error, :reason})
{:error, :reason}

iex> ExFlow.bind(fn _ -> 42 end).(:error)
:error

iex> ExFlow.bind(& &1).(42)
42

iex> {:error, :reason} |> ExFlow.bind(&(&1 * 2)) |> ExFlow.bind(&(&1 + 2))
{:error, :reason}

iex> :error |> ExFlow.bind(&(&1 * 2)) |> ExFlow.bind(&(&1 + 2))
:error

iex> 20 |> ExFlow.bind(&(&1 * 2)) |> ExFlow.bind(&(&1 + 2))
42
Link to this function

then(fun)

(since 0.1.0)

Binds an argument and produces one-argument function which ignores function return value

Returns new anonymous function which either returns input parameter if it looks like error or calls the function being bound with that parameter and returns that very parameter. Usefull for sideffect functions which don't transform input e.g. scheduling job to send email when user is created/ Inspired by >> in Haskell.

Parameter is considered to be error if it is equal to :error or a tuple which first element is :error.

Helps to compose functions with |> to not handle errors explicitly but just to bypass them.

## Examples

iex> ExFlow.then(fn a -> a + 2 end).({:error, :reason})
{:error, :reason}

iex> ExFlow.then(fn a -> a + 2 end).(:error)
:error

iex> ExFlow.then(& &1).(42)
42

iex> {:error, :reason} |> ExFlow.then(&(&1 * 2)) |> ExFlow.then(&(&1 + 2))
{:error, :reason}

iex> :error |> ExFlow.then(&(&1 * 2)) |> ExFlow.then(&(&1 + 2))
:error

iex> 20 |> ExFlow.then(&(&1 * 2)) |> ExFlow.then(&(&1 + 2))
20
Link to this macro

workflow(list)

(macro)

Creates workflow

In simple words helps to compose functions thinking only about happy path and return error as soon as possible. Actually speaking it is the same as Kernel.SpecialForms.with/1 but doesn't make you think about the errors and allows just to write the transformations on data instead.

It uses ~> operator which is the same as |> in context of workflow. So

  workflow do
    operation ~> operation2
  end

is the same as

  operation |> ExFlow.bind(&(operation2(&1)))

Also uses ~>> operator where is the same as |> in context of workflow but ignores the return or right parameter function. So

  workflow do
    operation ~>> operation2
  end

is the same as

  operation |> ExFlow.then(&(operation2(&1)))

which will return the result of operation not operation2. Useful for side-effect oe async operations which shouldn't transform input data