Iter (Iter v0.1.3)

View Source

A blazing fast compile-time optimized alternative to the Enum and Stream modules.

Overview

Iter allows you to effortlessly write highly-efficient pipelines to process enumerables, in a familiar and highly readable style.

iex> require Iter
iex> 1..10 |> Iter.map(& &1 ** 2) |> Iter.sum()
385

Iter will merge both the map and sum steps and perform both in one single pass. Unlike the same pipeline written with Enum, it won't build any intermediate list, therefore saving memory and CPU cycles.

You can think of Iter as compile-time streams, or as comprehensions on steroids. It should be highly efficient compared to the same pipeline written with Stream, since it does most of the work at compile time without any runtime overhead. And while it actually works very similarly to for/1 under the hood and basically emits the same code, it offers a much more flexible, composable and extensive API.

Because Iter is compile-time, these are macros and not functions. This has several implications:

  • you have to require the module first before using it
  • they won't appear in the stacktrace in case of errors (but Iter tries to make sure that stacktraces will point to the line of the step responsible)
  • if you "break" the pipeline, Iter won't be able to optimize it as a single pass: it will suffer the same issue as Enum
1..10
|> Iter.map(& &1 ** 2)
|> IO.inspect() # <= pipeline broken, creates an intermediate list
|> Iter.sum()

When there is no possibility of merging steps, Iter is simply delegating to Enum which is optimized plenty on individual steps.

Consistency

Iter is mostly consistent with the standard library, but it is prioritizing efficiency over absolute consistency with the Enum and Stream modules, which implies some slight differences. These differences are always documented in the concerned macro docs.

Negative indexes

Iter only supports positive indexes when inside a pipeline, so most of functions like at/1, slice/1 or take/1 which would also accept negative indexes cannot be replaced in cases needing it. The reason is simple: working with negative indexes implies to materialize the whole list once. If you need it, you should replace the relevant step to use Enum, or maybe call Iter.reverse/1 before accessing it (see Collecting the pipeline section).

API differences

Iter should cover most of the Enum API, but:

  • some operations are still missing
  • some operations won't be added because cannot be implemented efficiently
  • some extra functions are being provided: Iter.mean/1, Iter.first/1, Iter.last/1 (to compensate with the lack of negative indexes) and Iter.match/3 (pattern-match to filter and extract at once, like in comprehensions)

Collecting the pipeline

Some operations like Iter.to_list/1, Iter.reverse/2, Iter.reduce/3, Iter.group_by/2... need to materialize an intermediate list or accumulator and will collect the pipeline.

Operations that are collecting the pipeline are always mentioning it in their documentation.

Here is a simple example:

users
|> Iter.map(&fetch_user/1)
|> Iter.reject(&is_nil/1)
|> Iter.each(&process_user/1)

The pipeline above will start processing users as they are retrieved, in one single pass. But assuming we want to make sure to be able to first retrieving all users before starting the processing step, Iter.to_list/1 can be used to make the intent explicit:

users
|> Iter.map(&fetch_user/1)
|> Iter.reject(&is_nil/1)
|> Iter.to_list()  # forcing the pipeline to collect
|> Iter.each(&process_user/1)

Forcing a pipeline to collect through Enum.to_list/1 (or Enum.reverse/1, faster) can also be used to circumvent some of Iter's limitations like the absence of negative indexes support:

foo
|> Iter.map(&bar/1)
|> Iter.to_list()  # forcing the pipeline to collect
|> Iter.take(maybe_negative_index)

In the example above, Iter.take/2 is now the only step of its pipeline and can support negative indexing. The extra pass required is made explicit.

Summary

Functions

Returns true if all elements in enumerable are truthy. Equivalent to Enum.all?/1.

Returns true if fun returns a truthy value for all elements in enumerable. Equivalent to Enum.all?/2.

Returns true if at least one element in enumerable is truthy. Equivalent to Enum.any?/1.

Returns true if fun returns a truthy value for at least one element in enumerable. Equivalent to Enum.any?/2.

Finds the element at the given index (zero-based). Equivalent to Enum.at/2.

Finds the element at the given index (zero-based). Equivalent to Enum.at/3.

Given an enumerable of enumerables, concatenates the enumerables into a single one. Equivalent to Enum.concat/1.

Concatenates the enumerable on the right with the enumerable on the left. Equivalent to Enum.concat/2.

Returns the size of the enumerable. Equivalent to Enum.count/1.

Returns the count of elements in the enumerable for which fun returns a truthy value. Equivalent to Enum.count/2.

Enumerates the enumerable, removing successive duplicate elements. Equivalent to Enum.dedup/1.

Enumerates the enumerable, removing successive elements for which fun return duplicate values. Equivalent to Enum.dedup_by/2.

Drops an amount of elements from the beginning of the enumerable. Equivalent to Enum.drop/2.

Returns a list of every nth element in the enumerable dropped, starting with the first element. Equivalent to Enum.drop_every/2.

Drops elements at the beginning of the enumerable, while fun returns a truthy value. Equivalent to Enum.drop_while/2.

Invokes the given fun for each element in the enumerable. Equivalent to Enum.each/2.

Returns true if enumerable is empty, otherwise false. Equivalent to Enum.empty?/1.

Finds the element at the given index (zero-based). Equivalent to Enum.fetch/2.

Finds the element at the given index (zero-based). Equivalent to Enum.fetch!/2.

Filters the enumerable, keeping only elements for which fun returns a truthy value. Equivalent to Enum.filter/2.

Returns the first element for which fun returns a truthy value. Equivalent to Enum.find/2.

Returns the first element for which fun returns a truthy value, returns default if not found.any() Equivalent to Enum.find/3.

Similar to find/2, but returns the index (zero-based) of the element instead of the element itself. Equivalent to Enum.find_index/2.

Similar to find/2, but returns the value of the function invocation instead of the element itself. Equivalent to Enum.find_value/2.

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

Retrieves the first element of the enumerable, or nil if empty.

Retrieves the first element of the enumerable, or default if empty.

Maps the given fun over enumerable and flattens the result. Equivalent to Enum.flat_map/2.

Returns a map with keys as unique elements of enumerable and values as the count of every element. Equivalent to Enum.frequencies/1.

Returns a map with keys as unique elements given by key_fun and values as the count of every element. Equivalent to Enum.frequencies_by/2.

Splits the enumerable into groups based on key_fun. Equivalent to Enum.group_by/2.

Splits the enumerable into groups based on key_fun. Equivalent to Enum.group_by/3.

Intersperses separator between each element of the enumerable. Equivalent to Enum.intersperse/2.

Inserts the given enumerable into a collectable. Equivalent to Enum.into/2.

Inserts the given enumerable into a collectable and maps the fun function on each item. Equivalent to Enum.into/3.

Joins the given enumerable into a string without any separator. Equivalent to Enum.join/1.

Joins the given enumerable into a string with joiner as a separator. Equivalent to Enum.join/2.

Retrieves the last element of the enumerable, or nil if empty.

Retrieves the last element of the enumerable, or default if empty.

Applies fun on each element of enumerable. Equivalent to Enum.map/2.

Maps and intersperses the given enumerable with separator. Equivalent to Enum.map_intersperse/3.

Applies mapper and joins the given enumerable into a string without any separator. Equivalent to Enum.map_join/2.

Applies mapper and joins the given enumerable into a string with joiner as a separator. Equivalent to Enum.map_join/3.

Invokes the given function to each element in the enumerable to reduce it to a single element, while keeping an accumulator. Equivalent to Enum.map_reduce/3.

Pattern-matches on each element of the enumerable, filters out elements that do not match the pattern, and returns the expr.

Returns the maximal element in the enumerable according to Erlang's term ordering. Equivalent to Enum.max/1.

Returns the mean value of all elements in enumerable.

Checks if element exists within the enumerable. Equivalent to Enum.member?/2.

Returns the minimal element in the enumerable according to Erlang's term ordering. Equivalent to Enum.min/1.

Returns the product of all elements in enumerable. Equivalent to Enum.product/1.

Returns a random element of the enumerable. Equivalent to Enum.random/1.

Invokes fun for each element in the enumerable with the accumulator. Equivalent to Enum.reduce/2.

Invokes fun for each element in the enumerable with the accumulator. Equivalent to Enum.reduce/3.

Filters the enumerable, rejecting elements for which fun returns a truthy value. Equivalent to Enum.reject/2.

Returns a list of elements in enumerable in reverse order. Equivalent to Enum.reverse/1.

Reverses the elements in enumerable, appends the tail, and returns the result as a list. Equivalent to Enum.reverse/2.

Applies the given function to each element in the enumerable, storing the result in a list and passing it as the accumulator for the next computation. Equivalent to Enum.scan/3.

Returns a list with enumerable elements in a random order. Equivalent to Enum.shuffle/1.

Returns a subset list of the given enumerable by index_range. Equivalent to Enum.slice/2.

Returns a subset list of the given enumerable, from start_index with amount number of elements if available. Equivalent to Enum.slice/3.

Sorts the enumerable according to Erlang's term ordering. Equivalent to Enum.sort/1.

Sorts the enumerable by the given sorter function or module. Equivalent to Enum.sort/2.

Sorts the mapped results of the enumerable according to Erlang's term ordering. Equivalent to Enum.sort_by/2.

Splits the enumerable into two lists, leaving amount elements in the first one. Equivalent to Enum.split/2.

Splits the enumerable in two at the position of the element for which fun returns a falsy value for the first time. Equivalent to Enum.split_while/2.

Splits the enumerable in two lists based on the truthiness of applying fun on each element. Equivalent to Enum.split_with/2.

Returns the sum of all elements in enumerable. Equivalent to Enum.sum/1.

Takes an amount of elements from the beginning of the enumerable. Equivalent to Enum.take/2.

Returns a list of every nth element in the enumerable, starting with the first element. Equivalent to Enum.take_every/2.

Takes an amount of random elements from the enumerable. Equivalent to Enum.take_random/2.

Takes the elements from the beginning of the enumerable, while fun returns a truthy value. Equivalent to Enum.take_while/2.

Converts enumerable to a list. Equivalent to Enum.to_list/1.

Enumerates the enumerable, removing the duplicate elements. Equivalent to Enum.uniq/1.

Enumerates the enumerable, removing elements for which fun return duplicate values. Equivalent to Enum.uniq_by/2.

Extracts two-element tuples from the given enumerable and returns them as two separate lists. Equivalent to Enum.unzip/1.

Returns the enumerable with each element wrapped in a tuple alongside its index. Equivalent to Enum.with_index/1.

Returns the enumerable with each element wrapped in a tuple alongside its index. Equivalent to Enum.with_index/2.

Zips corresponding elements from a finite collection of enumerables into a list of tuples.

Zips corresponding elements from two enumerables into a list of tuples.

Functions

all?(enumerable)

(macro)

Returns true if all elements in enumerable are truthy. Equivalent to Enum.all?/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.all?(["yes", true])
true

iex> Iter.all?([false, true])
false

iex> Iter.all?([])
true

all?(enumerable, fun)

(macro)

Returns true if fun returns a truthy value for all elements in enumerable. Equivalent to Enum.all?/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Enum.all?([2, 4, 6], fn x -> rem(x, 2) == 0 end)
true

iex> Enum.all?([2, 3, 4], fn x -> rem(x, 2) == 0 end)
false

iex> Iter.all?([], fn x -> rem(x, 2) == 0 end)
true

any?(enumerable)

(macro)

Returns true if at least one element in enumerable is truthy. Equivalent to Enum.any?/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

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

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

iex> Iter.any?([])
false

any?(enumerable, fun)

(macro)

Returns true if fun returns a truthy value for at least one element in enumerable. Equivalent to Enum.any?/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Enum.any?([2, 4, 6], fn x -> rem(x, 2) == 1 end)
false

iex> Enum.any?([2, 3, 4], fn x -> rem(x, 2) == 1 end)
true

iex> Iter.any?([], fn x -> rem(x, 2) == 1 end)
false

at(enumerable, index)

(macro)

Finds the element at the given index (zero-based). Equivalent to Enum.at/2.

Returns nil if not found.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Note: Negative indexes are NOT supported when used in a pipeline, since this would imply to materialize the whole list and therefore cannot be done lazily. If you need to use negative indexes, you can either use materialize the pipeline first using Iter.to_list/1 or use the equivalent Enum function. Read the Collecting the pipeline section for more information.

Also, see Iter.last/1 if you need to access the last element.

Examples

iex> Iter.at([:foo, :bar, :baz], 2)
:baz

iex> Iter.at([:foo, :bar, :baz], 3)
nil

at(enumerable, index, default)

(macro)

Finds the element at the given index (zero-based). Equivalent to Enum.at/3.

Returns default if not found.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Note: Negative indexes are NOT supported when used in a pipeline, since this would imply to materialize the whole list and therefore cannot be done lazily. If you need to use negative indexes, you can either use materialize the pipeline first using Iter.to_list/1 or use the equivalent Enum function. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.at(1..1000, 5, :none)
6
iex> Iter.at(1..1000, 1000, :none)
:none

concat(enumerable)

(macro)

Given an enumerable of enumerables, concatenates the enumerables into a single one. Equivalent to Enum.concat/1.

Examples

iex> Iter.concat([1..3, 4..6])
[1, 2, 3, 4, 5, 6]

concat(left, right)

(macro)

Concatenates the enumerable on the right with the enumerable on the left. Equivalent to Enum.concat/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.concat(1..3, 4..6)
[1, 2, 3, 4, 5, 6]

count(enumerable)

(macro)

Returns the size of the enumerable. Equivalent to Enum.count/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.count([1, 2, 3])
3

count(enumerable, fun)

(macro)

Returns the count of elements in the enumerable for which fun returns a truthy value. Equivalent to Enum.count/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.count(1..5, fn x -> rem(x, 2) == 0 end)
2

dedup(enumerable)

(macro)

Enumerates the enumerable, removing successive duplicate elements. Equivalent to Enum.dedup/1.

Examples

iex> Iter.dedup([1, 2, 2, 3, 3, 1, 3])
[1, 2, 3, 1, 3]

dedup_by(enumerable, fun)

(macro)

Enumerates the enumerable, removing successive elements for which fun return duplicate values. Equivalent to Enum.dedup_by/2.

Examples

iex> Iter.dedup_by([{1, :a}, {2, :b}, {2, :c}, {1, :a}], fn {x, _} -> x end)
[{1, :a}, {2, :b}, {1, :a}]

drop(enumerable, amount)

(macro)

Drops an amount of elements from the beginning of the enumerable. Equivalent to Enum.drop/2.

Note: Negative indexes are NOT supported when used in a pipeline, since this would imply to materialize the whole list and therefore cannot be done lazily. If you need to use negative indexes, you can either use materialize the pipeline first using Iter.to_list/1 or use the equivalent Enum function. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.drop(1..10, 5)
[6, 7, 8, 9, 10]

drop_every(enumerable, nth)

(macro)

Returns a list of every nth element in the enumerable dropped, starting with the first element. Equivalent to Enum.drop_every/2.

Examples

iex> Iter.drop_every(1..10, 3)
[2, 3, 5, 6, 8, 9]

drop_while(enumerable, fun)

(macro)

Drops elements at the beginning of the enumerable, while fun returns a truthy value. Equivalent to Enum.drop_while/2.

Examples

iex> Iter.drop_while(1..10, & &1 < 6)
[6, 7, 8, 9, 10]

each(enumerable, fun)

(macro)

Invokes the given fun for each element in the enumerable. Equivalent to Enum.each/2.

Returns :ok.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> {:ok, pid} = Agent.start(fn -> [] end)
iex> Iter.each(1..5, fn i -> Agent.update(pid, &[i | &1]) end)
:ok
iex> Agent.get(pid, & &1)
[5, 4, 3, 2, 1]

empty?(enumerable)

(macro)

Returns true if enumerable is empty, otherwise false. Equivalent to Enum.empty?/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.empty?([])
true

iex> Iter.empty?([:foo])
false

fetch(enumerable, index)

(macro)

Finds the element at the given index (zero-based). Equivalent to Enum.fetch/2.

Returns {:ok, element} if found, otherwise :error.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Note: Negative indexes are NOT supported when used in a pipeline, since this would imply to materialize the whole list and therefore cannot be done lazily. If you need to use negative indexes, you can either use materialize the pipeline first using Iter.to_list/1 or use the equivalent Enum function. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.fetch([:foo, :bar, :baz], 2)
{:ok, :baz}

iex> Iter.fetch([:foo, :bar, :baz], 3)
:error

fetch!(enumerable, index)

(macro)

Finds the element at the given index (zero-based). Equivalent to Enum.fetch!/2.

Raises OutOfBoundsError if the given index is outside the range of the enumerable.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Note: Negative indexes are NOT supported when used in a pipeline, since this would imply to materialize the whole list and therefore cannot be done lazily. If you need to use negative indexes, you can either use materialize the pipeline first using Iter.to_list/1 or use the equivalent Enum function. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.fetch!([:foo, :bar, :baz], 2)
:baz

iex> Iter.fetch!([:foo, :bar, :baz], 3)
** (Enum.OutOfBoundsError) out of bounds error

filter(enumerable, fun)

(macro)

Filters the enumerable, keeping only elements for which fun returns a truthy value. Equivalent to Enum.filter/2.

Examples

iex> Iter.filter(1..4, &rem(&1, 2) == 1)
[1, 3]

find(enumerable, fun)

(macro)

Returns the first element for which fun returns a truthy value. Equivalent to Enum.find/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.find([2, 3, 4], fn x -> rem(x, 2) == 1 end)
3

iex> Iter.find([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

find(enumerable, default, fun)

(macro)

Returns the first element for which fun returns a truthy value, returns default if not found.any() Equivalent to Enum.find/3.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.find([2, 3, 4], 0, fn x -> rem(x, 2) == 1 end)
3

iex> Iter.find([2, 4, 6], 0, fn x -> rem(x, 2) == 1 end)
0

find_index(enumerable, fun)

(macro)

Similar to find/2, but returns the index (zero-based) of the element instead of the element itself. Equivalent to Enum.find_index/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.find_index(["ant", "bat", "cat"], fn x -> x =~ "b" end)
1

iex> Iter.find_index(["ant", "bat", "cat"], fn x -> x =~ "z" end)
nil

find_value(enumerable, fun)

(macro)

Similar to find/2, but returns the value of the function invocation instead of the element itself. Equivalent to Enum.find_value/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.find_value([%{x: nil}, %{x: 5}, %{}], fn map -> map[:x] end)
5

iex> Iter.find_value([%{x: nil}, %{}, %{}], fn map -> map[:x] end)
nil

find_value(enumerable, default, fun)

(macro)

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

Returns default if not found.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.find_value([%{x: nil}, %{x: 5}, %{}], 0, fn map -> map[:x] end)
5

iex> Iter.find_value([%{x: nil}, %{}, %{}], 0, fn map -> map[:x] end)
0

first(enumerable)

(macro)

Retrieves the first element of the enumerable, or nil if empty.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

There is no equivalent Enum function.

Examples

iex> Iter.first(1..1000)
1
iex> Iter.first([])
nil

first(enumerable, default)

(macro)

Retrieves the first element of the enumerable, or default if empty.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

There is no equivalent Enum function.

Examples

iex> Iter.first(1..10, :none)
1
iex> Iter.first([], :none)
:none

flat_map(enumerable, fun)

(macro)

Maps the given fun over enumerable and flattens the result. Equivalent to Enum.flat_map/2.

Examples

iex> Iter.flat_map(1..3, fn n -> 1..n end)
[1, 1, 2, 1, 2, 3]

frequencies(enumerable)

(macro)

Returns a map with keys as unique elements of enumerable and values as the count of every element. Equivalent to Enum.frequencies/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.frequencies([1, 1, 2, 1, 2, 3])
%{1 => 3, 2 => 2, 3 => 1}

frequencies_by(enumerable, key_fun)

(macro)

Returns a map with keys as unique elements given by key_fun and values as the count of every element. Equivalent to Enum.frequencies_by/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.frequencies_by(~w{aa aA bb cc}, &String.downcase/1)
%{"aa" => 2, "bb" => 1, "cc" => 1}

group_by(enumerable, key_fun)

(macro)

Splits the enumerable into groups based on key_fun. Equivalent to Enum.group_by/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.group_by(~w{ant buffalo cat dingo}, &String.length/1)
%{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}

group_by(enumerable, key_fun, value_fun)

(macro)

Splits the enumerable into groups based on key_fun. Equivalent to Enum.group_by/3.

The result is a map where each key is given by key_fun and each value is a list of elements given by value_fun.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.group_by(~w{ant buffalo cat dingo}, &String.length/1, &String.first/1)
%{3 => ["a", "c"], 5 => ["d"], 7 => ["b"]}

intersperse(enumerable, separator)

(macro)

Intersperses separator between each element of the enumerable. Equivalent to Enum.intersperse/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.intersperse(1..3, :foo)
[1, :foo, 2, :foo, 3]

into(enumerable, collectable)

(macro)

Inserts the given enumerable into a collectable. Equivalent to Enum.into/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.into([a: 1, b: 2, a: 3], %{})
%{a: 3, b: 2}

iex> Iter.into([1, 2, 1, 2.0], MapSet.new())
MapSet.new([1, 2, 2.0])

into(enumerable, collectable, fun)

(macro)

Inserts the given enumerable into a collectable and maps the fun function on each item. Equivalent to Enum.into/3.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.into([a: 1, b: 2, a: 3], %{}, fn {k, v} -> {k, v * 2} end)
%{a: 6, b: 4}

iex> Iter.into([1, 2, 1, 2.0], MapSet.new(), & &1 * 2)
MapSet.new([2, 4, 4.0])

join(enumerable)

(macro)

Joins the given enumerable into a string without any separator. Equivalent to Enum.join/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.join(1..3)
"123"

join(enumerable, joiner)

(macro)

Joins the given enumerable into a string with joiner as a separator. Equivalent to Enum.join/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.join(1..3, "-")
"1-2-3"

last(enumerable)

(macro)

Retrieves the last element of the enumerable, or nil if empty.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

There is no equivalent Enum function, but it can compensate for the lack of negative index support in at/2.

Examples

iex> Iter.last(1..10)
10
iex> Iter.last([])
nil

last(enumerable, default)

(macro)

Retrieves the last element of the enumerable, or default if empty.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

There is no equivalent Enum function, but it can compensate for the lack of negative index support in at/3.

Examples

iex> Iter.last(1..10, :none)
10
iex> Iter.last([], :none)
:none

map(enumerable, fun)

(macro)

Applies fun on each element of enumerable. Equivalent to Enum.map/2.

Examples

iex> Iter.map(1..3, & &1 ** 2)
[1, 4, 9]

map_intersperse(enumerable, separator, fun)

(macro)

Maps and intersperses the given enumerable with separator. Equivalent to Enum.map_intersperse/3.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.map_intersperse(1..3, :foo, & &1 ** 2)
[1, :foo, 4, :foo, 9]

map_join(enumerable, mapper)

(macro)

Applies mapper and joins the given enumerable into a string without any separator. Equivalent to Enum.map_join/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.map_join(1..3, & &1 ** 2)
"149"

map_join(enumerable, joiner, mapper)

(macro)

Applies mapper and joins the given enumerable into a string with joiner as a separator. Equivalent to Enum.map_join/3.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.map_join(1..3, "-", & &1 ** 2)
"1-4-9"

map_reduce(enumerable, acc, fun)

(macro)

Invokes the given function to each element in the enumerable to reduce it to a single element, while keeping an accumulator. Equivalent to Enum.map_reduce/3.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.map_reduce([1, 2, 3], 0, fn x, acc -> {x * 2, x + acc} end)
{[2, 4, 6], 6}

match(enumerable, pattern, expr)

(macro)

Pattern-matches on each element of the enumerable, filters out elements that do not match the pattern, and returns the expr.

This works a bit like a combination of map/2 and filter/2 and works very similarly as for/1 comprehensions.

There is no equivalent Enum function.

Examples

iex> Iter.match([{:ok, 1}, :error, {:ok, 3}], {:ok, x}, x + 1)
[2, 4]

The pattern also supports guards:

iex> Iter.match([1, nil, 3], x when is_integer(x), x * 2)
[2, 6]

max(enumerable)

(macro)

Returns the maximal element in the enumerable according to Erlang's term ordering. Equivalent to Enum.max/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.max([2, 4, 1, 3])
4

iex> Iter.max([])
** (Enum.EmptyError) empty error

mean(enumerable)

(macro)

Returns the mean value of all elements in enumerable.

Raises Enum.EmptyError if enumerable is empty.

There is no equivalent Enum function.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.mean(1..10)
5.5

iex> Iter.mean([])
** (Enum.EmptyError) empty error

member?(enumerable, element)

(macro)

Checks if element exists within the enumerable. Equivalent to Enum.member?/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Enum.member?([:ant, :bat, :cat], :bat)
true

iex> Enum.member?([:ant, :bat, :cat], :dog)
false

iex> Iter.member?([1, 2, 3], 2.0)
false

min(enumerable)

(macro)

Returns the minimal element in the enumerable according to Erlang's term ordering. Equivalent to Enum.min/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.min([2, 4, 1, 3])
1

iex> Iter.min([])
** (Enum.EmptyError) empty error

product(enumerable)

(macro)

Returns the product of all elements in enumerable. Equivalent to Enum.product/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.product(1..3)
6

random(enumerable)

(macro)

Returns a random element of the enumerable. Equivalent to Enum.random/1.

Raises Enum.EmptyError if enumerable is empty.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Iter.random(1..100)
27

reduce(enumerable, fun)

(macro)

Invokes fun for each element in the enumerable with the accumulator. Equivalent to Enum.reduce/2.

Raises Enum.EmptyError if enumerable is empty. The first element of the enumerable is used as the initial value of the accumulator.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.reduce(1..5, &*/2)
120

iex> Iter.reduce([], &*/2)
** (Enum.EmptyError) empty error

reduce(enumerable, acc, fun)

(macro)

Invokes fun for each element in the enumerable with the accumulator. Equivalent to Enum.reduce/3.

The value of acc is used as the initial value of the accumulator.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.reduce(1..5, 1, &*/2)
120

reject(enumerable, fun)

(macro)

Filters the enumerable, rejecting elements for which fun returns a truthy value. Equivalent to Enum.reject/2.

Examples

iex> Iter.reject(1..4, &rem(&1, 2) == 1)
[2, 4]

reverse(enumerable)

(macro)

Returns a list of elements in enumerable in reverse order. Equivalent to Enum.reverse/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.reverse(1..3)
[3, 2, 1]

reverse(enumerable, tail)

(macro)

Reverses the elements in enumerable, appends the tail, and returns the result as a list. Equivalent to Enum.reverse/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.reverse(1..3, 4..6)
[3, 2, 1, 4, 5, 6]

scan(enumerable, acc, fun)

(macro)

Applies the given function to each element in the enumerable, storing the result in a list and passing it as the accumulator for the next computation. Equivalent to Enum.scan/3.

Examples

iex> Iter.scan(1..5, 1, &*/2)
[1, 2, 6, 24, 120]

shuffle(enumerable)

(macro)

Returns a list with enumerable elements in a random order. Equivalent to Enum.shuffle/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Iter.shuffle(1..6)
[6, 4, 1, 5, 2, 3]

slice(enumerable, index_range)

(macro)

Returns a subset list of the given enumerable by index_range. Equivalent to Enum.slice/2.

Note: Negative indexes are NOT supported when used in a pipeline, since this would imply to materialize the whole list and therefore cannot be done lazily. If you need to use negative indexes, you can either use materialize the pipeline first using Iter.to_list/1 or use the equivalent Enum function. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.slice(1..100, 5..15)
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]

iex> Iter.slice(1..100, 5..15//5)
[6, 11, 16]

slice(enumerable, start_index, amount)

(macro)

Returns a subset list of the given enumerable, from start_index with amount number of elements if available. Equivalent to Enum.slice/3.

Note: Negative indexes are NOT supported when used in a pipeline, since this would imply to materialize the whole list and therefore cannot be done lazily. If you need to use negative indexes, you can either use materialize the pipeline first using Iter.to_list/1 or use the equivalent Enum function. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.slice(1..100, 5, 10)
[6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

sort(enumerable)

(macro)

Sorts the enumerable according to Erlang's term ordering. Equivalent to Enum.sort/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.sort([4, 1, 5, 2, 3])
[1, 2, 3, 4, 5]

sort(enumerable, sorter)

(macro)

Sorts the enumerable by the given sorter function or module. Equivalent to Enum.sort/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.sort([4, 1, 5, 2, 3], :desc)
[5, 4, 3, 2, 1]

sort_by(enumerable, fun, sorter \\ :asc)

Sorts the mapped results of the enumerable according to Erlang's term ordering. Equivalent to Enum.sort_by/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

This is actually just an alias for Enum.sort_by/2, Iter isn't able to optimize it.

Examples

iex> Iter.sort_by(["some", "kind", "of", "monster"], &byte_size/1)
["of", "some", "kind", "monster"]

split(enumerable, amount)

(macro)

Splits the enumerable into two lists, leaving amount elements in the first one. Equivalent to Enum.split/2.

Note: Negative indexes are NOT supported when used in a pipeline, since this would imply to materialize the whole list and therefore cannot be done lazily. If you need to use negative indexes, you can either use materialize the pipeline first using Iter.to_list/1 or use the equivalent Enum function. Read the Collecting the pipeline section for more information.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.split(1..10, 5)
{[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]}

split_while(enumerable, fun)

(macro)

Splits the enumerable in two at the position of the element for which fun returns a falsy value for the first time. Equivalent to Enum.split_while/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.split_while(1..10, & &1 < 6)
{[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]}

split_with(enumerable, fun)

(macro)

Splits the enumerable in two lists based on the truthiness of applying fun on each element. Equivalent to Enum.split_with/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.split_with(1..4, &rem(&1, 2) == 1)
{[1, 3], [2, 4]}

sum(enumerable)

(macro)

Returns the sum of all elements in enumerable. Equivalent to Enum.sum/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.sum(1..3)
6

take(enumerable, amount)

(macro)

Takes an amount of elements from the beginning of the enumerable. Equivalent to Enum.take/2.

Note: Negative indexes are NOT supported when used in a pipeline, since this would imply to materialize the whole list and therefore cannot be done lazily. If you need to use negative indexes, you can either use materialize the pipeline first using Iter.to_list/1 or use the equivalent Enum function. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.take(1..1000, 5)
[1, 2, 3, 4, 5]

take_every(enumerable, nth)

(macro)

Returns a list of every nth element in the enumerable, starting with the first element. Equivalent to Enum.take_every/2.

Examples

iex> Iter.take_every(1..10, 3)
[1, 4, 7, 10]

take_random(enumerable, amount)

(macro)

Takes an amount of random elements from the enumerable. Equivalent to Enum.take_random/2.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Iter.take_random(1..100, 3)
[92, 45, 9]

take_while(enumerable, fun)

(macro)

Takes the elements from the beginning of the enumerable, while fun returns a truthy value. Equivalent to Enum.take_while/2.

Examples

iex> Iter.take_while(1..1000, & &1 < 6)
[1, 2, 3, 4, 5]

to_list(enumerable)

(macro)

Converts enumerable to a list. Equivalent to Enum.to_list/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.to_list(1..3)
[1, 2, 3]

uniq(enumerable)

(macro)

Enumerates the enumerable, removing the duplicate elements. Equivalent to Enum.uniq/1.

Examples

iex> Iter.uniq([1, 2, 1, 3, 2, 4])
[1, 2, 3, 4]

uniq_by(enumerable, fun)

(macro)

Enumerates the enumerable, removing elements for which fun return duplicate values. Equivalent to Enum.uniq_by/2.

Examples

iex> Iter.uniq_by([{1, :x}, {2, :y}, {1, :z}], fn {x, _} -> x end)
[{1, :x}, {2, :y}]

unzip(enumerable)

(macro)

Extracts two-element tuples from the given enumerable and returns them as two separate lists. Equivalent to Enum.unzip/1.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.unzip([{:a, 1}, {:b, 2}, {:c, 3}])
{[:a, :b, :c], [1, 2, 3]}

with_index(enumerable)

(macro)

Returns the enumerable with each element wrapped in a tuple alongside its index. Equivalent to Enum.with_index/1.

Examples

iex> Iter.with_index(["a", "b", "c"])
[{"a", 0}, {"b", 1}, {"c", 2}]

with_index(enumerable, fun_or_offset)

(macro)

Returns the enumerable with each element wrapped in a tuple alongside its index. Equivalent to Enum.with_index/2.

Like Enum.with_index/2, accepts either an anonymous function or an integer offset, but it has to infer the type at compile time. If the expression can't be inferred to be either an fn or a capture, it will assume it is an integer (example: Iter.with_index(list, var) will only work if var is an integer).

If an offset is given, it will index from the given offset instead of from zero.

If a function is given, it will index by invoking the function for each element and index (zero-based) of the enumerable.

Examples

iex> Iter.with_index(["a", "b", "c"], 100)
[{"a", 100}, {"b", 101}, {"c", 102}]

iex> Iter.with_index(["a", "b", "c"], fn elem, index -> String.duplicate(elem, index) end)
["", "b", "cc"]

iex> Iter.with_index(["a", "b", "c"], &String.duplicate(&1, &2))
["", "b", "cc"]

zip(enumerables)

Zips corresponding elements from a finite collection of enumerables into a list of tuples.

This is actually just an alias for Enum.zip/1, Iter isn't able to optimize it.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.zip([[1, 2, 3], [:a, :b, :c], ["foo", "bar", "baz"]])
[{1, :a, "foo"}, {2, :b, "bar"}, {3, :c, "baz"}]

zip(left, right)

Zips corresponding elements from two enumerables into a list of tuples.

This is actually just an alias for Enum.zip/2, Iter isn't able to optimize it.

Note: This step collects the pipeline and cannot be merged with following steps. Read the Collecting the pipeline section for more information.

Examples

iex> Iter.zip([1, 2, 3, 4, 5], [:a, :b, :c])
[{1, :a}, {2, :b}, {3, :c}]