idiomatic-rustlisted
Install: claude install-skill rewrite-rs/skills
# Idiomatic Rust
This skill is about *expression*: what form does a Rust reader expect to see?
## The shape of idiomatic Rust
Prefer expressions over statements: a `match` that returns a value beats one that
assigns to a `let mut` in every arm, and a chain that produces the answer beats a
flag variable set in a loop and checked after it — let the type system carry
invariants instead of runtime checks. `let ... else` keeps an early return at the
top instead of drifting the happy path rightward under a nested `if let`;
`matches!` is the boolean test on a pattern. If-let chains compose conditions where
the toolchain supports them — a recent edition, so check the repo MSRV first.
## Iterators
Reach for the iterator pipeline before the index loop — `for i in 0..v.len() { ...
v[i] ... }` almost always has an iterator equivalent, and the iterator version fails
to compile on bad bounds instead of panicking at runtime. Collect into the type you
want, not a `Vec` you then convert:
```rust,ignore
// Reads like a translation.
let mut names = Vec::new();
for user in &users {
names.push(user.name.clone());
}
// Reads like Rust.
let names: Vec<String> = users.iter().map(|u| u.name.clone()).collect();
```
`collect` also targets `HashMap`, `HashSet`, `String`, and `Result<Vec<_>, _>` —
that last is how `?` composes with iteration.
```rust
use std::num::ParseIntError;
fn parse_all(lines: &[&str]) -> Result<Vec<i64>, ParseIntError> {
lines.iter().map(|line| line.parse::<i64>()