Bunch v0.3.0 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

Works like quote/2, but doesn't require a do/end block and options are passed as the last argument

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
Link to this macro

quote_expr(code, opts \\ []) View Source (macro)

Works like quote/2, but doesn't require a do/end block and options are passed as the last argument.

Useful when quoting a single expression.

Examples

iex> use Bunch
iex> quote_expr(String.t())
quote do String.t() end
iex> quote_expr(unquote(x) + 2, unquote: false)
quote unquote: false do unquote(x) + 2 end

Nesting

Nesting calls to quote disables unquoting in the inner call, while placing quote_expr in quote or another quote_expr does not:

iex> use Bunch
iex> quote do quote do unquote(:code) end end == quote do quote do :code end end
false
iex> quote do quote_expr(unquote(:code)) end == quote do quote_expr(:code) end
true

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