Seq
Seq module: lazy fold-based sequences (church-encoded). Seq(a) wraps fn(b, fn(b, a) -> b) -> b. Enum operates eagerly on Lists; Seq operates lazily over I/O or generated sequences.
Transformations (map, filter, take, ...) only build a new fold; nothing runs until a consumer (to_list, fold, count, find, ...) folds the sequence. Every fold visits the whole source: take, find, any, all and fold_while stop using elements early but never stop the iteration itself, so they do not terminate on an unbounded source (an unfold whose next never returns None). Bound such sources with unfold_until, repeat or iterate.
march> let evens = Seq.filter(Seq.from_list([1, 2, 3, 4, 5, 6]), fn x -> x % 2 == 0)
march> Seq.to_list(Seq.map(evens, fn x -> x * 10))
[20, 40, 60]Types
Step type for fold_while: Continue to keep folding, Halt to stop early.
Seq wraps a closure. March's type syntax cannot express the rank-2 type, so we omit the type annotation — the constructor takes any value (the fold fn).
Functions
True if every element satisfies pred; true for an empty seq. pred is not called again after the first failure, but the whole seq is still visited.
Examples
march> Seq.all(Seq.from_list([1, 2, 3]), fn x -> x > 0)
true
march> Seq.all(Seq.empty(), fn x -> x > 0)
trueTrue if any element satisfies pred; false for an empty seq. pred is not called again after the first match, but the whole seq is still visited.
Examples
march> Seq.any(Seq.from_list([1, 2, 3]), fn x -> x > 2)
true
march> Seq.any(Seq.empty(), fn x -> x > 2)
falseGroups elements into lists of n (which must be positive); the last batch holds the remainder and may be shorter. An empty seq yields no batches.
Examples
march> Seq.to_list(Seq.batch(Seq.from_list([1, 2, 3, 4, 5]), 2))
[[1, 2], [3, 4], [5]]
march> Seq.to_list(Seq.batch(Seq.empty(), 2))
[]Alias for batch: groups elements into lists of size n. Provided for parity with the API name used by the spec/plan; batch remains the canonical name.
march> Seq.to_list(Seq.batched(Seq.from_list([1, 2, 3, 4, 5]), 2))
[[1, 2], [3, 4], [5]]The elements of s1 followed by the elements of s2.
Examples
march> Seq.to_list(Seq.concat(Seq.from_list([1, 2]), Seq.from_list([3])))
[1, 2, 3]The number of elements in the seq.
Examples
march> Seq.count(Seq.from_list([1, 2, 3]))
3
march> Seq.count(Seq.empty())
0Concatenate seq with itself n times. cycle(seq, 0) is empty.
Because Seq is church-encoded the underlying source is re-folded once per cycle; do not pass a one-shot source like from_file_lines (each re-fold would attempt to re-read a closed fd).
march> Seq.to_list(Seq.cycle(Seq.from_list([1, 2]), 3))
[1, 2, 1, 2, 1, 2]All but the first n elements (empty if n >= length; the whole seq if n <= 0).
Examples
march> Seq.to_list(Seq.drop(Seq.from_list([1, 2, 3]), 2))
[3]
march> Seq.to_list(Seq.drop(Seq.from_list([1, 2, 3]), 5))
[]Calls f on each element for its side effects and returns :ok. f's result is discarded, but the current typing threads it as the accumulator, so f must return an Atom (e.g. :ok).
Seq.each(Seq.from_list(["a", "b"]), fn s -> do
println(s)
:ok
end)The empty seq: folding it returns the start accumulator unchanged.
Examples
march> Seq.to_list(Seq.empty())
[]
march> Seq.count(Seq.empty())
0Lazily keeps only the elements for which pred returns true.
Examples
march> Seq.to_list(Seq.filter(Seq.from_list([1, 2, 3, 4]), fn x -> x % 2 == 0))
[2, 4]The first element satisfying pred as Some, or None. Built on fold_while, so the whole seq is still visited.
Examples
march> Seq.find(Seq.from_list([1, 2, 3, 4]), fn x -> x > 2)
Some(3)
march> Seq.find(Seq.from_list([1, 2]), fn x -> x > 5)
NoneLazily applies f (which returns a Seq) to each element and concatenates the resulting seqs.
Examples
march> Seq.to_list(Seq.flat_map(Seq.from_list([1, 2]), fn x -> Seq.from_list([x, x])))
[1, 1, 2, 2]Folds the seq left to right: f(acc, x) returns the next accumulator, starting from start. Returns start for an empty seq.
Examples
march> Seq.fold(Seq.from_list([1, 2, 3]), 0, fn (acc, x) -> acc + x)
6
march> Seq.fold(Seq.empty(), 5, fn (acc, x) -> acc + x)
5Folds with early exit: f(acc, x) returns Continue(acc2) to keep going or Halt(result) to stop accumulating; the result is the last Continue/Halt payload. The remaining elements are still visited (and ignored) after a Halt, so this does not terminate on an unbounded seq.
Examples
march> Seq.fold_while(Seq.from_list([1, 2, 3, 4]), 0, fn (acc, x) -> if acc + x > 5 do Halt(acc) else Continue(acc + x) end)
3Open path and return a lazy Seq(Bytes) of fixed-size chunks. The final chunk may be shorter than size if the file does not divide evenly. Returns Ok(seq) or Err(file_error). The fd is closed on EOF, so consume to completion (to_list, fold, etc.).
Open path and return a lazy Seq(String) over its lines. Returns Ok(seq) on success or Err(file_error) on failure. The file handle is closed automatically when iteration reaches EOF; consume the seq fully (or via to_list) to release the fd.
Each line is yielded with its trailing newline stripped.
match Seq.from_file_lines("data.txt") do
Ok(s) -> Seq.to_list(Seq.take(s, 10)) -- first 10 lines
Err(_) -> []
endA seq over the elements of a list, in order.
Examples
march> Seq.to_list(Seq.from_list([1, 2, 3]))
[1, 2, 3]Build a Seq(String) from a string by splitting on "\\n" (a "\\r" before it is kept). Trailing empty lines are dropped, so neither "a\\nb\\n" nor "a\\nb\\n\\n" produces a final ""; blank lines in the middle are preserved. The empty string yields an empty seq.
Examples
march> Seq.to_list(Seq.from_string_lines("a\nb\n"))
["a", "b"]
march> Seq.to_list(Seq.from_string_lines("a\n\nb"))
["a", "", "b"]
march> Seq.to_list(Seq.from_string_lines(""))
[]Apply step repeatedly starting from seed, yielding n elements: [seed, step(seed), step(step(seed)), …]. iterate(_, _, 0) is empty.
march> Seq.to_list(Seq.iterate(1, fn x -> x * 2, 5))
[1, 2, 4, 8, 16]Lazily applies f to each element. f runs once per element each time the result is folded.
Examples
march> Seq.to_list(Seq.map(Seq.from_list([1, 2, 3]), fn x -> x * 10))
[10, 20, 30]A Seq(a) that yields x exactly n times. repeat(_, 0) is the empty seq; negative n is treated as 0.
march> Seq.to_list(Seq.repeat("hi", 3))
["hi", "hi", "hi"]
march> Seq.to_list(Seq.repeat(7, -2))
[]The first n elements (all of them if there are fewer; none if n <= 0). The source is still folded to its end, the extra elements just ignored, so take does not make an unbounded seq finite: use unfold_until.
Examples
march> Seq.to_list(Seq.take(Seq.from_list([1, 2, 3]), 2))
[1, 2]
march> Seq.to_list(Seq.take(Seq.from_list([1, 2, 3]), 0))
[]Folds the seq into a list, in order.
Examples
march> Seq.to_list(Seq.map(Seq.from_list([1, 2]), fn x -> x + 1))
[2, 3]A seq generated from seed: next(seed) returns Some((value, seed2)) to yield value and continue from seed2, or None to stop. next is re-run from seed every time the seq is folded. If next never returns None the seq is unbounded and no consumer terminates on it (see unfold_until).
Examples
march> Seq.to_list(Seq.unfold(1, fn n -> if n > 4 do None else Some((n, n + 1)) end))
[1, 2, 3, 4]Like unfold but with an upper bound on the number of elements produced. Stops at the smaller of (a) next returning None or (b) max elements yielded.
march> let s = Seq.unfold_until(0, fn n -> Some((n, n + 1)), 5)
march> Seq.to_list(s)
[0, 1, 2, 3, 4]Pairs elements of s1 with elements of s2, stopping at the shorter one. s2 is materialised to a list (via to_list) each time the result is folded, so it must be finite; s1 drives the iteration.
Examples
march> Seq.to_list(Seq.zip(Seq.from_list([1, 2, 3]), Seq.from_list(["a", "b"])))
[(1, "a"), (2, "b")]