infiniyield
Types
pub type Step(element, accumulator) {
Next(element: element, accumulator: accumulator)
}
Constructors
-
Next(element: element, accumulator: accumulator)
A yielder is a lazily evaluated infinite sequence of elements.
As a lazy data structure no work is done when a yielder is filtered,
mapped, etc, instead a new yielder is returned with these transformations
applied to the stream. Once the stream has all the required transformations
applied it can be evaluated using functions such as take and step.
pub opaque type Yielder(element)
Values
pub fn at(in yielder: Yielder(e), get index: Int) -> e
Returns nth element yielded by the given yielder, where 0 means the first element.
For any index less than 0 this function behaves as if it was set to 0.
Examples
cycle([1, 2, 3, 4]) |> at(2)
// -> 3
cycle([1, 2, 3, 4]) |> at(4)
// -> 1
pub fn chunk(
over yielder: Yielder(element),
by f: fn(element) -> key,
) -> Yielder(List(element))
Creates a yielder that emits chunks of elements
for which f returns the same value.
Examples
cycle([1, 2, 2, 3, 4, 4, 6, 7, 7])
|> chunk(by: fn(n) { n % 2 })
|> take(5)
// -> [[1], [2, 2], [3], [4, 4, 6], [7, 7, 1]]
pub fn cycle(list: List(a)) -> Yielder(a)
Creates a yielder that repeats a given list infinitely.
If an empty list is provided, attempting to yield a value from the yielder will result in an infinite loop.
Examples
cycle([1, 2]) |> take(6)
// -> [1, 2, 1, 2, 1, 2]
pub fn decrementing(from start: Int) -> Yielder(Int)
Creates a yielder of ints, starting at a given start int and decrementing by one each time.
Examples
incrementing(from: 5) |> take(5)
// -> [5, 4, 3, 2, 1]
pub fn drop(yielder: Yielder(e), desired: Int) -> Yielder(e)
Evaluates and discards the first N elements in a yielder, returning a new yielder.
This function does not evaluate the elements of the yielder, the computation is performed when the yielder is later run.
Examples
cycle([1, 2, 3, 4, 5])
|> drop(3)
|> take(3)
// -> [4, 5]
pub fn drop_while(
in yielder: Yielder(element),
satisfying predicate: fn(element) -> Bool,
) -> Yielder(element)
Creates a yielder that drops elements while the predicate returns True,
and then yields the remaining elements.
Examples
cycle([1, 2, 3, 4, 2, 5])
|> drop_while(satisfying: fn(x) { x < 4 })
|> take(3)
// -> [4, 2, 5]
pub fn each(
over yielder: Yielder(a),
with f: fn(a) -> b,
) -> Yielder(Nil)
Transform a yielder into one that calls the given function on each element.
Like map, but always returns Nil for each element after calling the given
transformation function.
Examples
cycle(["Tom", "Malory", "Louis"]) |> each(io.println) |> take(3)
// -> Nil
// Tom
// Malory
// Louis
pub fn filter(
yielder: Yielder(a),
keeping predicate: fn(a) -> Bool,
) -> Yielder(a)
Creates a yielder from an existing yielder and a predicate function.
The new yielder will contain elements from the first yielder for which
the given function returns True.
This function does not evaluate the elements of the yielder, the computation is performed when the yielder is later run.
Examples
import gleam/int
cycle([1, 2, 3, 4])
|> filter(int.is_even)
|> take(2)
// -> [2, 4]
pub fn filter_map(
yielder: Yielder(a),
keeping_with f: fn(a) -> Result(b, c),
) -> Yielder(b)
Creates a yielder from an existing yielder and a transforming predicate function.
The new yielder will contain elements from the first yielder for which
the given function returns Ok, transformed to the value inside the Ok.
This function does not evaluate the elements of the yielder, the computation is performed when the yielder is later run.
Examples
import gleam/string
import gleam/int
"a1b2c3d4e5f"
|> string.to_graphemes
|> cycle
|> filter_map(int.parse)
|> take(5)
// -> [1, 2, 3, 4, 5]
pub fn find(
in haystack: Yielder(a),
one_that is_desired: fn(a) -> Bool,
) -> a
Finds the first element in a given yielder for which the given function returns
True.
Examples
find(cycle([1, 2, 3]), fn(x) { x > 2 })
// -> Ok(3)
pub fn find_map(
in haystack: Yielder(a),
one_that is_desired: fn(a) -> Result(b, c),
) -> b
Finds the first element in a given yielder
for which the given function returns Ok(new_value),
then returns the new_value.
Examples
find_map(cycle(["a", "1", "2"]), int.parse)
// -> Ok(1)
pub fn first(from yielder: Yielder(e)) -> e
Returns the first element yielded by the given yielder.
Examples
cycle([1, 2, 3]) |> first
// -> 1
pub fn fold_until(
over yielder: Yielder(e),
from initial: acc,
with f: fn(acc, e) -> list.ContinueOrStop(acc),
) -> acc
Reduces a yielder of elements into a single value by calling a given
function on each element in turn, using list.ContinueOrStop to determine
whether or not to keep iterating.
Examples
import gleam/list
let f = fn(acc, e) {
case e {
_ if e < 4 -> list.Continue(e + acc)
_ -> list.Stop(acc)
}
}
cycle([1, 2, 3, 4])
|> fold_until(from: 0, with: f)
// -> 6
pub fn incrementing(from start: Int) -> Yielder(Int)
Creates a yielder of ints, starting at a given start int and incrementing by one each time.
Examples
incrementing(from: 1) |> take(5)
// -> [1, 2, 3, 4, 5]
pub fn index(
over yielder: Yielder(element),
) -> Yielder(#(element, Int))
Wraps values yielded from a yielder with indices, starting from 0.
Examples
cycle(["a", "b", "c"]) |> index |> take(3)
// -> [#("a", 0), #("b", 1), #("c", 2)]
pub fn interleave(
left: Yielder(element),
with right: Yielder(element),
) -> Yielder(element)
Creates a yielder that alternates between the two given yielders.
Examples
cycle([1, 2, 3, 4])
|> interleave(cycle([11, 12, 13, 14]))
|> take(8)
// -> [1, 11, 2, 12, 3, 13, 4, 14]
cycle([1, 2, 3, 4])
|> interleave(cycle([100]))
|> take(8)
// -> [1, 100, 2, 100, 3, 100, 4, 100]
pub fn intersperse(
over yielder: Yielder(element),
with elem: element,
) -> Yielder(element)
Creates a yielder that yields the given elem element
between elements emitted by the underlying yielder.
Examples
cycle([1])
|> intersperse(with: 0)
|> take(1)
// -> [1]
cycle([1, 2, 3, 4, 5])
|> intersperse(with: 0)
|> take(9)
// -> [1, 0, 2, 0, 3, 0, 4, 0, 5]
pub fn iterate(
from initial: element,
with f: fn(element) -> element,
) -> Yielder(element)
Creates a yielder that infinitely applies a function to a value.
Examples
iterate(1, fn(n) { n * 3 }) |> take(5)
// -> [1, 3, 9, 27, 81]
pub fn map(
over yielder: Yielder(a),
with f: fn(a) -> b,
) -> Yielder(b)
Creates a yielder from an existing yielder and a transformation function.
Each element in the new yielder will be the result of calling the given function on the elements in the given yielder.
This function does not evaluate the elements of the yielder, the computation is performed when the yielder is later run.
Examples
cycle([1, 2, 3])
|> map(fn(x) { x * 2 })
|> take(3)
// -> [2, 4, 6]
pub fn map2(
yielder1: Yielder(a),
yielder2: Yielder(b),
with fun: fn(a, b) -> c,
) -> Yielder(c)
Combines two yielders into a single one using the given function.
If a yielder is longer than the other the extra elements are dropped.
This function does not evaluate the elements of the two yielders, the computation is performed when the resulting yielder is later run.
Examples
let first = cycle([1, 2, 3])
let second = cycle([4, 5, 6])
map2(first, second, fn(x, y) { x + y }) |> take(3)
// -> [5, 7, 9]
let first = cycle([1, 2])
let second = cycle(["a", "b", "c"])
map2(first, second, fn(i, x) { #(i, x) }) |> take(2)
// -> [#(1, "a"), #(2, "b")]
pub fn prepend(yielder: Yielder(a), element: a) -> Yielder(a)
Add a new element to the start of a yielder.
Examples
let yielder = cycle([1, 2, 3]) |> prepend(0)
yielder.take(4)
// -> [0, 1, 2, 3]
pub fn repeat(x: element) -> Yielder(element)
Creates a yielder that returns the same value infinitely.
Examples
repeat(10)
|> take(4)
// -> [10, 10, 10, 10]
pub fn repeatedly(f: fn() -> element) -> Yielder(element)
Creates a yielder that yields values created by calling a given function repeatedly.
repeatedly(fn() { 7 })
|> take(3)
// -> [7, 7, 7]
pub fn scan(
over yielder: Yielder(element),
from initial: acc,
with f: fn(acc, element) -> acc,
) -> Yielder(acc)
Creates a yielder from an existing yielder and a stateful function.
Specifically, this behaves like fold, but yields intermediate results.
Examples
// Generate a sequence of partial sums
cycle([1, 2, 3, 4, 5])
|> scan(from: 0, with: fn(acc, el) { acc + el })
|> take(5)
// -> [1, 3, 6, 10, 15]
pub fn sized_chunk(
over yielder: Yielder(element),
into count: Int,
) -> Yielder(List(element))
Creates a yielder that emits chunks of given size.
If the last chunk does not have count elements, it is yielded
as a partial chunk, with less than count elements.
For any count less than 1 this function behaves as if it was set to 1.
Examples
cycle([1, 2, 3, 4, 5, 6])
|> sized_chunk(into: 2)
|> take(3)
// -> [[1, 2], [3, 4], [5, 6]]
cycle([1, 2, 3, 4, 5, 6, 7, 8])
|> sized_chunk(into: 3)
|> take(3)
// -> [[1, 2, 3], [4, 5, 6], [7, 8, 1]]
pub fn step(yielder: Yielder(e)) -> Step(e, Yielder(e))
Eagerly accesses the first value of a yielder, returning a Next
that contains the first value and the rest of the yielder.
Examples
let Next(first, rest) = cycle([1, 2, 3, 4]) |> step
first
// -> 1
rest |> take(3)
// -> [2, 3, 4]
pub fn take(yielder: Yielder(e), desired: Int) -> List(e)
Creates a list containing the desired number of elements.
Examples
cycle([1, 2, 3, 4, 5])
|> take(3)
// -> [1, 2, 3]
cycle([1, 2])
|> take(3)
// -> [1, 2, 1]
pub fn take_while(
in yielder: Yielder(e),
satisfying predicate: fn(e) -> Bool,
) -> List(e)
Creates a list containing the elements while the predicate returns True.
Examples
cycle([1, 2, 3, 2, 4])
|> take_while(satisfying: fn(x) { x < 3 })
// -> [1, 2]
pub fn transform(
over yielder: Yielder(a),
from initial: acc,
with f: fn(acc, a) -> Step(b, acc),
) -> Yielder(b)
Creates a yielder from an existing yielder and a stateful function that may short-circuit.
f takes arguments acc for current state and el for current element from underlying yielder,
and returns Next with the yielded element and new state value.
Examples
Approximate implementation of index in terms of transform:
cycle(["a", "b", "c"])
|> transform(0, fn(i, el) { Next(#(i, el), i + 1) })
|> take(3)
// -> [#(0, "a"), #(1, "b"), #(2, "c")]
pub fn unfold(
from initial: acc,
with f: fn(acc) -> Step(element, acc),
) -> Yielder(element)
Creates a yielder from a given function and accumulator.
The function is called on the accumulator and returns Next which contains a
new element and accumulator. The element is yielded by the yielder and the
new accumulator is used with the function to compute the next element in
the sequence.
Examples
unfold(from: 5, with: fn(n) {
case n {
n -> Next(element: n, accumulator: n - 1)
}
})
|> take(5)
// -> [5, 4, 3, 2, 1]
pub fn yield(element: a, next: fn() -> Yielder(a)) -> Yielder(a)
Add a new element to the start of a yielder.
This function is for use with use expressions, to replicate the behaviour
of the yield keyword found in other languages.
If you only need to prepend an element and don’t require the use syntax,
use prepend.
Examples
let yielder = {
use <- yield(1)
use <- yield(2)
use <- yield(3)
cycle([0])
}
yielder |> take(6)
// -> [1, 2, 3, 0, 0, 0]