Checkpoint: Rust Basics

This checkpoint consolidates everything from the basics track — Cargo, operators, tuples and arrays, formatting, pattern matching, conversions, constants, and ordering — into one multi-step program you build yourself.

Learn Checkpoint: Rust Basics in our free Rust course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Rust course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

You'll review each idea quickly, then tackle a real build challenge that combines parsing, sorting, and formatting, with a full worked solution and a quiz to confirm it stuck.

What This Checkpoint Covers

1️⃣ Quick Recap of the Basics Track

Here's a single program that exercises one idea from each earlier lesson — destructuring, expression-based if , matching a parsed Result , a const with formatted output, and a sort. If every line makes sense, you're in great shape for the build challenge.

📋 The Eight Skills in One Table

2️⃣ Build Challenge: A Scoreboard Report

Now put it together. You'll parse messy input into structs (skipping bad lines), sort with a tie-breaker, and print an aligned, formatted report with an average. This single task uses tuples/Options, conversions, ordering, and formatting at once.

Read the step-by-step plan in the comments, then implement it. Try it fully before opening the solution below.

One clean way to do it. The ? operator inside parse_record turns a failed split or parse into an early None , and filter_map drops those. This compiles and produces exactly the target output:

📝 Checkpoint Quiz

Answer each in your head, then expand to check. No peeking first!

cargo check . It runs the compiler's analysis but skips code generation, so it's much faster than cargo build for catching errors while you iterate.

The trailing semicolon after 42 turns it into a statement, so the block has no final expression and yields the unit value () . Drop the semicolon ( {' '} ) and the block evaluates to 42.

It produces 44 , because the cast wraps the bits to fit a u8 . Use u8::try_from(300) , which returns an Err instead of silently losing data.

Use let else when you want to bind the inner value for the rest of the function and bail out early on failure — its else block must diverge (return/break/panic). if let is for doing something only inside the matched block, with the binding scoped to that block.

Floats only implement PartialOrd , not Ord , because NaN is unordered. sort requires Ord . Use sort_by(|a, b| a.total_cmp(b)) instead.

A const has no fixed address — it's inlined at every use site. A static has one fixed memory location and the lifetime, lasting the whole program. Prefer const unless you specifically need a single shared address.

Practice quiz

Which Cargo command type-checks your code quickly without producing a runnable binary?

  • cargo build
  • cargo run
  • cargo check
  • cargo fmt

Answer: cargo check. cargo check runs the compiler's analysis but skips code generation, so it is much faster than cargo build for catching errors while iterating.

In Rust, what does the block 'let x = { 42; };' evaluate to?

  • the unit value ()
  • 42
  • a compile error
  • None

Answer: the unit value (). The trailing semicolon after 42 turns it into a statement, so the block has no final expression and yields the unit value (). Drop the semicolon to get 42.

What does '300_i32 as u8' produce?

  • 300
  • 255 (clamped)
  • a compile error
  • 44 (wrapped bits)

Answer: 44 (wrapped bits). The as cast wraps the bits to fit a u8, giving 44. Use u8::try_from(300) to get an Err instead of silently losing data.

How do you destructure the tuple '(12, 30)' into two bindings a and b?

Tuples are destructured with parentheses: let (a, b) = (12, 30); binds a to 12 and b to 30.

When matching an Option, when is 'let else' a better fit than 'if let'?

  • When you want to bind the inner value for the rest of the function and bail out early on failure
  • When you only need the value inside a small scoped block
  • When the Option is always Some
  • let else cannot be used with Option

Answer: When you want to bind the inner value for the rest of the function and bail out early on failure. let else binds the inner value for the remaining function body and its else block must diverge (return/break/panic). if let scopes the binding to the matched block only.

Why can't you call '.sort()' directly on a Vec<f64>?

  • f64 has no comparison at all
  • sort only works on integers
  • f64 implements PartialOrd but not Ord because NaN is unordered
  • Vec<f64> is not allowed

Answer: f64 implements PartialOrd but not Ord because NaN is unordered. Floats implement only PartialOrd (NaN is unordered), and sort requires Ord. Use sort_by(|a, b| a.total_cmp(b)) instead.

What is the key difference between a const and a static in Rust?

  • const is mutable, static is not
  • const is inlined at each use site; static has one fixed memory address
  • They are completely interchangeable
  • static can only hold integers

Answer: const is inlined at each use site; static has one fixed memory address. A const is inlined at every use site with no fixed address, while a static has one fixed memory location and the 'static lifetime for the whole program.

Why does 'filter_map' pair so well with a parser that returns Option<Record>?

  • It keeps the None values and discards the Some values
  • It panics on any None
  • It only works with Result, not Option
  • It both drops the None values and unwraps the Some values in one pass

Answer: It both drops the None values and unwraps the Some values in one pass. filter_map keeps only the Some values, unwrapping them, while silently dropping the Nones, filtering and extracting in a single pass.

In 'b.score.cmp(&a.score).then(a.name.cmp(&b.name))', what does .then(...) do?

  • It always uses the second ordering
  • It returns the first ordering unless it is Equal, then falls through to the second
  • It reverses both orderings
  • It panics if the first ordering is Equal

Answer: It returns the first ordering unless it is Equal, then falls through to the second. Ordering::then returns the first ordering unless it is Equal, in which case it uses the second — a clean way to express a tie-breaker.

Which format placeholder left-aligns a value in a field width of 6?

  • {:>6}
  • {:^6}
  • {:<6}
  • {:6.0}

Answer: {:<6}. {:<6} left-aligns in a width of 6; {:>6} right-aligns and {:^6} centers. The '<' chooses left alignment.