We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ownership I: Moves, Copy, Clone, Drop step 3 of 20
Move semantics: the relay
Repair relay so it consumes station names from the back of a vector and
joins them into one route:
pub fn relay(mut stations: Vec<String>) -> String
Separate adjacent names with exactly " -> ", including the spaces.
Preserve each name unchanged, including empty names, whitespace and any
separator text already inside a name.
| Stations | Result |
|---|---|
[] |
"" |
["depot"] |
"depot" |
["a", "b", "c"] |
"c -> b -> a" |
["", "north"] |
"north -> " |
["x -> y", "z"] |
"z -> x -> y" |
Keep the supplied link helper and its signature. Use its returned string
as the route for the next iteration. The starter already handles empty
input and removes stations in the required order.
Follow ownership through the helper
fn link(head: String, tail: String) -> String {
format!("{head} -> {tail}")
}
link takes ownership of both input strings and returns a newly formatted
string. After link(route, stop), the old value of route has been moved.
The caller needs to store the result before it can use route again.
Moving a String transfers ownership of its buffer; it does not clone the
text. The compiler may optimize away physical transfers, so a move is not
a promise that particular bytes are copied to a new address. Types that
implement Copy, such as integers, can instead be copied when passed by
value. String does not implement Copy.
Reinitialize the route on every iteration
The starter discards the helper's output:
let _ = link(route, stop);
This leaves route unavailable both for another iteration and for the
final return. Rust rejects the function with E0382 even if a particular
input would skip the loop. The function must be valid for all its inputs.
Store the returned value in the same binding:
route = link(route, stop);
The right-hand side produces the new string before the assignment writes
it into route. Add mut to the binding created by the first pop so
reassignment is allowed. Each completed iteration then leaves a valid
route for the next call or the final return.
Check your understanding
Would changing the starter to let _ = link(route.clone(), stop); fix the task?
Show answer
Hide answer
It avoids moving the original route, but it still discards the newly built
string. The result would remain the last station instead of the full route.
For ["a", "b", "c"], it would return "c".
Assigning the result while cloning would produce the right output, but the clone is unnecessary: the old route is no longer needed after each call. Pass it by value and keep the result.
Why pop and let-else fit this loop
stations.pop() removes the last element and returns it as Some(String),
or returns None when the vector is empty. Moving the first popped string
directly into route avoids a leading separator:
let Some(mut route) = stations.pop() else {
return String::new();
};
The else branch must diverge; here it returns from the function. On the
other branch, route owns the first popped station. The loop combines each
remaining station with that accumulated route.
mut stations permits changes to the function's local vector binding.
It does not require the caller's binding to be declared mut; the caller
transfers the vector into this function.
This exercise demonstrates consuming and reinitializing a value. Repeated formatting rebuilds the accumulated prefix, so this particular helper is not a recommendation for efficiently joining a large collection of strings.
Submissions must compile, pass the cases and pass the Rust Clippy gate.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.