Iter (Iter v0.1.3)
View SourceA 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()
385Iter 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
requirethe module first before using it - they won't appear in the stacktrace in case of errors (but
Itertries to make sure that stacktraces will point to the line of the step responsible) - if you "break" the pipeline,
Iterwon't be able to optimize it as a single pass: it will suffer the same issue asEnum
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) andIter.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
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
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
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
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
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
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
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]
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]
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
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
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]
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}]
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]
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]
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]
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]
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
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
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
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]
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
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
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
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
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
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
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
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]
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}
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}
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"]}
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"]}
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]
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])
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])
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"
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"
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
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
Applies fun on each element of enumerable. Equivalent to Enum.map/2.
Examples
iex> Iter.map(1..3, & &1 ** 2)
[1, 4, 9]
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]
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"
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"
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}
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]
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
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
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
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
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
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
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
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
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]
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]
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]
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]
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]
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]
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]
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]
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]
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"]
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]}
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]}
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]}
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
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]
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]
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]
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]
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]
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]
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}]
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]}
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}]
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"]
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"}]
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}]