4 ms·
Here's some generic code I wrote in Rust recently. I had two unrelated iterators/collections and I needed to flatten and sort them into a single buffer. st
by qppo 6y ago
Here's some generic code I wrote in Rust recently. I had two unrelated iterators/collections and I needed to flatten and sort them into a single buffer.
struct Data {
idx: usize
// ...
}
struct Foo {
stuff: Vec<Vec<Data>>
}
struct Bar {
stuff: Vec<Data>
}
fn flatten_and_sort (foo:Foo, bar:Bar) -> Vec<Data> {
let mut output =
foo.stuff.into_iter()
.flat_map(|v| v.into_iter())
.chain(bar.stuff.into_iter())
.collect::<Vec<_>>();
output.sort_by(|lhs, rhs| lhs.idx.cmp(&rhs.idx));
output
}
Now you could argue that this is just "generics for collections" but the way those iterator combinators are written make heavy use of generics/traits that aren't immediately applicable for collections. Those same combinator techniques can be applied to a whole host of other abstractions that allow for that kind of user code, but it's only possible if the type system empowers library authors to do it.
- saghm 6y agoYou can actually use the power of generics to get rid of the two inner calls to `into_iter()`: let mut output: Vec<_> = foo.stuff.into_iter() .flat_map(|v| v) .chain(bar.stuff) .collect();
- coolreader18 6y agoI believe you can just use `.flatten()` instead of `.flat_map(|v| v)`: let mut output: Vec<_> = foo.stuff.into_iter() .flatten() .chain(bar.stuff) .collect(); I might make it slightly more clear what the intent is by doing this: let mut output: Vec<_> = Iterator::chain(foo.stuff.into_iter().flatten(), bar.stuff) .collect(); But still basically the same.
- politician 6y agoYes, functional programming patterns are nice. It's possible to write that even more concisely in JavaScript.