Camden Narzt
Camden Narzt

Reputation: 2003

Non-destructively iterating over a Rust collection, but not by reference

I can write the following two ways, the second is inspired by What is the idiomatic way to create a collection of references to methods that take self?:

channels.iter().flat_map(|c|c.to_uppercase()).collect(),
channels.clone().into_iter().flat_map(char::to_uppercase).collect(),

The second line has to clone the collection because char::to_uppercase doesn't accept a reference as it's argument and .iter() provides references and .into_iter() moves the collection.

Is there a way to do this that doesn't need to clone the collection or create a closure? I don't hate closures, I promise, and I know they're just turned into (usually inline) function calls in LLVM anyway, but I like the cleanness of referring to a function like in the second line and would prefer to use it if it can be done without the clone.

Upvotes: 4

Views: 1319

Answers (2)

oli_obk
oli_obk

Reputation: 31253

Iterator has a cloned method which is equivalent to .map(|x| x.clone()) which, in case of Copy types is equivalent to .map(|&x| x). This way you can write

channels.iter().cloned().flat_map(char::to_uppercase).collect()

Upvotes: 8

Francis Gagné
Francis Gagné

Reputation: 65822

You can define a function that takes a reference. You can even put it inside another function, if you want to keep it close to its usage.

fn foobar() {
    fn to_uppercase(c: &char) -> ::std::char::ToUppercase {
        c.to_uppercase()
    }

    // [...]

    let channels_upper = channels.iter().flat_map(to_uppercase).collect();
}

Upvotes: 2

Related Questions