Rust fold fusion?

Consider std::iter::Iterator - Rust

We can do iter, init: B, f(B, &T) -> res: B

Now suppose we have multiple pairs (init1, f1), (init2, f2), (init3, f3) and we want to produce output (value1, value2, value3).

Furthermore suppose we want to do this while traversing the iterator just once.

Are there builtins to 'fusion' the folds together into a single fold ?

let (value1, value2, value3) = iter
    .fold(
        (init1, init2, init3),
        |(acc1, acc2, acc3), el| (f1(&el), f2(&el), f3(&el)),
    );
4 Likes

In the event you might like to apply this approach to any number of entries, there are a couple of ways to go about it depending on how you imagine the computation.

Playground

// the collection of any arbitrary length
let collection: Vec<(i32, Func)> = vec![(10, two), (20, one), (30, |x| x + 7)];

// using fold
let new_collection = collection.iter().fold(Vec::new(), |mut acc, pair| {
        acc.push(pair.1(pair.0));
        acc
    });

// using map
let new_collection: Vec<i32> = collection.iter().map(|pair| pair.1(pair.0)).collect();

// fold can build anything that is "traversable" aka can be iterated over...
let new_anything = collection.iter().fold(String::new(), |mut acc, pair| {
        acc.push_str(&pair.1(pair.0).to_string());
        acc
    });

// a capacity that is abstracted with the FromIterator trait
#[derive(Debug)]
struct MyType(String);

impl<'a> std::iter::FromIterator<&'a (i32, Func)> for MyType {
    fn from_iter<I: IntoIterator<Item = &'a (i32, Func)>>(iter: I) -> Self {
        //
        // use an adaptor (iter -> iter) that returns an iterator where
        // Item: String  ... an iterator that can be used to construct a String
        // (i.e., where String implements FromIterator)
        //
        MyType(String::from_iter(
                iter.into_iter().map(|pair| pair.1(pair.0).to_string()),
        ))
    }
 }
let iter = collection.iter();
let new_my_type = MyType::from_iter(iter);

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.