TypeVelo.
← Drills Hub

Rust Typing Drill

& : < > ! ( ) { } _ -

Every passage contains: & : < > ! ( ) { } _ - · :: ->

Net 0 wpmGross 0 wpmAcc 100%
println!("{} rows", rows.len()); } for _ in 0..row_count { let text = String::from("row"); fn total(rows: &[Row]) -> u32 { rows.iter().map(|r| r.count).sum() let text = String::from("row"); let text = String::from("row"); let text = String::from("row"); impl Reader for FileReader { pub struct Row { id: u32, name: String } let mut cache: HashMap<String, u32> = HashMap::new(); impl Reader for FileReader { match value { Some(n) => n * 2, let text = String::from("row"); println!("{} rows", rows.len()); } let text = String::from("row"); for _ in 0..row_count { Some(n) => n * 2, impl Reader for FileReader { Some(n) => n * 2, pub struct Row { id: u32, name: String } None => 0, } let row_count = rows.len(); let mut cache: HashMap<String, u32> = HashMap::new(); rows.iter().map(|r| r.count).sum() for _ in 0..row_count { let row_count = rows.len(); Some(n) => n * 2, let row_count = rows.len(); let mut cache: HashMap<String, u32> = HashMap::new(); } let text = String::from("row"); impl Reader for FileReader { println!("{} rows", rows.len()); rows.iter().map(|r| r.count).sum() for _ in 0..row_count {

QWERTY layout assumed. Backspace corrects; uncorrected errors count against net WPM.

HashMap::new() and String::from("row") both use the double colon, and both ask the right pinky to press the same key twice in a row, holding Shift across both presses, with no letter in between to give the finger a moment to reset. fn total(rows: &[Row]) -> u32 { asks for something else entirely: its arrow opens with that identical unshifted hyphen, then moves one finger over to a character that does need Shift, pulled in from the opposite hand for a single beat before the line carries on.

& and ! show up as ordinary parts of everyday lines rather than as rare exceptions. for row in &rows { and fn read(&self) -> Result<String, Error> { both use the ampersand glued directly against the word that follows it, with no space at all — a different job from the same character in R&D or up&down, where it sits between two already-complete words. println!("{} rows", rows.len()); attaches an exclamation mark straight onto the end of a macro's name, marking it as a macro rather than closing out a sentence.

match value { Some(n) => n * 2, None => 0, } uses the same arrow the JavaScript Typing Drill trains for a completely different purpose — routing to one of two outcomes rather than defining a function — and for _ in 0..row_count { pairs two unshifted periods back to back, the same same-key-twice shape as :: without any Shift involved at all.

Why This Drill

The double colon deserves attention precisely because it recurs whenever a type or one of its own functions gets named — HashMap::new(), String::from — asking the identical finger to fire twice in immediate succession with Shift held the whole time. The Semicolon & Colon Drill treats colon as a single, isolated decision; this passage asks for the same key held down through two full presses back to back.

The arrow's second half is the only part of that line needing a modifier at all, and it arrives one keystroke after a character that needed none whatsoever — a sharper contrast than the JavaScript Typing Drill's own arrow, which spends its unshifted half on an equals sign rather than a hyphen, so two different languages build an identical two-step handoff out of two different opening characters.

& and ! glued directly against the words beside them are a different job for both marks than the Shifted Top Row Drill trains — that drill's stop! closes a whole word with a bang at the very end, while println!'s exclamation mark is part of the name itself, and &rows opens a reference rather than joining two finished words the way R&D does.

Two Colons, Same Finger, No Letter Between Them

HashMap::new() and String::from("row") each ask the right pinky to press the semicolon-and-Shift combination twice in immediate succession, holding Shift across both presses rather than releasing it in between. That's a heavier version of the single colon decision the Semicolon & Colon Drill isolates on its own.

A Hyphen and a Shifted Character Crossing Hands

The hyphen half of -> asks for nothing beyond an ordinary right-pinky press with no modifier at all. The half right after it does need Shift, and that Shift comes from the hand that had no part in the hyphen a moment earlier — a handoff between hands rather than one finger's job. fn total(rows: &[Row]) -> u32 { needs that crossing exactly once, in the middle of an otherwise unshifted line.

An Ampersand That Opens Instead of Joins

for row in &rows { and fn read(&self) -> Result<String, Error> { both press the ampersand directly against the word right after it, with no space at all — opening a reference rather than sitting between two complete words the way it does in an expression like R&D.

Two Periods Doing What Two Colons Do, Without Shift

for _ in 0..row_count { presses the period key twice in a row with nothing between them, the same same-key-repeated shape as :: but entirely unshifted — a quieter version of the identical idea, since no modifier has to be held across either press.

Frequently Asked Questions

Why does typing :: feel harder than typing a single colon?

It asks the same right pinky to press the same shifted key twice in a row with no letter in between to give it a moment to reset, rather than the single, isolated shift decision an ordinary colon requires.

What's actually happening in the hands during ->?

First an ordinary hyphen with no modifier involved at all, then, on the very next press, a character that needs Shift supplied by the hand that had nothing to do with the hyphen a moment before.

Does & always sit between two words the way it does in R&D?

Not in Rust. &rows and &self press the ampersand directly against the identifier that follows, with no space at all, since it's opening a reference rather than joining two already-finished words.

Why does println! need an exclamation mark at all?

It marks the name as a macro rather than an ordinary function call, and the mark attaches directly to the end of the word — a different role from the same key closing out a sentence or an interjection elsewhere.

Is 0..row_count typed with the same motion as HashMap::new()?

The shape is similar — the same key pressed twice with nothing between the presses — but the range operator uses the unshifted period, while the double colon needs Shift held across both presses, so the two aren't the same physical motion.

How does Rust's closure syntax |r| compare to the pipe used elsewhere in this batch?

rows.iter().map(|r| r.count) presses the pipe twice in a handful of characters, bracketing a single letter — a tighter, denser use of the key than the TypeScript Typing Drill's union types, which space a pipe between whole quoted words instead.