We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Ground Rules: Values, Types, Control Flow step 16 of 24
Loop labels and labeled blocks
Find the first occurrence of target in the grid. Return a two-element
vector containing its zero-based row and column indices, or [-1, -1] if it
is absent.
pub fn find_in_grid(grid: &[Vec<i32>], target: i32) -> Vec<i64>
Search rows from top to bottom and values within each row from left to right.
If there are multiple matches, return the earliest in that order. Rows can be
empty or have different lengths. An empty grid, or a grid containing only empty
rows, returns [-1, -1]. Compare the full i32 values, including negatives.
Do not modify the grid.
| Grid | Target | Result |
|---|---|---|
[[1, 2], [3, 4]] |
3 |
[1, 0] |
[[], [7], [8, 9, 10]] |
10 |
[2, 2] |
[[5, 5], [5]] |
5 |
[0, 0] |
[[], []] |
1 |
[-1, -1] |
Repair the undeclared label
The starter uses break 'search without declaring 'search, which produces
E0426. Its break also carries a vector value. Adding a label to the outer
for loop alone is not sufficient: a for loop cannot be exited with a value.
A labeled block around the search can receive that value, or you can restructure
the function while preserving the required behavior.
A label selects the construct to leave
An ordinary break exits the innermost enclosing loop. A labeled break can
exit an outer loop instead. This complete example stops both loops after
visiting the first matching number:
fn main() {
let rows = [[1, 2], [3, 4]];
let mut visited = 0;
'rows: for row in &rows {
for &value in row {
visited += 1;
if value == 3 {
break 'rows;
}
}
}
assert_eq!(visited, 3);
}
Write a label as an apostrophe, a name and a colon before the construct.
continue 'rows would continue the next iteration of the labeled loop;
it cannot target a plain block.
A labeled block can produce a value
A labeled block runs once. break 'label value ends it with that value; if no
break is taken, its final expression supplies the value. These result paths
must have compatible types.
fn first_positive(values: &[i32]) -> Option<i32> {
'search: {
for &value in values {
if value > 0 {
break 'search Some(value);
}
}
None
}
}
fn main() {
assert_eq!(first_positive(&[-2, 0, 7, 9]), Some(7));
assert_eq!(first_positive(&[-2, 0]), None);
}
For the grid search, the block can produce either the matching coordinates or
the not-found vector. A loop expression can also receive a break value;
for and while loops cannot.
Breaking from a block continues execution after that block. Returning exits the function, so it skips later statements in the function. Both operations still follow Rust's normal rules for dropping local values as their scopes end.
Index types
enumerate() gives usize indices. The return type uses i64 so it can also
represent the sentinel -1. The task's indices fit in i64. A cast from a
64-bit usize to i64 is not a widening conversion: arbitrary unsigned values
above i64::MAX would not retain their numeric value. Use the cast only with
the index range in mind.
Your solution must compile, return the exact two-element vector and pass Clippy with warnings treated as errors.
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.