View Source Iter (iterex v0.1.1)

Functions for working with iterators.

An iterator is a struct that wraps any value which implements the Iter.Iterable protocol. Lists, maps and ranges are all common data types which can be used as iterators.

Explicit conversion

Whilst the Iter.Iterable protocol is designed to work with many different types, you must explicitly convert your iterables into an iterator using Iter.from/1. This allows for easy pattern matching of iterators as well as for default implementations of Elixir's Enum and Collectable protocols.

Any value passed to Iter.from/1 must implement the Iter.IntoIterable protocol.

Lazy by default

Like Elixir's Stream, an Iter is lazy by default. Any function which returns an Iter.t does so by simply composing iterables on top of each other. No iteration is performed until it is needed, and then only the minimum amount needed to return the result.

Summary

Functions

Returns true if all elements in the iterator are truthy.

Returns true if fun.(element) is truthy for all elements in the iterator.

Returns true if at least one element in the iterator is truthy.

Returns true if fun.(element) is truthy for at least one element in the iterator.

Append a new element to the end of the iterable.

Return the element index items from the beginning of the iterator.

Chunks the iterator by buffering elements for which fun returns the same value.

Shortcut to chunk_every(iterable, count, count).

Consumes the iterator in chunks, containing count elements each, where each new chunk steps step elements into the iterator.

Chunks the iterator with fine grained control of when every chunk is emitted.

Creates an iterator that concatenates an iterator of iterators.

Creates an iterator that iterates the first argument, followed by the second argument.

Count the number of elements remaining in the iterator.

Count the number of elements for which fun returns a truthy value.

Counts the elements in iterator stopping at limit.

Counts the elements of iterator for which predicate returns a truthy value, stopping at limit.

Create an iterator that cycles it's elements eternally.

Remove consecutive duplicate elements from the iterator.

Remove consecutive elements for which fun returns duplicate values from the iterator.

Returns a new iterator which drops the first how_many elements.

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

Returns a new iterator which drops elements at the beginning of the iterator until predicate returns a truthy value.

Call fun for every element in the iterator.

Returns an iterator that contains no elements.

Determines if the iterator is empty.

Remove elements for which predicate returns a truthy value.

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

Finds the index of the first value in the iterator that matches predicate.

Similar to find/3, but returns the value of the function invocation instead of the element itself.

Maps fun over the iterator flattening the result.

Flattens nested iterators.

Convert anything that implements Iter.IntoIterable into an Iter.

Intersperses separator between each element of the iterator.

Is the passed value an iterator?

Emits a sequence of values, starting with start_value. Successive values are generated by calling next_fun on the previous value.

Apply fun to each element in the iterator and collect the result.

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

Returns the maximal element in the iterator according to Erlang's term sorting.

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

Checks if element is a member of iterable.

Returns the minimal element in the iterator according to Erlang's term sorting.

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

Returns the minimal and maximal element in the iterator according to Erlang's term ordering.

Advance the iterator and return the next value.

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

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

Prepend a new element to the beginning of the iterable.

Keep elements for which predicate returns a truthy value.

Returns an iterator generated by calling generator_fun repeatedly.

Create an iterator from a resource.

Creates an iterator starting at the same point, but stepping by step_size each iteration.

Takes the next count elements from the iterable and stops iteration.

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

Creates an iterable which emits elements until predicate returns false.

Convert an iterator into a list.

Convert an iterator into an Elixir stream.

Creates a new iterator which returns only unique elements.

Creates a new iterator which replaces each element with a tuple containing the original element and the count of elements so far.

Zips corresponding elements from a finite collection of iterators into one iterator of tuples.

Zips to iterators together.

Zips corresponding elements from a finite collection of iterators into a new iterator, transforming them with zip_fun as it goes.

Zips corresponding elements from two iterators into a new one, transforming them with zip_fun as it goes.

Types

@type element() :: any()
@type mapper() :: (element() -> any())
@type predicate() :: (element() -> as_boolean(any()))
@type sorter() :: (element(), element() -> as_boolean(any()))
@type t() :: %Iter{iterable: Iter.Iterable.t()}

Functions

@spec all?(t()) :: boolean()

Returns true if all elements in the iterator are truthy.

Examples

iex> [1, 2, false]
...> |> Iter.from()
...> |> Iter.all?()
false

iex> [1, 2, nil]
...> |> Iter.from()
...> |> Iter.all?()
false

iex> [1, 2, 3]
...> |> Iter.from()
...> |> Iter.all?()
true
@spec all?(t(), predicate()) :: boolean()

Returns true if fun.(element) is truthy for all elements in the iterator.

Iterates over the iterator and invokes fun on each element. If fun ever returns a falsy value (false or nil), iteration stops immediately and false is returned. Otherwise true is returned.

Examples

iex> [2, 4, 6]
...> |> Iter.from()
...> |> Iter.all?(&(rem(&1, 2) == 0))
true

iex> [2, 3, 4]
...> |> Iter.from()
...> |> Iter.all?(&(rem(&1, 2) == 0))
false

iex> []
...> |> Iter.from()
...> |> Iter.all?()
true
@spec any?(t()) :: boolean()

Returns true if at least one element in the iterator is truthy.

When an element is a truthy value (neither false nor nil) iteration stops immediately and true is returned. In all other cases false is returned.

Examples

iex> [false, false, false]
...> |> Iter.from()
...> |> Iter.any?()
false

iex> [false, true, false]
...> |> Iter.from()
...> |> Iter.any?()
true

iex> []
...> |> Iter.from()
...> |> Iter.any?()
false
Link to this function

any?(iterable, predicate)

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

Returns true if fun.(element) is truthy for at least one element in the iterator.

Consumes the iterator and invokes fun on each element. When an invocation of fun returns a truthy value (neither false nor nil) iteration stops immediately and true is returned. In all other cases false is returned.

Examples

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

iex> [2, 3, 4]
...> |> Iter.from()
...> |> Iter.any?(&(rem(&1, 2) == 1))
true

iex> []
...> |> Iter.from()
...> |> Iter.any?(&(rem(&1, 2) == 1))
false
@spec append(t(), element()) :: t()

Append a new element to the end of the iterable.

Example

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

Return the element index items from the beginning of the iterator.

Works by advancing the iterator the specified number of elements and then returning the element requested and an iterator of the remaining elements.

Return values

  • {:ok, element, new_iterator} - the element requested and the iterator of the remaining elements.
  • :done - the iterator was exhausted before the element was found.

Examples

iex> 10..20
...> |> Iter.from()
...> |> Iter.at(5)
{:ok, 15, Iter.from(16..20)}
@spec chunk_by(t(), (element() -> any())) :: t()

Chunks the iterator by buffering elements for which fun returns the same value.

Elements are only emitted when fun returns a new value or iterable is exhausted.

Examples

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

chunk_every(iter, count)

View Source
@spec chunk_every(t(), pos_integer()) :: t()

Shortcut to chunk_every(iterable, count, count).

Link to this function

chunk_every(iter, count, step)

View Source

Consumes the iterator in chunks, containing count elements each, where each new chunk steps step elements into the iterator.

step is optional and, if not passed defaults to count, i.e. chunks do not overlap. Chunking will stop as soon as the iterable is exhausted or when we emit an incomplete chunk.

If the last chunk does not have chunk elements to fill the chunk, elements are taken from leftover to fill in the chunk, if leftover does not have enough elements to fill the chunk, then a partial chunk is returned with less than count elements.

If :discard is given in leftover the last chunk is discarded unless it has exactly count elements.

Examples

iex> [a, b, c] = [1, 2, 3, 4, 5, 6]
...> |> Iter.from()
...> |> Iter.chunk_every(2)
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2]
iex> Iter.to_list(b)
[3, 4]
iex> Iter.to_list(c)
[5, 6]

iex> [a, b] = [1, 2, 3, 4, 5, 6]
...> |> Iter.from()
...> |> Iter.chunk_every(3, 2, :discard)
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2, 3]
iex> Iter.to_list(b)
[3, 4, 5]

iex> [a, b, c] = [1, 2, 3, 4, 5, 6]
...> |> Iter.from()
...> |> Iter.chunk_every(3, 2, [7] |> Iter.from())
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2, 3]
iex> Iter.to_list(b)
[3, 4, 5]
iex> Iter.to_list(c)
[5, 6, 7]

iex> [a, b] = [1, 2, 3, 4, 5, 6]
...> |> Iter.from()
...> |> Iter.chunk_every(3, 3, [] |> Iter.from())
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2, 3]
iex> Iter.to_list(b)
[4, 5, 6]

iex> [a, b] = [1, 2, 3, 4]
...> |> Iter.from()
...> |> Iter.chunk_every(3, 3, [0] |> Iter.from() |> Iter.cycle())
...> |> Iter.to_list()
iex> Iter.to_list(a)
[1, 2, 3]
iex> Iter.to_list(b)
[4, 0, 0]
Link to this function

chunk_every(iter, count, step, leftover)

View Source
@spec chunk_every(t(), pos_integer(), pos_integer(), t() | :discard) :: Enumerable.t()
Link to this function

chunk_while(iter, acc, chunk_fun, after_fun)

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

Chunks the iterator with fine grained control of when every chunk is emitted.

chunk_fun receives the current element and the accumulator and must return {:cont, element, acc} to emit the given chunk and continue with accumulator or {:cont, acc} to not emit any chunk and continue with the return accumulator.

after_fun is invoked when iteration is done and must also return {:cont, element, acc} or {:cont, acc}.

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> 1..10
...> |> Iter.from()
...> |> Iter.chunk_while([], chunk_fun, after_fun)
...> |> Iter.to_list()
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
@spec concat(t()) :: t()

Creates an iterator that concatenates an iterator of iterators.

Example

iex> [Iter.from(1..2), Iter.from(3..4)]
...> |> Iter.from()
...> |> Iter.concat()
...> |> Iter.to_list()
[1, 2, 3, 4]
@spec concat(t(), t()) :: t()

Creates an iterator that iterates the first argument, followed by the second argument.

Example

iex> lhs = Iter.from(1..3)
...> rhs = Iter.from(4..6)
...> Iter.concat(lhs, rhs) |> Iter.to_list()
[1, 2, 3, 4, 5, 6]
@spec count(t()) :: non_neg_integer()

Count the number of elements remaining in the iterator.

Some iterators can be counted without consuming the iterator, but most cannot and you should consider the iterator passed to this function as having been exhausted.

Example

iex> 1..10
...> |> Iter.from()
...> |> Iter.count()
10
@spec count(t(), (element() -> as_boolean(any()))) :: non_neg_integer()

Count the number of elements for which fun returns a truthy value.

Example

iex> 1..5
...> |> Iter.from()
...> |> Iter.count(&(rem(&1, 2) == 0))
2
Link to this function

count_until(iter, limit)

View Source
@spec count_until(t(), pos_integer()) :: {:ok, non_neg_integer(), t()}

Counts the elements in iterator stopping at limit.

Examples

iex> 1..20
...> |> Iter.from()
...> |> Iter.count_until(5)
{:ok, 5, Iter.from(6..20)}

iex> 1..3
...> |> Iter.from()
...> |> Iter.count_until(5)
{:ok, 3, Iter.empty()}

iex> []
...> |> Iter.from()
...> |> Iter.count_until(5)
{:ok, 0, Iter.empty()}
Link to this function

count_until(iter, predicate, limit)

View Source
@spec count_until(t(), predicate(), pos_integer()) :: {:ok, non_neg_integer(), t()}

Counts the elements of iterator for which predicate returns a truthy value, stopping at limit.

Examples

iex> 1..20
...> |> Iter.from()
...> |> Iter.count_until(&(rem(&1, 2) == 0), 7)
{:ok, 7, Iter.from(15..20)}

iex> 1..20
...> |> Iter.from()
...> |> Iter.count_until(&(rem(&1, 2) == 0), 11)
{:ok, 10, Iter.empty()}
@spec cycle(t()) :: t() | no_return()

Create an iterator that cycles it's elements eternally.

iex> [:a, :b, :c]
...> |> Iter.from()
...> |> Iter.cycle()
...> |> Iter.take(5)
...> |> Iter.to_list()
[:a, :b, :c, :a, :b]
@spec dedup(t()) :: t()

Remove consecutive duplicate elements from the iterator.

Example

iex> [1, 1, 2, 3, 3, 4, 5, 4]
...> |> Iter.from()
...> |> Iter.dedup()
...> |> Iter.to_list()
[1, 2, 3, 4, 5, 4]
@spec dedup_by(t(), (element() -> any())) :: t()

Remove consecutive elements for which fun returns duplicate values from the iterator.

Example

iex> [{1, :a}, {2, :b}, {2, :c}, {1, :a}] ...> |> Iter.from() ...> |> Iter.dedup_by(&elem(&1, 0)) ...> |> Iter.to_list() [{1, :a}, {2, :b}, {1, :a}]

@spec drop(t(), non_neg_integer()) :: t()

Returns a new iterator which drops the first how_many elements.

Examples

iex> 1..3
...> |> Iter.from()
...> |> Iter.drop(2)
...> |> Iter.to_list()
[3]
@spec drop_every(t(), non_neg_integer()) :: t()

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

Examples

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

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

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

drop_while(iter, predicate)

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

Returns a new iterator which drops elements at the beginning of the iterator until predicate returns a truthy value.

Example

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

Call fun for every element in the iterator.

The return value is not used.

Example

["marty", "doc"]
|> Iter.from()
|> Iter.each(&IO.puts/1)
"marty"
"doc"
#=> :done
@spec empty() :: t()

Returns an iterator that contains no elements.

Example

iex> Iter.empty()
...> |> Iter.to_list()
[]
@spec empty?(t()) :: boolean()

Determines if the iterator is empty.

Examples

iex> Iter.empty()
...> |> Iter.empty?()
true

iex> 1..20
...> |> Iter.from()
...> |> Iter.empty?
false
@spec filter(t(), predicate()) :: t()

Remove elements for which predicate returns a truthy value.

Example

iex> [1, 2, 3, 4]
...> |> Iter.from()
...> |> Iter.filter(&(rem(&1, 2) == 0))
...> |> Iter.to_list()
[2, 4]
@spec find(t(), predicate()) :: {:ok, element(), t()} | :done

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

Example

iex> [1, 2, 3, 4, 5]
...> |> Iter.from()
...> |> Iter.find(&(&1 > 3))
{:ok, 4, Iter.from([5])}

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

find_index(iter, predicate)

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

Finds the index of the first value in the iterator that matches predicate.

Example

iex> [1, 2, 3, 4, 5]
...> |> Iter.from()
...> |> Iter.find_index(&(&1 > 3))
{:ok, 3, Iter.from([5])}
@spec find_value(t(), (element() -> any())) :: {:ok, any(), t()} | :done

Similar to find/3, but returns the value of the function invocation instead of the element itself.

Example

iex> [2, 3, 4]
...> |> Iter.from()
...> |> Iter.find_value(fn x ->
...>   if x > 2, do: x * x
...> end)
{:ok, 9, Iter.from([4])}

iex> [2, 4, 6]
...> |> Iter.from()
...> |> Iter.find_value(&(rem(&1, 2) == 1))
:done

iex> [2, 3, 4]
...> |> Iter.from()
...> |> Iter.find_value(&(rem(&1, 2) == 1))
{:ok, true, Iter.from([4])}
@spec flat_map(t(), mapper()) :: t()

Maps fun over the iterator flattening the result.

Example

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

Flattens nested iterators.

Example

iex> [[:a, :a], [:b, :b], [:c, :c]]
...> |> Iter.from()
...> |> Iter.flatten()
...> |> Iter.to_list()
[:a, :a, :b, :b, :c, :c]
@spec from(Iter.IntoIterable.t()) :: t()

Convert anything that implements Iter.IntoIterable into an Iter.

Link to this function

intersperse(iter, separator)

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

Intersperses separator between each element of the iterator.

Examples

iex> 1..3
...> |> Iter.from()
...> |> Iter.intersperse(0)
...> |> Iter.to_list()
[1, 0, 2, 0, 3]

iex> [1]
...> |> Iter.from()
...> |> Iter.intersperse(0)
...> |> Iter.to_list()
[1]

iex> []
...> |> Iter.from()
...> |> Iter.intersperse(0)
...> |> Iter.to_list()
[]
Link to this macro

is_iter(value)

View Source (macro)
@spec is_iter(any()) :: Macro.output()

Is the passed value an iterator?

Link to this function

iterate(start_value, next_fun)

View Source
@spec iterate(element(), (element() -> element())) :: t()

Emits a sequence of values, starting with start_value. Successive values are generated by calling next_fun on the previous value.

iex> Iter.iterate(0, &(&1 + 1))
...> |> Iter.take(5)
...> |> Iter.to_list()
[0, 1, 2, 3, 4]
@spec map(t(), mapper()) :: t()

Apply fun to each element in the iterator and collect the result.

Example

iex> [1, 2, 3, 4]
...> |> Iter.from()
...> |> Iter.map(&(&1 * 2))
...> |> Iter.to_list()
[2, 4, 6, 8]
Link to this function

map_every(iter, nth, mapper)

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

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

The first element is always mapped unless nth is 0.

Examples

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

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

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

iex> 1..3
...> |> Iter.from()
...> |> Iter.map_every(1, fn x -> x + 1000 end)
...> |> Iter.to_list()
[1001, 1002, 1003]
Link to this function

max(iter, sorter \\ &>=/2)

View Source
@spec max(t(), sorter()) :: {:ok, element()} | :done

Returns the maximal element in the iterator according to Erlang's term sorting.

Example

iex> [1, 4, 3, 2]
...> |> Iter.from()
...> |> Iter.max()
{:ok, 4}

iex> Iter.empty()
...> |> Iter.max()
:done
Link to this function

max_by(iter, mapper, sorter \\ &>=/2)

View Source
@spec max_by(t(), mapper(), sorter()) :: {:ok, element()} | :done

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

Example

iex> ["a", "aa", "aaa"]
...> |> Iter.from()
...> |> Iter.max_by(&String.length/1)
{:ok, "aaa"}

iex> Iter.empty()
...> |> Iter.max_by(&String.length/1)
:done
@spec member?(t(), element()) :: boolean()

Checks if element is a member of iterable.

Examples

iex> 1..5
...> |> Iter.from()
...> |> Iter.member?(3)
true

iex> 1..5
...> |> Iter.from()
...> |> Iter.member?(6)
false
Link to this function

min(iter, sorter \\ &<=/2)

View Source
@spec min(t(), sorter()) :: {:ok, element()} | :done

Returns the minimal element in the iterator according to Erlang's term sorting.

Example

iex> [1, 4, 3, 2]
...> |> Iter.from()
...> |> Iter.min()
{:ok, 1}
Link to this function

min_by(iter, mapper, sorter \\ &<=/2)

View Source
@spec min_by(t(), mapper(), sorter()) :: {:ok, element()} | :done

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

Example

iex> ["a", "aa", "aaa"]
...> |> Iter.from()
...> |> Iter.min_by(&String.length/1)
{:ok, "a"}

iex> Iter.empty()
...> |> Iter.min_by(&String.length/1)
:done
@spec min_max(t()) :: {:ok, min, max} | :done when min: element(), max: element()

Returns the minimal and maximal element in the iterator according to Erlang's term ordering.

Example

iex> [2, 3, 1]
...> |> Iter.from()
...> |> Iter.min_max()
{:ok, 1, 3}

iex> Iter.empty()
...> |> Iter.min_max()
:done
@spec next(t()) :: {:ok, element(), t()} | :done

Advance the iterator and return the next value.

Return values

  • {:ok, element, new_iterator} - returns the next element and an updated iterator.
  • :done - the iterator is exhausted.
@spec peek(t()) :: {:ok, element(), t()} | :done

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

Warning

Many iterators cannot be peeked, so this function simulates peeking by consuming an element from the iterator and returning a new iterator which pushes that element back onto the front.

Example

iex> {:ok, 1, iter} = 1..3
...> |> Iter.from()
...> |> Iter.peek()
...> Iter.to_list(iter)
[1, 2, 3]
@spec peek(t(), how_many :: pos_integer()) ::
  {:ok, [element()], non_neg_integer(), t()} | :done

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

Warning

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

Because it's possible to try and peek past the end of an iterator you shouldn't expect the number of elements returned to always be the same as how many you asked for. For this reason the return value includes the number of elements that were able to be peeked.

Example

iex> {:ok, peeks, 3, iter} = 1..5
...> |> Iter.from()
...> |> Iter.peek(3)
iex> Iter.to_list(peeks)
[1, 2, 3]
iex> Iter.to_list(iter)
[1, 2, 3, 4, 5]

iex> {:ok, peeks, 3, iter} = 1..3
...> |> Iter.from()
...> |> Iter.peek(5)
iex> Iter.to_list(peeks)
[1, 2, 3]
iex> Iter.to_list(iter)
[1, 2, 3]
@spec prepend(t(), element()) :: t()

Prepend a new element to the beginning of the iterable.

Example

iex> 1..3
...> |> Iter.from()
...> |> Iter.prepend(4)
...> |> Iter.to_list()
[4, 1, 2, 3]
@spec reject(t(), predicate()) :: t()

Keep elements for which predicate returns a truthy value.

Example

iex> [1, 2, 3, 4]
...> |> Iter.from()
...> |> Iter.reject(&(rem(&1, 2) == 0))
...> |> Iter.to_list()
[1, 3]
Link to this function

repeatedly(generator_fun)

View Source
@spec repeatedly((-> element())) :: t()

Returns an iterator generated by calling generator_fun repeatedly.

Examples

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Iter.repeatedly(&:rand.uniform/0) |> Iter.take(3) |> Iter.to_list()
[0.5455598952593053, 0.6039309974353404, 0.6684893034823949]
Link to this function

resource(start_fun, next_fun, after_fun)

View Source
@spec resource(
  start_fun :: (-> acc),
  next_fun :: (acc -> {[element()], acc} | {:halt, acc}),
  after_fun :: (acc -> any())
) :: t()
when acc: any()

Create an iterator from a resource.

iex> Iter.resource(
...>   fn ->
...>     {:ok, pid} = StringIO.open("Marty")
...>     pid
...>   end,
...>   fn pid ->
...>     case IO.read(pid, 1) do
...>       :eof -> {:halt, pid}
...>       char -> {[char], pid}
...>     end
...>   end,
...>   fn pid ->
...>     StringIO.close(pid)
...>   end
...> )
...> |> Iter.to_list()
["M", "a", "r", "t", "y"]
@spec step_by(t(), pos_integer()) :: t()

Creates an iterator starting at the same point, but stepping by step_size each iteration.

The first element of the iterator will always be returned, regardless of the step given.

Examples

  iex> 1..9
  ...> |> Iter.from()
  ...> |> Iter.step_by(3)
  ...> |> Iter.to_list()
  [1, 4, 7]
@spec take(t(), integer()) :: t()

Takes the next count elements from the iterable and stops iteration.

If a negative count is given, the last count values will be taken. For such, the collection is fully enumerated keeping up to count elements in memory. Once the end of the collection is reached, the last count elements will be iterated. Therefore, using a negative count on an infinite collection will never return.

The rest of the underlying iterable is discarded.

Examples

iex> Iter.empty()
...> |> Iter.take(3)
...> |> Iter.to_list()
[]

iex> Iter.empty()
...> |> Iter.take(-3)
...> |> Iter.to_list()
[]

iex> 1..5
...> |> Iter.from()
...> |> Iter.take(3)
...> |> Iter.to_list()
[1, 2, 3]

iex> 1..5
...> |> Iter.from()
...> |> Iter.take(-3)
...> |> Iter.to_list()
[3, 4, 5]
Link to this function

take_chunk(iter, how_many)

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

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

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

Example

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

take_while(iter, predicate)

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

Creates an iterable which emits elements until predicate returns false.

The rest of the underlying iterable is discarded.

Example

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

Convert an iterator into a list.

@spec to_stream(t()) :: Enumerable.t()

Convert an iterator into an Elixir stream.

Example

iex> [:a, :b, :c]
...> |> Iter.from()
...> |> Iter.cycle()
...> |> Iter.to_stream()
...> |> Enum.take(5)
[:a, :b, :c, :a, :b]
@spec uniq(t()) :: t()

Creates a new iterator which returns only unique elements.

Warning

Except for specific data structures (eg MapSet and Range) most iterators will need to store a set of "seen values" in order to provide this function. In such cases memory usage will grow in direct relation to the number of unique elements in the iterator.

Example

iex> 1..5
...> |> Iter.from()
...> |> Iter.uniq()
Iter.from(1..5)

iex> [1, 2, 3, 2, 1]
...> |> Iter.from()
...> |> Iter.uniq()
...> |> Iter.to_list()
[1, 2, 3]
@spec with_index(t()) :: t()

Creates a new iterator which replaces each element with a tuple containing the original element and the count of elements so far.

Example

iex> 1..3
...> |> Iter.from()
...> |> Iter.with_index()
...> |> Iter.to_list()
[{1, 0}, {2, 1}, {3, 2}]
@spec zip(t()) :: t()

Zips corresponding elements from a finite collection of iterators into one iterator of tuples.

The zipping finishes as soon as any iterable in the collection is exhausted.

Example

iex> first = Iter.from(1..3)
...> second = Iter.from([:a, :b, :c])
...> third = Iter.from(["a", "b", "c"])
...> [first, second, third]
...> |> Iter.from()
...> |> Iter.zip()
...> |> Iter.to_list()
[{1, :a, "a"}, {2, :b, "b"}, {3, :c, "c"}]
@spec zip(t(), t()) :: t()

Zips to iterators together.

The zipping finishes as soon as either iterator is exhausted.

Example

iex> first = Iter.from(1..3)
...> second = Iter.from([:a, :b, :c])
...> Iter.zip(first, second)
...> |> Iter.to_list()
[{1, :a}, {2, :b}, {3, :c}]
@spec zip_with(t(), ([element()] -> any())) :: t()

Zips corresponding elements from a finite collection of iterators into a new iterator, transforming them with zip_fun as it goes.

The first element from each of the iterators will be put into a list which is then passed to the one-arity zip_fun function. Then, the second elements from each of the iterators are put into a list, and so on until any of the iterators are exhausted.

Example

iex> first = Iter.from(1..3)
...> second = Iter.from(4..6)
...> third = Iter.from(7..9)
...> [first, second, third]
...> |> Iter.from()
...> |> Iter.zip_with(fn [a, b, c] -> a + b + c end)
...> |> Iter.to_list()
[12, 15, 18]
Link to this function

zip_with(lhs, rhs, zipper)

View Source
@spec zip_with(t(), t(), (element(), element() -> any())) :: t()

Zips corresponding elements from two iterators into a new one, transforming them with zip_fun as it goes.

The zip_fun will be called with the first elements from the iterators, then the second elements and so on.

Example

iex> first = Iter.from(1..3)
...> second = Iter.from(4..6)
...> Iter.zip_with(first, second, &(&1 + &2))
...> |> Iter.to_list()
[5, 7, 9]