Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C-style switch statement with fall-through in Rust [duplicate]

I’m new to Rust, but as a fan of Haskell, I greatly appreciate the way match works in Rust. Now I’m faced with the rare case where I do need fall-through – in the sense that I would like all matching cases of several overlapping ones to be executed. This works:

fn options(stairs: i32) -> i32 {
    if stairs == 0 {
        return 1;
    }
    let mut count: i32 = 0;
    if stairs >= 1 {
        count += options(stairs - 1);
    }
    if stairs >= 2 {
        count += options(stairs - 2);
    }
    if stairs >= 3 {
        count += options(stairs - 3);
    }
    count
}

My question is whether this is idiomatic in Rust or whether there is a better way.

The context is a question from Cracking the Coding Interview: “A child is running up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time. Implement a method to count how many possible ways the child can run up the stairs.”

like image 714
Denis Drescher Avatar asked Nov 17 '22 06:11

Denis Drescher


2 Answers

Based on the definition of the tribonacci sequence I found you could write it in a more concise manner like this:

fn options(stairs: i32) -> i32 {
    match stairs {
        0 => 0,
        1 => 1,
        2 => 1,
        3 => 2,
        _ => options(stairs - 1) + options(stairs - 2) + options(stairs - 3)
    }
}

I would also recommend changing the funtion definition to only accept positive integers, e.g. u32.

like image 94
ljedrz Avatar answered Dec 23 '22 00:12

ljedrz


To answer the generic question, I would argue that match and fallthrough are somewhat antithetical.

match is used to be able to perform different actions based on the different patterns. Most of the time, the very values extracted via pattern matching are so different than a fallthrough does not make sense.

A fallthrough, instead, points to a sequence of actions. There are many ways to express sequences: recursion, iteration, ...

In your case, for example, one could use a loop:

for i in 1..4 {
    if stairs >= i {
        count += options(stairs - i);
    }
}

Of course, I find @ljedrz' solution even more elegant in this particular instance.

like image 23
Matthieu M. Avatar answered Dec 22 '22 23:12

Matthieu M.