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]
pub fn zip(
  left: Yielder(a),
  right: Yielder(b),
) -> Yielder(#(a, b))

Zips two yielders together, emitting values from both until the shorter one runs out.

Examples

cycle(["a", "b", "c"])
|> zip(incrementing(20))
|> take(3)
// -> [#("a", 20), #("b", 21), #("c", 22)]
Search Document