Skip to content

← Ground Rules: Values, Types, Control Flow step 9 of 24

Easy Primitives

bool and char

Classify every character of a string as "digit", "alpha", "space" or "other", in order.

pub fn char_kinds(text: &str) -> Vec<String>

Test them in that order: a digit is a digit even though it is not alphabetic, and anything that is neither a digit, nor a letter, nor whitespace is "other".

"a1 é" gives ["alpha", "digit", "space", "alpha"]four results, from a string that is five bytes long. That gap is the entire point.

The starter fails the gate on a clippy lint that exists specifically to catch a beginner reflex.

char is four bytes and holds a Unicode scalar value

In C, char is a byte. In Rust it is not. A char is exactly 4 bytes and holds one Unicode scalar value — any code point from U+0000 to U+10FFFF, excluding the surrogate range U+D800..=U+DFFF which exists only as a UTF-16 implementation detail.

So 'é' is one char. '語' is one char. '🦀' is one char. Each of them occupies four bytes as a char value, and two, three or four bytes when encoded into a UTF-8 string.

That is why "a1 é" is five bytes but four characters, and it is the seed of the whole UTF-8 story that item 1.24 tells properly. Two ways of walking a string:

text.chars()   // yields char — what a human means by "character"
text.bytes()   // yields u8   — what the memory actually contains

Reaching for .bytes() here would give you five results and would misclassify the two halves of é as "other". .chars() is the one you want.

Useful predicates, all on char:

  • is_ascii_digit() — strictly '0'..='9'. There is also is_numeric(), which is true for '٣' and 'Ⅳ' too; pick deliberately.
  • is_alphabetic() — Unicode-aware, so 'é', 'Ω' and '語' all qualify.
  • is_whitespace() — Unicode-aware, so non-breaking space counts.
  • is_ascii_alphanumeric(), is_uppercase(), to_ascii_lowercase(), and more.

bool is a type, not an integer

Rust’s bool has exactly two values and does not convert to a number by itself. if x requires x: bool — an integer will not do, and if 1 is E0308. There is no truthiness. This removes an entire class of C bug and occasionally annoys you for about four seconds.

Three default-on clippy lints police the beginner reflexes here, and you will meet the first one in the starter:

  • bool_comparisonx == true is just x, and x == false is !x. Comparing a boolean to a boolean literal adds a comparison and subtracts clarity.
  • needless_boolif cond { true } else { false } is just cond.
  • char_lit_as_u8'A' as u8 compiles but is almost always a mistake in disguise; b'A' is a byte literal and says what you meant.

None of these need configuration. They are on for everyone, by default, and they are exactly the mistakes a newcomer makes — the gate does real teaching here for free.

Building the answer

Bind one &str from an if/else if chain, then convert it to a String when you push it. Four string literals and one conversion; no format! needed, and useless_format would tell you so if you tried.