Iterators API Reference
Complete reference for Blitz’s Rayon-style parallel iterators.
Overview
Section titled “Overview”Blitz provides three iterator types:
| Type | Creation | Purpose |
|---|---|---|
ParIter(T) | blitz.iter(T, slice) | Read-only parallel iteration |
ParIterMut(T) | blitz.iterMut(T, slice) | Mutable parallel iteration |
RangeIter | blitz.range(start, end) | Index range iteration |
Creating Iterators
Section titled “Creating Iterators”blitz.iter(T, slice) -> ParIter(T)
Section titled “blitz.iter(T, slice) -> ParIter(T)”Create an immutable parallel iterator over a slice.
const data = [_]i64{ 1, 2, 3, 4, 5 };const it = blitz.iter(i64, &data);
// All operations are parallel and thread-safeconst sum = it.sum(); // 15Thread Safety: Read-only access, fully thread-safe.
blitz.iterMut(T, slice) -> ParIterMut(T)
Section titled “blitz.iterMut(T, slice) -> ParIterMut(T)”Create a mutable parallel iterator over a slice.
var data = [_]i64{ 1, 2, 3, 4, 5 };var it = blitz.iterMut(i64, &data);
it.mapInPlace(double); // data is now [2, 4, 6, 8, 10]
fn double(x: i64) i64 { return x * 2; }Thread Safety: Each element written by exactly one thread (disjoint access).
blitz.range(start, end) -> RangeIter
Section titled “blitz.range(start, end) -> RangeIter”Create an iterator over the index range [start, end).
const it = blitz.range(0, 1000);it.forEach(processIndex);
fn processIndex(i: usize) void { // Process index i}ParIter(T) Methods
Section titled “ParIter(T) Methods”Aggregations
Section titled “Aggregations”sum() -> T
Section titled “sum() -> T”Compute the sum of all elements using parallel reduction.
const data = [_]i64{ 1, 2, 3, 4, 5 };const sum = blitz.iter(i64, &data).sum(); // 15Returns: Sum of all elements (0 for empty slice)
min() -> ?T
Section titled “min() -> ?T”Find the minimum element using parallel reduction.
const min = blitz.iter(i64, &data).min(); // ?i64if (min) |m| { std.debug.print("Min: {}\n", .{m});}Returns: ?T - The minimum, or null for empty slice
max() -> ?T
Section titled “max() -> ?T”Find the maximum element using parallel reduction.
const max = blitz.iter(i64, &data).max(); // ?i64Returns: ?T - The maximum, or null for empty slice
count() -> usize
Section titled “count() -> usize”Count the number of elements.
const n = blitz.iter(i64, &data).count(); // 5Custom Reduce
Section titled “Custom Reduce”reduce(identity, reducer) -> T
Section titled “reduce(identity, reducer) -> T”General parallel reduction with a custom binary operation.
const product = blitz.iter(i64, &data).reduce(1, multiply);
fn multiply(a: i64, b: i64) i64 { return a * b; }Parameters:
identity:T- Identity value for the operation (e.g., 0 for sum, 1 for product)reducer:fn(T, T) T- Associative binary operation
Requirements: The reducer must be associative: f(f(a,b), c) == f(a, f(b,c))
Find Operations
Section titled “Find Operations”findAny(predicate) -> ?T
Section titled “findAny(predicate) -> ?T”Find any element matching the predicate. Non-deterministic order, fastest search.
const found = blitz.iter(i64, &data).findAny(isNegative);
fn isNegative(x: i64) bool { return x < 0; }Performance: Supports early exit - stops when any thread finds a match.
findFirst(predicate) -> ?FindResult(T)
Section titled “findFirst(predicate) -> ?FindResult(T)”Find the first element matching the predicate (deterministic order).
const result = blitz.iter(i64, &data).findFirst(isNegative);if (result) |r| { std.debug.print("First negative at index {}: {}\n", .{ r.index, r.value });}Returns: ?struct { index: usize, value: T } - First match with index
findLast(predicate) -> ?FindResult(T)
Section titled “findLast(predicate) -> ?FindResult(T)”Find the last element matching the predicate (deterministic order).
position(predicate) -> ?usize
Section titled “position(predicate) -> ?usize”Find the index of the first matching element.
const pos = blitz.iter(i64, &data).position(isNegative);rposition(predicate) -> ?usize
Section titled “rposition(predicate) -> ?usize”Find the index of the last matching element.
Predicates (Early Exit)
Section titled “Predicates (Early Exit)”any(predicate) -> bool
Section titled “any(predicate) -> bool”Check if any element matches. Short-circuits on first match.
const hasNegative = blitz.iter(i64, &data).any(isNegative);Performance: Early exit when match found - can be 100-1000x faster than full scan.
all(predicate) -> bool
Section titled “all(predicate) -> bool”Check if all elements match. Short-circuits on first non-match.
const allPositive = blitz.iter(i64, &data).all(isPositive);
fn isPositive(x: i64) bool { return x > 0; }Min/Max by Comparator or Key
Section titled “Min/Max by Comparator or Key”minBy(comparator) -> ?T
Section titled “minBy(comparator) -> ?T”Find minimum using a custom comparator.
const Person = struct { name: []const u8, age: u32 };
const youngest = blitz.iter(Person, &people).minBy(compareByAge);
fn compareByAge(a: Person, b: Person) std.math.Order { return std.math.order(a.age, b.age);}maxBy(comparator) -> ?T
Section titled “maxBy(comparator) -> ?T”Find maximum using a custom comparator.
minByKey(K, key_fn) -> ?T
Section titled “minByKey(K, key_fn) -> ?T”Find minimum by extracting a comparable key.
const youngest = blitz.iter(Person, &people).minByKey(u32, getAge);
fn getAge(p: Person) u32 { return p.age; }maxByKey(K, key_fn) -> ?T
Section titled “maxByKey(K, key_fn) -> ?T”Find maximum by extracting a comparable key.
Transformations
Section titled “Transformations”map(func) -> MappedIter
Section titled “map(func) -> MappedIter”Create a new iterator with transformed values (lazy).
const squared = blitz.iter(i64, &data).map(square);const sumOfSquares = squared.sum();
fn square(x: i64) i64 { return x * x; }Note: Lazy evaluation - transformation applied when consumed.
forEach(func) -> void
Section titled “forEach(func) -> void”Execute a function for each element in parallel.
blitz.iter(i64, &data).forEach(process);
fn process(x: i64) void { std.debug.print("Value: {}\n", .{x});}Note: No ordering guarantee - elements processed in parallel.
collect(allocator) -> ![]T
Section titled “collect(allocator) -> ![]T”Collect elements into a new allocated array.
const copy = try blitz.iter(i64, &data).collect(allocator);defer allocator.free(copy);Sub-Iterators
Section titled “Sub-Iterators”chunks_iter(chunk_size) -> ChunksIter(T)
Section titled “chunks_iter(chunk_size) -> ChunksIter(T)”Create an iterator over fixed-size chunks.
const chunks = blitz.iter(f64, &data).chunks_iter(1000);const numChunks = chunks.count(); // ceil(data.len / 1000)enumerate_iter() -> EnumerateIter(T)
Section titled “enumerate_iter() -> EnumerateIter(T)”Create an iterator with indices starting at 0.
const enum_it = blitz.iter(i64, &data).enumerate_iter();enum_it.forEach(processWithIndex);
fn processWithIndex(index: usize, value: i64) void { // ...}ParIterMut(T) Methods
Section titled “ParIterMut(T) Methods”Includes all ParIter methods plus:
mapInPlace(func) -> void
Section titled “mapInPlace(func) -> void”Transform each element in place.
var it = blitz.iterMut(i64, &data);it.mapInPlace(double);
fn double(x: i64) i64 { return x * 2; }Thread Safety: Each element written by exactly one thread.
fill(value) -> void
Section titled “fill(value) -> void”Set all elements to a value (parallel memset).
var it = blitz.iterMut(i64, &data);it.fill(0); // Zero all elementsRangeIter Methods
Section titled “RangeIter Methods”sum(T, value_fn) -> T
Section titled “sum(T, value_fn) -> T”Sum values generated from indices.
const total = blitz.range(0, 1000).sum(i64, identity);
fn identity(i: usize) i64 { return @intCast(i); }forEach(func) -> void
Section titled “forEach(func) -> void”Process each index in parallel.
blitz.range(0, 1000).forEach(processIndex);
fn processIndex(i: usize) void { // Process index i}Performance Comparison
Section titled “Performance Comparison”| Operation | Sequential | Parallel (10 cores) | Speedup |
|---|---|---|---|
| sum (100M i64) | 31 ms | 3.1 ms | 10x |
| min (100M i64) | 45 ms | 8 ms | 5.6x |
| any (10M, early exit) | 35 ms | 0.07 ms | 500x |
| findAny (10M) | 35 ms | 0.1 ms | 350x |
| mapInPlace (10M) | 25 ms | 3 ms | 8x |
Best Practices
Section titled “Best Practices”- Use
findAnyoverfindFirstwhen order doesn’t matter - it’s faster - Use
any/allfor boolean checks - early exit is very fast - Use built-in aggregations (
sum,min,max) - optimized parallel reduction - Use
minByKey/maxByKeywhen you have a natural key - cleaner thanminBy - Use
chunks_iterfor complex per-chunk processing with custom reduction - Don’t parallelize tiny data - overhead exceeds benefit below ~1000 elements