rust-lang / rust-lang/book

Suggestion: Section 4.3 `first_word` example could be updated to use simpler, UTF-8-friendly iteration.

Open
#2,883 3 comments 7 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Q for ourselves
Dominant language
Rust
Stars
18.3k
Forks
4.1k
Avg merge
14m
Merged PRs (30d)
1

Description

The first_word() example in Section 4.3 currently iterates over the String's individual bytes, rather than Unicode characters:

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[0..i];
        }
    }

    &s[..]
}

This happens to work because the ASCII space character (or any ASCII character, for that matter) it's looking for can't appear in the middle of a multi-byte UTF-8 character sequence, but it seems like bad practice regardless, and it's one of a new Rust developer's first exposures to String handling in the book. Instead, the example could be made more UTF-8 friendly and simpler by using String::char_indices():

fn first_word(s: &String) -> &str {
    // String slices are based on byte offsets, but require you to slice at valid UTF-8
    // character boundaries. We can solve this with String::char_indices(), which gives
    // us the real UTF-8 byte offset with each unicode character, allowing us to slice
    // naturally while still handling UTF-8 character boundaries safely.
    for (idx, c) in s.char_indices() {
        if c == ' ' {
            return &s[..idx];
        }
    }
    return &s[..];
}

This also works with the "return an index" version, since idx has the same semantics as i in the original example.

I understand that this isn't the chapter to get deep into Unicode handling, and there is certainly more to Unicode than individual "characters", but I don't think changing the example in this way would distract from the lessons about slicing or require too much (if any) additional explanation than the existing solution, and it has the benefit of encouraging new developers to use UTF-8-friendly functions from the start. It also guides new developers toward useful, more UTF-8-friendly char functions like is_whitespace().

Is this a reasonable update to slip into the next edition of the book, or do you think this cracks opens the Pandora's Box of Unicode a little too much?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Section 4.3 first_word() example and compare its byte-iteration version with the proposed String::char_indices() approach. Check whether the return-an-index example has the same assumptions. Done means the relevant examples and surrounding explanation consistently reflect the accepted UTF-8 handling decision.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
documentation
Issue type
Documentation
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.