We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Shape Your Data: Structs, Enums, Pattern Matching step 10 of 26
Binding values with @ and or-patterns
Repair the starter so it labels each number with its bucket and value.
pub fn bucket(values: Vec<i64>) -> Vec<String>
| Value | Label |
|---|---|
At most 9, including all negative numbers |
"small:{value}" |
10 through 99, inclusive |
"mid:{value}" |
At least 100 |
"large:{value}" |
Preserve input order and duplicates. An empty vector produces an empty
vector. Every i64 is valid, including i64::MIN and i64::MAX.
Format the integer in decimal without spaces or extra punctuation.
For example, [0, 50, 1000, -5] becomes
["small:0", "mid:50", "large:1000", "small:-5"].
The starter already classifies and formats the values. Fix the or-pattern
in payload, keeping the supplied Bucket enum and helper functions.
Testing and binding with @
name @ pattern tests a pattern and gives the matched value a name. The
starter uses n @ ..=9 to match any integer at most nine and bind it to n.
This is an upper-bounded inclusive range: nine is included, and no explicit
lower bound is needed.
Here is a complete example with a different set of ranges:
fn describe(value: i64) -> String {
match value {
n @ 1..=5 => format!("in range: {n}"),
n => format!("outside: {n}"),
}
}
fn main() {
assert_eq!(describe(3), "in range: 3");
assert_eq!(describe(8), "outside: 8");
}
The final n binds any remaining value, making the match exhaustive.
Use @ when the inner pattern adds a useful test or destructuring step.
n @ _ adds nothing over a plain n.
One binding across several alternatives
An or-pattern joins alternatives with |. They share one arm body, so
each alternative must bind the same names with compatible types and the
same binding modes. The starter mixes n and m: whichever alternative
matches, the arm body needs one consistently named binding.
This example combines two variants that both contain an integer:
enum Reading {
Sensor(i64),
Manual(i64),
}
fn value(reading: &Reading) -> i64 {
match reading {
Reading::Sensor(n) | Reading::Manual(n) => *n,
}
}
fn main() {
assert_eq!(value(&Reading::Sensor(12)), 12);
assert_eq!(value(&Reading::Manual(-3)), -3);
}
Matching &Reading this way borrows its contents, so n has type &i64.
Dereferencing it copies the integer. The same reasoning applies to the
starter's payload(bucket: &Bucket).
Reading the compiler's messages
Start with the earliest binding error, then compile again after fixing it. One mistake can cause additional messages about later uses of a binding.
| Problem | Typical diagnostic |
|---|---|
| A name is absent from an alternative | E0408: variable is not bound in all patterns |
| The same name has different types | E0308: mismatched types |
The same name uses different modes, such as ref n and n |
E0409: variable is bound inconsistently |
A name appears twice within one pattern, such as (n, n) |
E0416: identifier is bound more than once |
Repeating a name within one pattern is not an equality test. If two fields must be equal, bind them separately and compare them in a guard.
Borrowing still depends on context
@ does not force a move. Like other bindings, it can copy, move or borrow
according to the type and binding mode. An i64 bound by value is copied.
A String bound by value is moved, while a reference pattern or an explicit
ref binding can borrow it. Adding @ does not allow moving owned data
out through a shared reference.
Alternatives can also appear inside another pattern. For example,
Some(1 | 4 | 9) matches the same values as
Some(1) | Some(4) | Some(9). Choose the form that makes the shared
structure easiest to read.
Submissions must compile, pass the tests and pass clippy -D warnings.
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.