Rust: from zero to your own organizer Lesson 26 of 40
Tuples: two results from one function
Lesson 26. Return a task title and its duration together without mixing up the values.
This text was translated with AI.
Before this lesson: lessons 9, 14, 19 and 22. If returning a value from a function feels unfamiliar, revisit lesson 14.
Familiar image and recall map
A task card has a place for a title and another for a number of minutes. It is one card with two different entries. A tuple is one value made of a fixed number of ordered elements, which may have different types. Rust knows how many places it has, and each place’s type, when it compiles the program. The card image has a limit: tuple places have positions rather than names. The next lesson introduces a struct when named fields would help.
Two values → parentheses and comma → one tuple → return → unpack into names. Say the chain without looking at code. (String, u32) is a tuple type: the first place holds an owned String, the second a u32 whole number. (title, minutes) creates a value in that order. The comma separates places, and the parentheses group them into one value. (u32, String) is a different type because the order differs.
Return one pair
Save your previous src/main.rs in organizer, replace the whole file with this example, and run cargo run beside Cargo.toml. No other files or dependencies change. Predict the output without Cargo’s own messages.
The type after -> in first_task is the single return type (String, u32). The final line has no ;, so it returns the tuple. In let (title, minutes) = first_task();, the pattern on the left unpacks it: the first element gets the name title, the second minutes. The function still returns one compound value.
fn first_task() -> (String, u32) {
let title = String::from("Reading");
let minutes = 20;
(title, minutes)
}
fn main() {
let (title, minutes) = first_task();
println!("{title}: {minutes} min");
}
Reading: 20 min
The String moves from the function into the tuple, then into title; this follows lesson 19’s ownership rule. A u32 can be copied. A tuple works well for a short intermediate result when the meaning of each place is clear near its use.
Positions and the image’s limit
To read one place, put a dot and its position number after the tuple name: .0 is first and .1 is second. Counting begins at zero, as with an array index. In the separate example below, _u32 on 25 states its number type explicitly; lesson 10 covered number types. true is a Boolean value from lesson 11. The tuple holds minutes and a Boolean answer to whether there was enough time.
fn main() {
let report = (25_u32, true);
println!("Minutes: {}", report.0);
println!("Finished: {}", report.1);
}
Minutes: 25
Finished: true
Both elements here copy when read. Taking a String through .0 can instead move ownership to a new variable; it does not copy text for free. A two-element tuple has no .2. This separate example intentionally fails with E0609:
fn main() {
let report = (20_u32, true);
println!("{}", report.2);
}
Do not confuse (20, true) with an array [20, true]: an array requires all elements to have one type. The empty parentheses () from lesson 14 are a tuple with no elements and the unit value. A one-element tuple needs a comma, (20,); (20) is just a number in parentheses.
Recall without the page
- Why does a function returning
(String, u32)still return one value? - Which place does
.1select? - How does
(20,)differ from(20)?
Check: a tuple is one compound value; .1 is the second place; the comma makes a one-element tuple. Close the page and say “two values → one tuple → return → unpack” from memory.
Exercise
Required. Write plan() -> (String, u32) so it returns Walk and 30. In main, unpack those values into title and minutes, then print Walk — 30 min. Both displayed values must come from the function, not from a finished message in println!.
Boundary check. Swap the order of the returned elements without changing the declared type. Read the compiler error, then restore the order.
Hint
Make (String::from("Walk"), 30) the final expression of the function. Put (title, minutes) to the left of = in main.
Reference answer after trying
fn plan() -> (String, u32) {
(String::from("Walk"), 30)
}
fn main() {
let (title, minutes) = plan();
println!("{title} — {minutes} min");
}
Walk — 30 min
The tuple held values of two types together; unpacking gave each result a useful name. Official tuple explanation.
If you have found a mistake or a typo in this article, tell us about it
Comments (0)
Log in to leave a comment →
No comments yet. Be the first.