Expand description
Fluent extension trait for std::iter::Iterator — the Rust port of the
@codibre/fluent-iterable
vocabulary.
JavaScript got a fluent iterator chain protocol that Node’s standard
library never shipped, so this library ships the same vocabulary for
Rust on the one mechanism the language actually has: an extension trait
with a blanket impl over every Iterator. No wrapper type, no DSL —
chain onto any iterator you already have.
use fluent_iterable::FluentIter;
let rows = [("sa", 10), ("sp", 30), ("sa", 25)];
let by_state: Vec<(&str, Vec<(&str, i32)>)> =
rows.into_iter().group_by_stable(|(s, _)| *s).collect();
assert_eq!(by_state[0].1, vec![("sa", 10), ("sa", 25)]);
let report = rows
.into_iter()
.map(|(_, v)| v)
.join_by(|v| format!("{v:>4}"), " | ");
assert_eq!(report, " 10 | 30 | 25");§npm ⇄ Rust map
Only the operations that std lacks live here. Everything else already
has a native spelling — using it keeps code idiomatic:
§What is deliberately not ported (and why)
| npm surface | reason |
|---|---|
every *Async operation, flatMerge | stable Rust has no AsyncIterator trait; generic async iteration is unexpressible. Revisit when the language lands it. |
emit / catch / finally / execute / waitAll | JS emitter/lifecycle surface. Result, Drop and dedicated stream crates own this in Rust. |
toObject / toObjectChain* / unwind | dynamic-property idioms; struct field selection via flat_map is the Rust answer. |
branch | needs fan-out buffering (tee); possible v2. |
distinct(key, choose, maxOccurrences) extras | v1 keeps first-wins; a chooser/max-occurrences flavor can land later without breaking names. |
toMapChain dynamic key depth | JS nests to an arbitrary number of key functions; Rust fixes the concrete nested type at depth 2. Deeper nesting is a fold of depth-2 layers. |
avg() returning NaN on empty | Rust says it in the type: Option<f64>, None on empty. |
sort() default comparator (stringified JS ordering) | Rust uses Ord (FluentIter::sorted) — numeric/lexicographic by the type’s own ordering, never string coercion. |
combine default-identity keys | keys are explicit closures in Rust. |
whenEmpty with a differently-typed fallback | the fallback must yield the same Item type; map it first. |
§Laziness
Adapters (FluentIter::distinct, FluentIter::when_empty,
FluentIter::repeat) stream and short-circuit like std adapters.
Terminals that need the whole sequence (group_by_stable, combine,
sort*, to_map*) return owned Vec/HashMap directly — the JS side
materializes at these points anyway, and materializing keeps the order
semantics exact and obvious.
Structs§
- Combine
- Inner equi-join produced by
FluentIter::combine— see there. - Combine
Join - Folded join produced by
FluentIter::combine_join— see there. - Distinct
- Streaming deduplication adapter behind
FluentIter::distinct. - Distinct
By - Keyed streaming dedup produced by
FluentIter::distinct_by— see there. - Group
ByStable - Stable grouping produced by
FluentIter::group_by_stable— see there. - Repeat
- Finite repetition adapter behind
FluentIter::repeat. - SortBy
- Sorted sequence produced by
FluentIter::sort_by/FluentIter::sort_by_desc. - Sort
With - Sorted sequence produced by
FluentIter::sort_with— see there. - Sorted
- Sorted sequence produced by
FluentIter::sorted— see there. - When
Empty - Fallback adapter behind
FluentIter::when_empty.
Traits§
- Fluent
Iter - The missing combinators of
std::iter::Iterator, in the [@codibre/fluent-iterable] vocabulary (see the crate docs for the full npm ⇄ Rust map).