fluent-iterable (Rust)
The fluent-iterable vocabulary for Rust — an extension trait over
std::iter::Iterator, published on crates.io asfluent-iterable.
JavaScript needed fluent iterator chains, and this monorepo shipped them.
Rust's std already owns most of that surface (map, filter,
flat_map, any, fold, …) — but not the parts with real algorithmic
content: stable grouping, equi-joins, distinctness checks, cardinality
short-circuits, nested indices. This crate ports exactly that residue, in
the same operation names, as one extension trait:
use FluentIter;
let orders = ;
let customers = ;
// inner join, like .combine(other, keySelf, keyOther) — lazy: the left
// side streams, resolve with collect()
let lines: = orders
.iter
.combine
.collect;
// stable grouping, like .group(keyFn) — lazy, full pass on first pull
let by_customer: =
orders.iter.group_by_stable.collect;
// fold + project, like .reduceAndMap(reducer, initial, mapFn)
let report = orders
.iter
.map
.reduce_and_map;
assert_eq!;
No wrapper type, no runtime dependencies, nothing to learn beyond your
iterators: use fluent_iterable::FluentIter; and chain.
npm ⇄ Rust map
Operations this crate provides (npm name → Rust method):
| npm fluent-iterable | Rust |
|---|---|
.group(keyFn) |
group_by_stable (lazy; full pass on first pull) |
.combine(other, ka, kb) |
combine (lazy; left streams) |
.combineJoin(baseKey) |
combine_join (lazy) |
.distinct() |
distinct (lazy adapter) |
.distinct(keyFn) |
distinct_by (lazy adapter) |
.isDistinct() |
is_distinct (short-circuits) |
.isDistinct(keyFn) |
is_distinct_by (short-circuits) |
.toMap(k, v) |
to_map_by |
.toMapChain(k1, k2) |
to_map_chain (depth 2) |
.toMapChainReduce(…) |
to_map_chain_reduce (depth 2) |
.join(sep) |
join |
.join(sep, mapFn) |
join_by |
.avg() / .avg(mapFn) |
avg / avg_by (Option<f64>, None empty) |
.sort(cmp?) |
sorted / sort_with (stable, lazy wrapper) |
.sortBy(key) / desc |
sort_by / sort_by_desc (stable, lazy wrapper) |
.hasExactly(n) |
has_exactly |
.hasLessThan(n) |
has_less_than |
.hasLessOrExactly(n) |
has_less_or_exactly |
.hasMoreThan(n) |
has_more_than |
.hasMoreOrExactly(n) |
has_more_or_exactly |
.reduceAndMap(r, i, m) |
reduce_and_map (init first, Rust-style) |
.contains(item) |
contains |
.whenEmpty(fb) |
when_empty (lazy adapter) |
.repeat(n) |
repeat (finite cycle, lazy adapter) |
Operations you do not need here — std already has them:
map, filter, filter_map, flat_map/flatten, take, skip,
take_while, skip_while, count, any/all, sum, min, max,
fold (reduce), chain (concat/append), enumerate (withIndex),
collect (toArray), slice::chunks (partition), max_by_key (top).
What is deliberately not ported
| npm surface | why |
|---|---|
every *Async operation, flatMerge |
stable Rust has no AsyncIterator trait; revisit when the language lands it. |
emit / catch / finally / execute / waitAll |
JS emitter/lifecycle surface; Result, Drop and stream crates own this in Rust. |
toObject / toObjectChain* / unwind |
dynamic-property idioms; struct selection via flat_map is the Rust answer. |
branch |
needs fan-out buffering (tee); candidate for v2. |
distinct(key, choose, maxOcurrences) extras |
v1 is first-wins; a chooser/max-occurrences flavor can land later. |
toMapChain arbitrary key depth |
Rust fixes the concrete nested type at depth 2; deeper nesting folds layers. |
Intentional semantics upgrades are marked in the rustdoc
(avg returning Option<f64> instead of NaN, stable sorts by Ord
instead of JS string coercion, explicit initial value for
to_map_chain_reduce).
Development (inside this monorepo)
This directory is both a cargo package and a pnpm workspace member, so the usual root commands drive it:
Coverage locally (not wired into the turbo test:coverage task on purpose —
CI runners have no cargo-llvm-cov):
Publishing to crates.io is done from this directory with cargo publish
(the package.json exists only to bridge pnpm/turbo; the crate itself has
zero npm coupling).