Bunch v0.1.2 Bunch View Source

A bunch of general-purpose helper and convenience functions.

Link to this section Summary

Functions

Brings some useful functions to the scope

Returns error tuple if given value is nil and ok tuple otherwise

Returns value decreased by value (mod divisor)

Embeds the argument in a one-element list if it is not a list itself. Otherwise works as identity

Macro providing support for python-style condition notation

Returns stacktrace as a string

Returns given stateful try value along with its status

Works like withl/2, but allows shorter syntax

A labeled version of the with macro

Helper for writing pipeline-like syntax. Maps given value using match clauses or lambda-like syntax

Works similar to ~>/2, but accepts only -> clauses and appends default identity clause at the end

Link to this section Functions

Link to this macro __using__(args) View Source (macro)

Brings some useful functions to the scope.

Link to this function error_if_nil(v, reason) View Source
error_if_nil(value, reason) :: Bunch.Type.try_t(value)
when value: any(), reason: any()

Returns error tuple if given value is nil and ok tuple otherwise.

Link to this function int_part(value, divisor) View Source
int_part(value :: non_neg_integer(), divisor :: pos_integer()) ::
  non_neg_integer()

Returns value decreased by value (mod divisor)

Examples

iex> Bunch.int_part(10, 4)
8
iex> Bunch.int_part(7, 7)
7
Link to this function listify(list) View Source
listify(a | [a]) :: [a] when a: any()

Embeds the argument in a one-element list if it is not a list itself. Otherwise works as identity.

Examples

iex> Bunch.listify(:a)
[:a]
iex> Bunch.listify([:a, :b, :c])
[:a, :b, :c]
Link to this macro provided(expr, list) View Source (macro)

Macro providing support for python-style condition notation.

Examples

iex> use Bunch
iex> x = 10
iex> x |> provided(that: x > 0, else: 0)
10
iex> x = -4
iex> x |> provided(that: x > 0, else: 0)
0

Apart from that, supported are also do and not keys:

iex> use Bunch
iex> x = -4
iex> x |> provided do x > 0 else 0 end
0
iex> x = -4
iex> x |> provided(not: x > 0, else: 0)
-4

Returns stacktrace as a string.

The stacktrace is formatted to the readable format.

Link to this function stateful_try_with_status(res) View Source
stateful_try_with_status(result) :: {status, result}
when status: Bunch.Type.try_t(),
     result:
       Bunch.Type.stateful_try_t(state :: any())
       | Bunch.Type.stateful_try_t(value :: any(), state :: any())

Returns given stateful try value along with its status.

Link to this macro withl(keyword) View Source (macro)
withl(
  keyword :: [
    {key :: atom(), with_clause :: term()}
    | {:do, code_block :: term()}
    | {:else, match_clauses :: term()}
  ]
) :: term()

Works like withl/2, but allows shorter syntax.

Examples

iex> use Bunch
iex> x = 1
iex> y = 2
iex> withl a: true <- x > 0,
...>       b: false <- y |> rem(2) == 0,
...>       do: {x, y},
...>       else: (a: false -> {:error, :x}; b: true -> {:error, :y})
{:error, :y}

For more details and more verbose and readable syntax, check docs for withl/2.

Link to this macro withl(with_clauses, list) View Source (macro)
withl(keyword(with_clause :: term())) do
  code_block :: term()
else
  match_clauses :: term()
end :: term()

A labeled version of the with macro.

Helps to determine in else block which with clause did not match. Therefore else block is always required. Due to the Elixir syntax requirements, all clauses have to be labeled.

Labels also make it possible to access results of already succeeded matches from else clauses. That is why labels have to be known at the compile time.

There should be at least one clause in the else block for each label that corresponds to a <- clause.

Duplicate labels are allowed.

Examples

iex> use Bunch
iex> list = [-1, 3, 2]
iex> binary = <<1,2>>
iex> withl max: i when i > 0 <- list |> Enum.max(),
...>       bin: <<b::binary-size(i), _::binary>> <- binary do
...>   {list, b}
...> else
...>   max: i -> {:error, :invalid_maximum, i}
...>   bin: b -> {:error, :binary_too_short, b, i}
...> end
{:error, :binary_too_short, <<1,2>>, 3}
Link to this macro expr ~> mapper View Source (macro)

Helper for writing pipeline-like syntax. Maps given value using match clauses or lambda-like syntax.

Examples

iex> use Bunch
iex> {:ok, 10} ~> ({:ok, x} -> x)
10
iex> 5 ~> &1 + 2
7

Lambda-like expressions are not converted to lambdas under the hood, but result of expr is injected to &1 at the compile time.

Useful especially when dealing with a pipeline of operations (made up e.g. with pipe (|>) operator) some of which are hard to express in such form:

iex> use Bunch
iex> ["Joe", "truck", "jacket"]
...> |> Enum.map(&String.downcase/1)
...> |> Enum.filter(& &1 |> String.starts_with?("j"))
...> ~> ["Words:" | &1]
...> |> Enum.join("\n")
"Words:
joe
jacket"
Link to this macro expr ~>> mapper_clauses View Source (macro)

Works similar to ~>/2, but accepts only -> clauses and appends default identity clause at the end.

Examples

iex> use Bunch
iex> {:ok, 10} ~>> ({:ok, x} -> {:ok, x+1})
{:ok, 11}
iex> :error ~>> ({:ok, x} -> {:ok, x+1})
:error