We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Errors Are Values step 12 of 24
? on Option, and bridging to Result
Complete two functions that find a word on the first line of an input. One returns an Option; the other gives a descriptive error when the word is missing.
Required behavior
nth_word(s: String, n: usize) -> Option<String> returns the word at
zero-based index n on the first line, as an owned String. Return
None if the line or word is absent.
nth_word_len(s: String, n: usize) -> Result<usize, String> returns that
word's UTF-8 byte length. If the word is absent, return the exact error
format!("no word at index {n}").
| Input | Index | Word | Byte length or error |
|---|---|---|---|
"the cat sat" |
1 | Some("cat") |
Ok(3) |
"the cat sat" |
9 | None |
Err("no word at index 9") |
"héllo wörld" |
1 | Some("wörld") |
Ok(6) |
"alpha beta\ngamma" |
2 | None |
Err("no word at index 2") |
The displayed words are shorthand for owned Strings. The harness writes
None as JSON null; on failure it also writes a null length and the
error message.
Define the first line before splitting words
Use str::lines to find the first line. It recognizes newline
(\n) and carriage-return/newline (\r\n) endings and excludes
those terminators from the returned text.
An empty string has no first line. A string starting with \n has an
empty first line, so "\nsecond line" still has no word at index zero.
Do not skip an empty or whitespace-only first line to search later lines.
Then use split_whitespace, which recognizes Unicode whitespace and
never yields empty words. A lone \r is whitespace but is not a line
ending for lines: "one\rtwo" has two words on its first line.
Punctuation remains part of a word.
The returned length counts bytes, not Unicode scalar values or visible
characters. For example, "wörld" occupies six UTF-8 bytes.
Propagate absence inside Option
s.lines().next() returns Option<&str>. Applying ? extracts the
line or returns None from nth_word. The word lookup returns another
Option and can use ? in the same way.
Convert the selected slice into an owned String before returning it. Returning a slice into the consumed input would leave it referring to storage that the function drops.
Supply an error when returning Result
The starter applies ? directly to nth_word(s, n) inside a function
returning Result. That fails with E0277: an absent Option contains no
error value for the function to return.
Convert it first:
let word = nth_word(s, n)
.ok_or_else(|| format!("no word at index {n}"))?;
This fragment belongs inside nth_word_len. On success, ok_or_else
produces Ok(word), and ? extracts the String so you can return its
length. On absence, the closure creates the message and ? returns
that error immediately.
ok_or can express the same conversion, but its argument is evaluated
eagerly. Here ok_or(format!(...)) would format a message even when the
word exists. Use ok_or_else to defer that work.
Going from Result to Option is a different choice: .ok() discards an
error and turns it into None. Use that direction only when losing the
error details is intended.
Why unwrap does not meet the contract
An unchecked unwrap or expect would panic when the word is missing.
This function must return an error instead. The supplied source explicitly
denies Clippy's unwrap_used and expect_used lints, so those calls
also fail the lint check. Those lints are not enabled by default in Clippy.
? depends on both the operand and the return type of the enclosing
function or closure. Here the Option lookups belong in nth_word, and
the converted Result belongs in nth_word_len. For more detail, see
how the operator propagates failure.
The submission must compile, match the output cases and pass Clippy with warnings denied.
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.