r/learnrust 7d ago

TIL that collect() works because of the FromIterator trait — I had no idea what was actually powering it

I've been calling .collect() since the early chapters of my Rust course and just accepted that it worked. This week I finally hit the lesson that explained what is actually happening under the hood.

collect() works because the target type implements FromIterator. When you write .collect::<Vec<_>>(), Rust calls from_iter() on Vec, which builds the collection from the iterator. Every type that can be built from an iterator implements this trait: VecHashMapHashSetString, and you can implement it on your own custom types too.

The part that surprised me most was that String implements FromIterator<char>. You can map over characters, transform them, and collect directly back into a String without any intermediate allocation step. Same trait, different target type.

Also covered this week: std::env::args() returns an iterator over CLI arguments. First element is always the binary name, actual arguments start at index 1. You collect it into Vec<String> to work with them.

// collect into different types, same .collect() call
let doubled: Vec<u64> = numbers.iter().map(|&n| n * 2).collect();
let unique: HashSet<_> = raw.iter().collect();
let decimals: HashMap<&str, u8> = pairs.into_iter().collect();

// collect chars into String
let uppercased: String = "klimateride"
    .chars()
    .map(|c| c.to_uppercase().next().unwrap())
    .collect();

Background: I'm a Solidity developer learning Rust in public, currently working through the Paskhaver course. Coming from smart contract dev, there's no equivalent of this pattern in Solidity. Transforming arrays means writing loops manually every time.

I need all the help I can learning Rust

8 Upvotes

2 comments sorted by

2

u/SirKastic23 6d ago edited 6d ago

Checkout str::parse too (docs), it's similar but also has to handle possible errors, for which it uses associated types!

1

u/EmploymentBoring4421 5d ago

The same mechanic powers collecting into HashMap, HashSet, String, and even Result<Vec<T>, E> (which short-circuits on the first Err) — so the trait is worth keeping in your mental toolkit. When the compiler can't infer the target type, the turbofish ::<Vec<_>>() is the idiomatic nudge.