View Source Bunch.Enum (Bunch v1.6.1)

A bunch of helper functions for manipulating enums.

Summary

Functions

Splits enumerable into chunks, and passes each chunk through collector.

Returns elements that occur at least min_occurences times in enumerable.

Generates a list by calling i times function f.

Generates a list consisting of i values v.

Works like Enum.each/2, but breaks on error.

Works like Enum.flat_map/2, but breaks on error.

Works like Enum.each/2, but breaks on error.

Works like Enum.map/2, but breaks on error.

Works like Enum.map_reduce/3, but breaks on error.

Works like Enum.reduce/3, but breaks on error.

Works like Enum.reduce_while/3, but breaks on error.

Implementation of Enum.unzip/1 for more-than-two-element tuples.

Works the same way as Enum.zip/1, but does not cut off remaining values.

Functions

Link to this function

chunk_by_prev(enum, chunker, collector \\ & &1)

View Source
@spec chunk_by_prev(Enum.t(), chunker :: (a, a -> boolean()), collector :: ([a] -> b)) ::
  [b]
when a: any(), b: any()

Splits enumerable into chunks, and passes each chunk through collector.

New chunk is created each time chunker returns false. The chunker is passed current and previous element of enumerable.

Examples:

iex> Bunch.Enum.chunk_by_prev([1,2,5,5], fn x, y -> x - y <= 2 end)
[[1, 2], [5, 5]]
iex> Bunch.Enum.chunk_by_prev([1,2,5,5], fn x, y -> x - y <= 2 end, &Enum.sum/1)
[3, 10]
Link to this function

duplicates(enum, min_occurences \\ 2)

View Source
@spec duplicates(Enum.t(), pos_integer()) :: list()

Returns elements that occur at least min_occurences times in enumerable.

Results are NOT ordered in any sensible way, neither is the order anyhow preserved, but it is deterministic.

Examples

iex> Bunch.Enum.duplicates([1,3,2,5,3,2,2])
[2, 3]
iex> Bunch.Enum.duplicates([1,3,2,5,3,2,2], 3)
[2]
@spec repeat(f :: (-> a), non_neg_integer()) :: [a] when a: any()

Generates a list by calling i times function f.

iex> {:ok, pid} = Agent.start_link(fn -> 0 end)
iex> Bunch.Enum.repeat(fn -> Agent.get_and_update(pid, &{&1, &1+1}) end, 4)
[0, 1, 2, 3]
iex> Bunch.Enum.repeat(fn -> :abc end, 0)
[]
@spec repeated(v, non_neg_integer()) :: [v] when v: any()

Generates a list consisting of i values v.

iex> Bunch.Enum.repeated(:abc, 4)
[:abc, :abc, :abc, :abc]
iex> Bunch.Enum.repeated(:abc, 0)
[]
@spec try_each(Enum.t(), fun :: (a -> result)) :: result
when a: any(), result: Bunch.Type.try_t()

Works like Enum.each/2, but breaks on error.

Behaves like Enum.each/2 as long as given fun returns :ok. If it happens to return {:error, reason}, traversal is stopped and the error is returned.

Examples:

iex> fun = fn 0 -> {:error, :zero}; x -> send(self(), 1/x); :ok end
iex> Bunch.Enum.try_each([1,2,3], fun)
:ok
iex> Bunch.Enum.try_each([1,0,3], fun)
{:error, :zero}
@spec try_flat_map(Enum.t(), fun :: (a -> result)) :: result
when a: any(), b: any(), result: Bunch.Type.try_t([b])

Works like Enum.flat_map/2, but breaks on error.

Behaves like Enum.flat_map/2 as long as reducing function returns {:ok, values}. If it happens to return {:error, reason}, reduction is stopped and the error is returned.

Examples:

iex> fun = fn 0 -> {:error, :zero}; x -> {:ok, [1/x, 2/x, 3/x]} end
iex> Bunch.Enum.try_flat_map([1,5,-2,8], fun)
{:ok, [1.0, 2.0, 3.0, 0.2, 0.4, 0.6, -0.5, -1.0, -1.5, 0.125, 0.25, 0.375]}
iex> Bunch.Enum.try_flat_map([1,5,0,8], fun)
{:error, :zero}
Link to this function

try_flat_map_reduce(enum, acc, f)

View Source
@spec try_flat_map_reduce(Enum.t(), acc, fun :: (a, acc -> result)) :: result
when a: any(), b: any(), acc: any(), result: Bunch.Type.stateful_try_t([b], acc)

Works like Enum.each/2, but breaks on error.

Behaves like Enum.flat_map_reduce/3 as long as given fun returns {{:ok, value}, new_acc}. If it happens to return {{:error, reason}, new_acc}, reduction is stopped and the error is returned.

Examples:

iex> fun = fn
...> x, acc when acc >= 0 -> {{:ok, [x+1, x+2, x+3]}, x + acc}
...> _, acc -> {{:error, :negative_prefix_sum}, acc}
...> end
iex> Bunch.Enum.try_flat_map_reduce([1,5,-2,8], 0, fun)
{{:ok, [2,3,4,6,7,8,-1,0,1,9,10,11]}, 12}
iex> Bunch.Enum.try_flat_map_reduce([1,5,-7,8], 0, fun)
{{:error, :negative_prefix_sum}, -1}
@spec try_map(Enum.t(), fun :: (a -> Bunch.Type.try_t(b))) :: Bunch.Type.try_t([b])
when a: any(), b: any()

Works like Enum.map/2, but breaks on error.

Behaves like Enum.map/2 as long as given fun returns {:ok, value}. If it happens to return {:error, reason}, reduction is stopped and the error is returned.

Examples:

iex> fun = fn 0 -> {:error, :zero}; x -> {:ok, 1/x} end
iex> Bunch.Enum.try_map([1,5,-2,8], fun)
{:ok, [1.0, 0.2, -0.5, 0.125]}
iex> Bunch.Enum.try_map([1,5,0,8], fun)
{:error, :zero}
Link to this function

try_map_reduce(enum, acc, f)

View Source
@spec try_map_reduce(
  Enum.t(),
  acc,
  fun :: (a, acc -> Bunch.Type.stateful_try_t(b, acc))
) ::
  Bunch.Type.stateful_try_t([b], acc)
when a: any(), b: any(), acc: any()

Works like Enum.map_reduce/3, but breaks on error.

Behaves like Enum.map_reduce/3 as long as given fun returns {{:ok, value}, new_acc}. If it happens to return {{:error, reason}, new_acc}, reduction is stopped and the error is returned.

Examples:

iex> fun = fn
...> x, acc when acc >= 0 -> {{:ok, x+1}, x + acc}
...> _, acc -> {{:error, :negative_prefix_sum}, acc}
...> end
iex> Bunch.Enum.try_map_reduce([1,5,-2,8], 0, fun)
{{:ok, [2,6,-1,9]}, 12}
iex> Bunch.Enum.try_map_reduce([1,5,-7,8], 0, fun)
{{:error, :negative_prefix_sum}, -1}
Link to this function

try_reduce(enum, acc, f)

View Source
@spec try_reduce(Enum.t(), acc, fun :: (a, acc -> result)) :: result
when a: any(), acc: any(), result: Bunch.Type.stateful_try_t(acc)

Works like Enum.reduce/3, but breaks on error.

Behaves like Enum.reduce/3 as long as given fun returns {:ok, new_acc}. If it happens to return {{:error, reason}, new_acc}, reduction is stopped and the error is returned.

Examples:

iex> fun = fn
...> x, acc when acc >= 0 -> {:ok,  x + acc}
...> _, acc -> {{:error, :negative_prefix_sum}, acc}
...> end
iex> Bunch.Enum.try_reduce([1,5,-2,8], 0, fun)
{:ok, 12}
iex> Bunch.Enum.try_reduce([1,5,-7,8], 0, fun)
{{:error, :negative_prefix_sum}, -1}
Link to this function

try_reduce_while(enum, acc, f)

View Source
@spec try_reduce_while(
  Enum.t(),
  acc,
  reducer :: (a, acc -> Bunch.Type.stateful_try_t(:cont | :halt, acc))
) :: Bunch.Type.stateful_try_t(acc)
when a: any(), acc: any()

Works like Enum.reduce_while/3, but breaks on error.

Behaves like Enum.reduce_while/3 as long as given fun returns {{:ok, :cont | :halt}, new_acc}. If it happens to return {{:error, reason}, new_acc}, reduction is stopped and the error is returned.

Examples:

iex> fun = fn
...> 0, acc -> {{:ok, :halt}, acc}
...> x, acc when acc >= 0 -> {{:ok, :cont}, x + acc}
...> _, acc -> {{:error, :negative_prefix_sum}, acc}
...> end
iex> Bunch.Enum.try_reduce_while([1,5,-2,8], 0, fun)
{:ok, 12}
iex> Bunch.Enum.try_reduce_while([1,5,0,8], 0, fun)
{:ok, 6}
iex> Bunch.Enum.try_reduce_while([1,5,-7,8], 0, fun)
{{:error, :negative_prefix_sum}, -1}
@spec unzip(tuples :: [tuple()]) :: tuple()

Implementation of Enum.unzip/1 for more-than-two-element tuples.

Size of returned tuple is equal to size of the shortest tuple in tuples.

Examples:

iex> Bunch.Enum.unzip([{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}])
{[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]}
iex> Bunch.Enum.unzip([{1,2,3}, {4,5}, {6,7,8,9}, {10,11,12}])
{[1, 4, 6, 10], [2, 5, 7, 11]}
@spec zip_longest(list()) :: [list()]

Works the same way as Enum.zip/1, but does not cut off remaining values.

Examples:

iex> Bunch.Enum.zip_longest([[1, 2] ,[3 ,4, 5]])
[[1, 3], [2, 4], [5]]

It also returns list of lists, as opposed to tuples.