Strings can't be edited by position
In some languages strings are immutable and you rebuild them after a change. In Rust a String can change, but not by assigning to a position. This code is rejected:
let mut name = "bndrei".to_string();
name[0] = 'A';
The compiler reports the type `str` cannot be indexed by `{integer}`. A Rust string is stored as UTF-8 bytes, and one character can take several of them, so "replace the character at position 0" could change the length of the whole string. Rust avoids the question by not offering positional assignment. You have several explicit ways to produce the changed text.
The approach in this lesson: go through a vector of characters
A Vec<char> has one slot per character and supports assignment by index. The pattern has three parts:
- Split the string into characters with
chars()and gather them withcollect(). - Edit the vector by index.
- Join the characters back into a
Stringwith anothercollect().
The same method, collect(), does both the first and the last part. It builds whatever collection the surrounding code asks for, so Rust needs to know the target type. In the first call the turbofish collect::<Vec<char>>() names it. In the last call the type comes from the variable being assigned to. A bare let x = chars.iter().collect(); fails with type annotations needed, because nothing says whether you want a vector, a string or something else.
The lesson's exercise
Someone saved the name "bndrei Chiriac" with a typo, and the first letter should be A. The starter code has already done the first two parts: it splits name into chars and replaces the first element with 'A'. Your job is the last part: collect the characters back into a string and assign it to name.
let mut name = "bndrei Chiriac".to_string();
let mut chars = name.chars().collect::<Vec<char>>();
chars[0] = 'A';
name = chars.iter().collect();
After this, name holds Andrei Chiriac. A few details:
iter()yields references. Iterating overcharswithiter()produces&charvalues. AStringcan be built from an iterator of&charas well as ofchar, so the call works as written.chars.into_iter().collect()also works and consumes the vector.- The target type is the variable. Because
nameis aString,collect()builds aString. The same assignment to a variable of another type would build something else, or fail to compile. let mutis required twice.charsis mutable so thatchars[0] = 'A'is allowed, andnameis mutable so that it can be given a new value. Withoutmutonname, the compiler reportscannot assign twice to immutable variable.- The first borrow is over.
name.chars()only borrowsnamefor the duration of the statement, and the collected vector owns its characters, so assigning tonameafterwards is fine.
Other ways to change a string
The vector route is the most general, but Rust has shorter tools for specific edits:
| Goal | Code | Result |
|---|---|---|
| Replace a byte range | s.replace_range(0..1, "A") | the first character becomes A |
| Replace matching text | "bndrei".replace("bn", "An") | a new String, Andrei |
| Build from a slice | format!("A{}", &t[1..]) | a new String, Andrei |
| Add at the end | s.push('!') | the String grows in place |
| Insert at a byte position | s.insert(0, '>') | the String grows in place |
| Remove the last character | s.pop() | returns an Option<char> |
| Empty it | s.clear() | an empty String |
Methods that change the string in place need a mut variable. Methods like replace return a new string and leave the original as it was.
Common mistakes
- Indexing the string.
name[0]doesn't compile for reading or for writing. - Forgetting the type for
collect(). Name it with the turbofish or with a type annotation. - Using byte positions on non-ASCII text.
replace_range,insertand slices count bytes and panic if a position falls inside a character. The vector route counts characters. - Expecting the original to change. Editing the vector never touches
nameuntil you collect and assign.
Key takeaways
- Rust strings can't be changed by index; convert to
Vec<char>, edit, and collect back. collect()needs a known target type, from a turbofish or the variable it is assigned to.- Both the vector and the string must be
mutin this pattern. - Shorter in-place tools exist, such as
push,insert,replace_rangeandclear.
