View Source Iter (Iter v0.1.2)

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

overview

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.

The benchmarks folder illustrates how Iter compares to Enum or Stream through some examples.

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

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

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

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

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.

Link to this section 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.

Link to this section Functions

Link to this macro

all?(enumerable)

View Source (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

Examples

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

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

iex> Iter.all?([])
true
Link to this macro

all?(enumerable, fun)

View Source (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

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

any?(enumerable)

View Source (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

Examples

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

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

iex> Iter.any?([])
false
Link to this macro

any?(enumerable, fun)

View Source (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

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

at(enumerable, index)

View Source (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

Examples

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

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

at(enumerable, index, default)

View Source (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

Examples

iex> Iter.at(1..1000, 5, :none)
6
iex> Iter.at(1..1000, 1000, :none)
:none
Link to this macro

concat(enumerable)

View Source (macro)

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

examples

Examples

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

concat(left, right)

View Source (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

Examples

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

count(enumerable)

View Source (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

Examples

iex> Iter.count([1, 2, 3])
3
Link to this macro

count(enumerable, fun)

View Source (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

Examples

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

dedup(enumerable)

View Source (macro)

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

examples

Examples

iex> Iter.dedup([1, 2, 2, 3, 3, 1, 3])
[1, 2, 3, 1, 3]
Link to this macro

dedup_by(enumerable, fun)

View Source (macro)

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

examples

Examples

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

drop(enumerable, amount)

View Source (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

Examples

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

drop_every(enumerable, nth)

View Source (macro)

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

examples

Examples

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

drop_while(enumerable, fun)

View Source (macro)

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

examples

Examples

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

each(enumerable, fun)

View Source (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

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

empty?(enumerable)

View Source (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

Examples

iex> Iter.empty?([])
true

iex> Iter.empty?([:foo])
false
Link to this macro

fetch(enumerable, index)

View Source (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

Examples

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

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

fetch!(enumerable, index)

View Source (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

Examples

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

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

filter(enumerable, fun)

View Source (macro)

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

examples

Examples

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

find(enumerable, fun)

View Source (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

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

find(enumerable, default, fun)

View Source (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

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

find_index(enumerable, fun)

View Source (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

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

find_value(enumerable, fun)

View Source (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

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

find_value(enumerable, default, fun)

View Source (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

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

first(enumerable)

View Source (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

Examples

iex> Iter.first(1..1000)
1
iex> Iter.first([])
nil
Link to this macro

first(enumerable, default)

View Source (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

Examples

iex> Iter.first(1..10, :none)
1
iex> Iter.first([], :none)
:none
Link to this macro

flat_map(enumerable, fun)

View Source (macro)

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

examples

Examples

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

frequencies(enumerable)

View Source (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

Examples

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

frequencies_by(enumerable, key_fun)

View Source (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

Examples

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

group_by(enumerable, key_fun)

View Source (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

Examples

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

group_by(enumerable, key_fun, value_fun)

View Source (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

Examples

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

intersperse(enumerable, separator)

View Source (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

Examples

iex> Iter.intersperse(1..3, :foo)
[1, :foo, 2, :foo, 3]
Link to this macro

into(enumerable, collectable)

View Source (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

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

into(enumerable, collectable, fun)

View Source (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

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

join(enumerable)

View Source (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

Examples

iex> Iter.join(1..3)
"123"
Link to this macro

join(enumerable, joiner)

View Source (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

Examples

iex> Iter.join(1..3, "-")
"1-2-3"
Link to this macro

last(enumerable)

View Source (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

Examples

iex> Iter.last(1..10)
10
iex> Iter.last([])
nil
Link to this macro

last(enumerable, default)

View Source (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

Examples

iex> Iter.last(1..10, :none)
10
iex> Iter.last([], :none)
:none
Link to this macro

map(enumerable, fun)

View Source (macro)

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

examples

Examples

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

map_intersperse(enumerable, separator, fun)

View Source (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

Examples

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

map_join(enumerable, mapper)

View Source (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

Examples

iex> Iter.map_join(1..3, & &1 ** 2)
"149"
Link to this macro

map_join(enumerable, joiner, mapper)

View Source (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

Examples

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

map_reduce(enumerable, acc, fun)

View Source (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

Examples

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

match(enumerable, pattern, expr)

View Source (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

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

max(enumerable)

View Source (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

Examples

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

iex> Iter.max([])
** (Enum.EmptyError) empty error
Link to this macro

mean(enumerable)

View Source (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

Examples

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

iex> Iter.mean([])
** (Enum.EmptyError) empty error
Link to this macro

member?(enumerable, element)

View Source (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

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

min(enumerable)

View Source (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

Examples

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

iex> Iter.min([])
** (Enum.EmptyError) empty error
Link to this macro

product(enumerable)

View Source (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

Examples

iex> Iter.product(1..3)
6
Link to this macro

random(enumerable)

View Source (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

Examples

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

reduce(enumerable, fun)

View Source (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

Examples

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

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

reduce(enumerable, acc, fun)

View Source (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

Examples

iex> Iter.reduce(1..5, 1, &*/2)
120
Link to this macro

reject(enumerable, fun)

View Source (macro)

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

examples

Examples

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

reverse(enumerable)

View Source (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

Examples

iex> Iter.reverse(1..3)
[3, 2, 1]
Link to this macro

reverse(enumerable, tail)

View Source (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

Examples

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

scan(enumerable, acc, fun)

View Source (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

Examples

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

shuffle(enumerable)

View Source (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

Examples

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

slice(enumerable, index_range)

View Source (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

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

slice(enumerable, start_index, amount)

View Source (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

Examples

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

sort(enumerable)

View Source (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

Examples

iex> Iter.sort([4, 1, 5, 2, 3])
[1, 2, 3, 4, 5]
Link to this macro

sort(enumerable, sorter)

View Source (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

Examples

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

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

View Source

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

Examples

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

split(enumerable, amount)

View Source (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

Examples

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

split_while(enumerable, fun)

View Source (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

Examples

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

split_with(enumerable, fun)

View Source (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

Examples

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

sum(enumerable)

View Source (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

Examples

iex> Iter.sum(1..3)
6
Link to this macro

take(enumerable, amount)

View Source (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

Examples

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

take_every(enumerable, nth)

View Source (macro)

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

examples

Examples

iex> Iter.take_every(1..10, 3)
[1, 4, 7, 10]
Link to this macro

take_random(enumerable, amount)

View Source (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

Examples

# Although not necessary, let's seed the random algorithm
iex> :rand.seed(:exsss, {1, 2, 3})
iex> Iter.take_random(1..100, 3)
[74, 28, 55]
Link to this macro

take_while(enumerable, fun)

View Source (macro)

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

examples

Examples

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

to_list(enumerable)

View Source (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

Examples

iex> Iter.to_list(1..3)
[1, 2, 3]
Link to this macro

uniq(enumerable)

View Source (macro)

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

examples

Examples

iex> Iter.uniq([1, 2, 1, 3, 2, 4])
[1, 2, 3, 4]
Link to this macro

uniq_by(enumerable, fun)

View Source (macro)

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

examples

Examples

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

unzip(enumerable)

View Source (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

Examples

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

with_index(enumerable)

View Source (macro)

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

examples

Examples

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

with_index(enumerable, fun_or_offset)

View Source (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

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"]

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

Examples

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

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

Examples

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