Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Activity 12: Write the Match

How this works

The problems are on this paper, but you'll work through the problems in Rust Playground, and the finished functions go to Gradescope.

  1. Open play.rust-lang.org
  2. For each problem, copy the type (struct/enum) and the function signature into the playground
  3. Write the match that makes the function produce the results in the table
  4. Write a fn main that calls it with the examples, and check you get what the table says
  5. Paste your finished functions into the Gradescope assignment

Work with the people around you. But you'll submit individually.

A worked example

The problem gives you this:

enum Coin { Penny, Nickel, Dime }

fn value(c: Coin) -> u32 {
    // your code here
}
CallReturns
value(Coin::Penny)1
value(Coin::Dime)10

You write the body, and a main to check it:

enum Coin { Penny, Nickel, Dime }

fn value(c: Coin) -> u32 {
    match c {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
    }
}

fn main() {
    println!("{}", value(Coin::Penny));
    println!("{}", value(Coin::Dime));
}

When you run it, if it prints 1 and 10, the problem is done.

Problem 1: Which way are we going

enum Direction { North, East, South, West }

fn label(dir: Direction) -> String {
    // your code here
}
CallReturns
label(Direction::North)"going north"
label(Direction::East)"going east"
label(Direction::South)"going south"
label(Direction::West)"going west"

Problem 2: A score that might not exist

fn describe(score: Option<u32>) -> String {
    // your code here
}

Tip: to return an owned string you can use format! instead of println! to create a string with variable values. And to make a String out of a "string literal" like "hello" you need to use "hello".to_string().

CallReturns
describe(Some(95))"scored 95"
describe(Some(0))"scored 0"
describe(None)"did not take it"

Problem 3: Class standing

Match on a struct, ignoring the fields you don't need.

struct Student {
    name: String,
    year: u32,
    credits: u32,
}

fn standing(s: &Student) -> String {
    // your code here
}
CallReturns
standing(&Student { name: String::from("Kesar"), year: 3, credits: 96 })"senior"
a student with 72 credits"junior"
a student with 30 credits"sophomore"
a student with 12 credits"first year"

Senior is 90 credits or more, junior 60, sophomore 30.

Problem 4: Adding up to n

You'll use recursion here. You'll write a match with a base case and a recursive call.

fn sum_to(n: u32) -> u32 {
    // your code here
}

sum_to(4) is 4 + 3 + 2 + 1 + 0.

CallReturns
sum_to(0)0
sum_to(4)10
sum_to(10)55

Problem 5: The first even number

This one is more challenging. This needs a loop as well as a match, and it returns an Option.

fn first_even(nums: [u32; 5]) -> Option<u32> {
    // your code here
}
CallReturns
first_even([1, 3, 6, 7, 8])Some(6)
first_even([2, 4, 6, 8, 10])Some(2)
first_even([1, 3, 5, 7, 9])None

Solutions

Problem 1: Direction

fn label(dir: Direction) -> String {
    match dir {
        Direction::North => String::from("going north"),
        Direction::East  => String::from("going east"),
        Direction::South => String::from("going south"),
        Direction::West  => String::from("going west"),
    }
}

Four arms, one per variant, and no _ needed. The return type is String, so we need this or "going north".to_string() technically.

Problem 2: a score that might not exist

fn describe(score: Option<u32>) -> String {
    match score {
        Some(n) => format!("scored {}", n),
        None => "did not take it".to_string(),
    }
}

Some(n) names the number so you can use it on the right. Two arms covers the whole type: an Option has nothing else in it.

Problem 3: class standing

fn standing(s: &Student) -> String {
    match s {
        &Student { credits, .. } if credits >= 90 => String::from("senior"),
        &Student { credits, .. } if credits >= 60 => String::from("junior"),
        &Student { credits, .. } if credits >= 30 => String::from("sophomore"),
        _ => String::from("first year"),
    }
}

Biggest number first. Put >= 30 at the top and every senior is a sophomore.

.. ignores name and year. The & is there because s is a &Student.

Problem 4: adding up to n

fn sum_to(n: u32) -> u32 {
    match n {
        0 => 0,
        _ => n + sum_to(n - 1),
    }
}

The base case is the arm that does not call itself. Without it, n - 1 runs past zero and a u32 cannot go negative.

Problem 5: the first even number

fn first_even(nums: [u32; 5]) -> Option<u32> {
    for n in nums {
        match n % 2 {
            0 => return Some(n),
            _ => {}
        }
    }
    None
}

return leaves the whole function the moment you find one. None sits after the loop, for when it finishes without finding anything.