View Source Iter.Impl (iterex v0.1.1)

The default implementations of all Iter.Iterable callbacks except next/1.

By adding use Iter.Impl to your Iter.Iterable definition all of the default functions will be automatically delegated and marked as overridable.

This allows you to implement only those callbacks which can reasonably be made faster for your particular iterable, and not have to implement all of them.

For example, here's a fictional implementation of iterable for List:

defimpl Iter.Iterable, for: List do
  use Iter.Impl

  def next([head | tail]), do: {:ok, head, tail}
  def next([]), do: :done

  def peek([]), do: :done
  def peek([head | _] = list), do: {:ok, head, list}

  def empty?([]), do: true
  def empty?(_), do: false
end

Be aware that all the default implementations rely on your implementation of next/1 which you always must provide.

Summary

Functions

Generate overridable delegations to the default iterable callbacks.

Tests if every element in the iterable matches predicate.

Tests if any element in the iterable matches predicate.

Creates an iterable that appends an element to the end of the iterable.

Returns the element index items from the beginning of the iterable.

Creates an iterable that chunks elements by subsequent return values of fun.

Creates an iterable that chunks elements into count sized chunks of step spacing.

Creates an iterable that chunks based on a chunk function.

Takes an iterable and iterates each iterable in an iterable.

Consumes the iterable, returning the number of elements within

Consumes the iterable, returning the number of elements for which fun returns a truthy value.

Creates an iterator that cycles it's elements eternally.

Creates an iterable that only emits elements if they are different from the previous element.

Creates an iterable that only emits elements if they are different from the previous element.

Creates an iterable which drops the first how_many elements.

Returns a new iterable with every nth element in the iterable dropped, starting with the first element.

Drops elements at the beginning of iterable while fun returns a truthy value.

Consumes the iterable and applies fun to each element.

Determines if the iterable is empty.

Creates an iterable which drops elements for which predicate doesn't return true.

Searches for the first element in the iterable which matches predicate.

Returns the index of the first element in the iterable which matches predicate.

Returns the first truthy value returned by fun.

Creates an iterable which works like map/2 but flattens nested iterables.

Creates an iterable which flattens nested iterables.

Creates a new iterable which places separator between adjacent items of the original iterable.

Creates a new iterable which applies mapper to each element and using it's result as the new element value.

Creates a new iterable which applies mapper on every nth element of the iterable, starting with the first element.

Returns the maximal element in the iterable according to Erlang's term ordering.

Returns the maximal element in the iterable as calculated by mapper.

Is the element a member of the iterable?

Returns the minimal element in the iterable according to Erlang's term ordering.

Returns the minimal element in the iterable as calculated by mapper.

Finds the minimal and maximal elements in the iterable.

Peeks at the first element of the iterable, without consuming it.

Peeks at the first how_many elements of the iterable, without consuming them.

Creates a new iterable which places element at the beginning of the iterable.

Creates an iterable starting at the same point, but stepping by how_many each iteration.

Collects the first how_many elements into a new iterable and returns it along with the advanced initial iterable.

Creates an iterable which takes the first how_many elements.

Creates an iterable which takes the last how_many elements.

Creates an iterable which emits elements until predicate returns false.

Convert the iterable into a list.

Creates an iterable that only emits unique elements.

Creates an iterable which emits the current iteration count as well as the next value.

Zips corresponding elements from a finite collection of iterables into one iterable of results as computed by zipper.

Types

Functions

Generate overridable delegations to the default iterable callbacks.

Link to this function

all?(iterable, predicate)

View Source
@spec all?(iterable(), predicate()) :: boolean()

Tests if every element in the iterable matches predicate.

Examples

iex> Impl.all?([2, 4, 6, 8], &(rem(&1, 2) == 0))
true

iex> Impl.all?([2, 3, 4], &(rem(&1, 2) == 0))
false
Link to this function

any?(iterable, predicate)

View Source
@spec any?(iterable(), predicate()) :: boolean()

Tests if any element in the iterable matches predicate.

Examples

iex> Impl.any?([2, 4, 6], &(rem(&1, 2) == 1))
false

iex> Impl.any?([2, 3, 4], &(rem(&1, 2) == 1))
true
Link to this function

append(iterable, element)

View Source
@spec append(iterable(), element()) :: iterable()

Creates an iterable that appends an element to the end of the iterable.

Examples

iex> Impl.append(1..3, 4)
...> |> Impl.to_list()
[1, 2, 3, 4]
@spec at(iterable(), non_neg_integer()) :: {:ok, element(), iterable()} | :done

Returns the element index items from the beginning of the iterable.

Example

iex> Impl.at([:a, :b, :c], 1)
{:ok, :b, [:c]}
Link to this function

chunk_by(iterable, chunker)

View Source
@spec chunk_by(iterable(), (element() -> any())) :: iterable()

Creates an iterable that chunks elements by subsequent return values of fun.

Example

iex> Impl.chunk_by([1, 2, 2, 3, 4, 4, 6, 7, 7], &(rem(&1, 2) == 1))
...> |> Impl.to_list()
[[1], [2, 2], [3], [4, 4, 6], [7, 7]]
Link to this function

chunk_every(iterable, count, step, leftover)

View Source
@spec chunk_every(iterable(), pos_integer(), pos_integer(), iterable() | :discard) ::
  iterable()

Creates an iterable that chunks elements into count sized chunks of step spacing.

Examples

iex> Impl.chunk_every([1, 2, 3, 4, 5, 6], 2, 2, []) |> Impl.to_list()
[[1, 2], [3, 4], [5, 6]]

iex> Impl.chunk_every([1, 2, 3, 4, 5, 6], 3, 2, :discard) |> Impl.to_list()
[[1, 2, 3], [3, 4, 5]]

iex> Impl.chunk_every([1, 2, 3, 4, 5, 6], 3, 2, [7]) |> Impl.to_list()
[[1, 2, 3], [3, 4, 5], [5, 6, 7]]

iex> Impl.chunk_every([1, 2, 3, 4, 5, 6], 3, 3, []) |> Impl.to_list()
[[1, 2, 3], [4, 5, 6]]

iex> cycler = Impl.cycle([0])
iex> Impl.chunk_every([1, 2, 3, 4], 3, 3, cycler) |> Impl.to_list()
[[1, 2, 3], [4, 0, 0]]
Link to this function

chunk_while(iterable, acc, chunk_fun, after_fun)

View Source
@spec chunk_while(
  iterable(),
  acc,
  (element(), acc -> {:cont, chunk, acc} | {:cont, acc} | {:halt, acc}),
  (acc -> {:cont, chunk, acc} | {:cont, acc})
) :: iterable()
when acc: any(), chunk: any()

Creates an iterable that chunks based on a chunk function.

Examples

iex> chunk_fun = fn element, acc ->
...>   if rem(element, 2) == 0 do
...>     {:cont, Enum.reverse([element | acc]), []}
...>   else
...>     {:cont, [element | acc]}
...>   end
...> end
iex> after_fun = fn
...>   [] -> {:cont, []}
...>   acc -> {:cont, Enum.reverse(acc), []}
...> end
iex> iter = 1..10 |> Impl.chunk_while([], chunk_fun, after_fun)
iex> Impl.to_list(iter)
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
@spec concat(iterable()) :: iterable()

Takes an iterable and iterates each iterable in an iterable.

Example

iex> Impl.concat([1..3, 2..4, 3..5]) |> Impl.to_list()
[1, 2, 3, 2, 3, 4, 3, 4, 5]
@spec count(iterable()) :: non_neg_integer()

Consumes the iterable, returning the number of elements within

Examples

iex> Impl.count([])
0

iex> Impl.count([1,2,3])
3
@spec count(iterable(), (element() -> as_boolean(any()))) :: non_neg_integer()

Consumes the iterable, returning the number of elements for which fun returns a truthy value.

Example

iex> 1..5
...> |> Impl.count(&(rem(&1, 2) == 0))
2
@spec cycle(iterable()) :: iterable()

Creates an iterator that cycles it's elements eternally.

Example

iex> Impl.cycle(1..3)
...> |> Impl.take_head(5)
...> |> Impl.to_list()
[1, 2, 3, 1, 2]
@spec dedup(iterable()) :: iterable()

Creates an iterable that only emits elements if they are different from the previous element.

Example

iex> Impl.dedup([:a, :a, :b, :c, :b, :c, :c, :d])
...> |> Impl.to_list()
[:a, :b, :c, :b, :c, :d]
@spec dedup_by(iterable(), (element() -> any())) :: iterable()

Creates an iterable that only emits elements if they are different from the previous element.

The function fun maps every element to a term which is used to determine if two elements are duplicates.

Example

iex> [{1, :a}, {2, :b}, {2, :c}, {1, :a}]
...> |> Impl.dedup_by(&elem(&1, 0))
...> |> Impl.to_list()
[{1, :a}, {2, :b}, {1, :a}]
Link to this function

drop(iterable, how_many)

View Source
@spec drop(iterable(), non_neg_integer()) :: iterable()

Creates an iterable which drops the first how_many elements.

Examples

iex> Impl.drop([1, 2, 3], 2)
...> |> Impl.to_list()
[3]

iex> Impl.drop([1, 2, 3], 0)
...> |> Impl.to_list()
[1, 2, 3]

iex> Impl.drop([1, 2, 3], -2)
...> |> Impl.to_list()
[1]
Link to this function

drop_every(iterable, nth)

View Source
@spec drop_every(iterable(), non_neg_integer()) :: iterable()

Returns a new iterable with every nth element in the iterable dropped, starting with the first element.

Examples

iex> 1..10
...> |> Impl.drop_every(2)
...> |> Impl.to_list()
[2, 4, 6, 8, 10]

iex> 1..12
...> |> Impl.drop_every(3)
...> |> Impl.to_list()
[2, 3, 5, 6, 8, 9, 11, 12]

iex> 1..10
...> |> Impl.drop_every(0)
...> |> Impl.to_list()
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

iex> [1, 2, 3]
...> |> Impl.drop_every(1)
...> |> Impl.to_list()
[]
Link to this function

drop_while(iterable, predicate)

View Source
@spec drop_while(iterable(), predicate()) :: iterable()

Drops elements at the beginning of iterable while fun returns a truthy value.

Example

iex> [1, 2, 3, 2, 1]
...> |> Impl.drop_while(&(&1 < 3))
...> |> Impl.to_list()
[3, 2, 1]
@spec each(iterable(), (element() -> any())) :: :done

Consumes the iterable and applies fun to each element.

Primarily used for side-effects.

Always returns :done.

Example

Impl.each([1, 2, 3], &IO.puts("#{&1}"))
"1"
"2"
"3"
#=> :done
@spec empty?(iterable()) :: boolean()

Determines if the iterable is empty.

Example

iex> Impl.empty?([])
true

iex> Impl.empty?(1..20)
false
Link to this function

filter(iterable, predicate)

View Source
@spec filter(iterable(), predicate()) :: iterable()

Creates an iterable which drops elements for which predicate doesn't return true.

Example

iex> Impl.filter([1, 2, 3, 4], &(rem(&1, 2) == 1))
...> |> Impl.to_list()
[1, 3]
Link to this function

find(iterable, predicate)

View Source
@spec find(iterable(), predicate()) :: {:ok, element()} | :done

Searches for the first element in the iterable which matches predicate.

Example

iex> Impl.find([1, 2, 3, 4], &(&1 > 2))
{:ok, 3, [4]}

iex> Impl.find([1, 2, 3, 4], &(&1 > 4))
:done
Link to this function

find_index(iterable, predicate)

View Source
@spec find_index(iterable(), predicate()) ::
  {:ok, non_neg_integer(), iterable()} | :done

Returns the index of the first element in the iterable which matches predicate.

Examples

iex> Impl.find_index([1, 2, 3, 4], &(&1 > 2))
{:ok, 2, [4]}

iex> Impl.find_index([1, 2, 3, 4], &(&1 > 4))
:done
Link to this function

find_value(iterable, fun)

View Source
@spec find_value(iterable(), (element() -> result)) ::
  {:ok, result, iterable()} | :done
when result: any()

Returns the first truthy value returned by fun.

Example

iex> Impl.find_value([1, 2, 3, 4], fn
...>   i when i > 2 -> i * 2
...>   _ -> nil
...> end)
{:ok, 6, [4]}
@spec flat_map(iterable(), (element() -> iterable() | element())) :: iterable()

Creates an iterable which works like map/2 but flattens nested iterables.

Example

iex> [:a, :b, :c]
...> |> Impl.flat_map(&[&1, &1])
...> |> Impl.to_list()
[:a, :a, :b, :b, :c, :c]
@spec flatten(iterable()) :: iterable()

Creates an iterable which flattens nested iterables.

Example

iex> Impl.flatten([[1, 2], [3, [4, [5, 6]]]])
...> |> Impl.to_list()
[1, 2, 3, 4, 5, 6]
Link to this function

intersperse(iterable, separator)

View Source
@spec intersperse(iterable(), any()) :: iterable()

Creates a new iterable which places separator between adjacent items of the original iterable.

Example

iex> Impl.intersperse([:a, :b, :c], :wat)
...> |> Impl.to_list()
[:a, :wat, :b, :wat, :c]
@spec map(iterable(), (element() -> new_element)) :: iterable()
when new_element: any()

Creates a new iterable which applies mapper to each element and using it's result as the new element value.

Example

iex> Impl.map([1, 2, 3], &(&1 * &1))
...> |> Impl.to_list()
[1, 4, 9]
Link to this function

map_every(iterable, nth, mapper)

View Source
@spec map_every(iterable(), non_neg_integer(), (element() -> new_element)) ::
  iterable()
when new_element: any()

Creates a new iterable which applies mapper on every nth element of the iterable, starting with the first element.

The first element is always mapped unless nth is 0.

Examples

iex> Impl.map_every(1..10, 2, fn x -> x + 1000 end)
...> |> Impl.to_list()
[1001, 2, 1003, 4, 1005, 6, 1007, 8, 1009, 10]

iex> Impl.map_every(1..10, 3, fn x -> x + 1000 end)
...> |> Impl.to_list()
[1001, 2, 3, 1004, 5, 6, 1007, 8, 9, 1010]

iex> Impl.map_every(1..5, 0, fn x -> x + 1000 end)
...> |> Impl.to_list()
[1, 2, 3, 4, 5]

iex> Impl.map_every([1, 2, 3], 1, fn x -> x + 1000 end)
...> |> Impl.to_list()
[1001, 1002, 1003]
@spec max(iterable(), (element(), element() -> boolean())) :: {:ok, element()} | :done

Returns the maximal element in the iterable according to Erlang's term ordering.

Examples

iex> Impl.max([1, 3, 2], &>=/2)
{:ok, 3}

iex> Impl.max([], &>=/2)
:done
Link to this function

max_by(iterable, mapper, sorter)

View Source
@spec max_by(
  iterable(),
  (element() -> new_element),
  (new_element, new_element -> boolean())
) ::
  {:ok, element()} | :done
when new_element: element()

Returns the maximal element in the iterable as calculated by mapper.

Example

iex> Impl.max_by(["a", "aa", "aaa"], &String.length/1, &>=/2)
{:ok, "aaa"}

iex> Impl.max_by([], &String.length/1, &>=/2)
:done
Link to this function

member?(iterable, element)

View Source
@spec member?(iterable(), element()) :: boolean()

Is the element a member of the iterable?

@spec min(iterable(), (element(), element() -> boolean())) :: {:ok, element()} | :done

Returns the minimal element in the iterable according to Erlang's term ordering.

Examples

iex> Impl.min([1, 3, 2], &<=/2)
{:ok, 1}

iex> Impl.min([], &<=/2)
:done
Link to this function

min_by(iterable, mapper, sorter)

View Source
@spec min_by(
  iterable(),
  (element() -> new_element),
  (new_element, new_element -> boolean())
) ::
  {:ok, element()} | :done
when new_element: element()

Returns the minimal element in the iterable as calculated by mapper.

Example

iex> Impl.min_by(["a", "aa", "aaa"], &String.length/1, &<=/2)
{:ok, "a"}

iex> Impl.min_by([], &String.length/1, &<=/2)
:done
@spec min_max(iterable()) :: {:ok, element(), element()} | :done

Finds the minimal and maximal elements in the iterable.

Example

iex> Impl.min_max(1..12)
{:ok, 1, 12}

iex> Impl.min_max([])
:done
@spec peek(iterable()) :: {:ok, element(), iterable()} | :done

Peeks at the first element of the iterable, without consuming it.

Warning

Many iterables cannot be peeked, so this function simulates peeking by consuming an element from the iterable and returning a new iterable which pushes that element back on to the front.

Example

iex> {:ok, :a, iterable} = Impl.peek([:a, :b, :c])
...> Impl.to_list(iterable)
[:a, :b, :c]
Link to this function

peek(iterable, how_many)

View Source
@spec peek(iterable(), how_many :: pos_integer()) ::
  {:ok, [element()], non_neg_integer(), iterable()} | :done

Peeks at the first how_many elements of the iterable, without consuming them.

Warning

Many iterables cannot be peeked, so this function simulates peeking by consuming elements from the iterable and returning a new iterable which pushes those elements back on to the front.

Example

iex> {:ok, [:a, :b, :c], 3, iterable} = Impl.peek([:a, :b, :c, :d], 3)
...> Impl.to_list(iterable)
[:a, :b, :c, :d]
Link to this function

prepend(iterable, element)

View Source
@spec prepend(iterable(), element()) :: iterable()

Creates a new iterable which places element at the beginning of the iterable.

Example

iex> 1..5
...> |> Impl.prepend(6)
...> |> Impl.to_list()
[6, 1, 2, 3, 4, 5]
Link to this function

step_by(iterable, step_size)

View Source
@spec step_by(iterable(), non_neg_integer()) :: iterable()

Creates an iterable starting at the same point, but stepping by how_many each iteration.

Example

iex> [0, 1, 2, 3, 4, 5]
...> |> Impl.step_by(2)
...> |> Impl.to_list()
[0, 2, 4]
Link to this function

take_chunk(iterable, how_many)

View Source
@spec take_chunk(iterable(), pos_integer()) ::
  {:ok, iterable(), iterable()} | {:done, iterable()}

Collects the first how_many elements into a new iterable and returns it along with the advanced initial iterable.

This is very much like take/2 except that it returns the remaining iterable so that it can be called repeatedly.

Example

iex> iter = 1..9
...> {:ok, [1, 2, 3], iter} = Impl.take_chunk(iter, 3)
...> {:ok, [4, 5, 6], iter} = Impl.take_chunk(iter, 3)
...> Impl.to_list(iter)
[7, 8, 9]
Link to this function

take_head(iterable, how_many)

View Source
@spec take_head(iterable(), non_neg_integer()) :: iterable()

Creates an iterable which takes the first how_many elements.

Example

iex> Impl.take_head(1..5, 0)
...> |> Impl.to_list()
[]

iex> Impl.take_head(1..5, 3)
...> |> Impl.to_list()
[1, 2, 3]
Link to this function

take_tail(iterable, how_many)

View Source
@spec take_tail(iterable(), non_neg_integer()) :: iterable()

Creates an iterable which takes the last how_many elements.

Example

iex> Impl.take_tail(1..5, 0)
...> |> Impl.to_list()
[]

iex> Impl.take_tail(1..5, 3)
...> |> Impl.to_list()
[3, 4, 5]
Link to this function

take_while(iterable, predicate)

View Source
@spec take_while(iterable(), predicate()) :: iterable()

Creates an iterable which emits elements until predicate returns false.

Example

iex> [1, 2, 3]
...> |> Impl.take_while(&(&1 < 3))
...> |> Impl.to_list()
[1, 2]
@spec to_list(iterable()) :: [element()]

Convert the iterable into a list.

@spec uniq(iterable()) :: iterable()

Creates an iterable that only emits unique elements.

Example

iex> Impl.uniq([:a, :a, :b, :c, :b, :c, :c, :d])
...> |> Impl.to_list()
[:a, :b, :c, :d]
@spec with_index(iterable()) :: iterable()

Creates an iterable which emits the current iteration count as well as the next value.

This is analogous to Enum.with_index/1 except that counting starts from the beginning of the iterable, meaning you can convert an iterable into an enumerator after consuming some if it.

Examples

iex> Impl.with_index([:a, :b, :c]) ...> |> Impl.to_list() [a: 0, b: 1, c: 2]

iex> [:a, :b, :c, :d] ...> |> Impl.drop(2) ...> |> Impl.with_index() ...> |> Impl.to_list() [c: 0, d: 1]

@spec zip(iterable(), ([element()] -> any())) :: iterable()

Zips corresponding elements from a finite collection of iterables into one iterable of results as computed by zipper.

Example

iex> Impl.zip([1..3, 4..6, 7..9], &List.to_tuple/1) ...> |> Impl.to_list() [{1, 4, 7}, {2, 5, 8}, {3, 6, 9}]