正确的锈匹配成语

时间:2014-02-01 05:06:52

标签: recursion switch-statement rust

我意识到语言是0.9 / 0.10并且仍在进行重大更改(比如本周放弃do?),但很想知道我是否在这里使用声音惯用语。我已经实现了两个版本的变更算法,一个是天真的,另一个看起来更好“。在我看来。

这是0.9。两个片段在一对assert!

中编译并产生相同的结果
fn count_change_naive(cents: int, coins: &[int]) -> int {
    if (cents == 0) {
        1
    } else if (cents < 0) {
        0
    } else {
        if coins.iter().len() > 0 {
            let new_amount: int = cents - coins[0];
            let coins_tailed: &[int] = coins.tail();
            count_change_naive(cents, coins_tailed) + count_change_naive(new_amount, coins)
        } else {
            0
        }
    }
}

这是非常笨拙的IMO。我试图实现以下内容:

fn count_change_idiomatic(cents: int, coins: &[int]) -> int {
    match cents {
        n if cents == 0                     => 1,
        n if cents < 0                      => 0,
        n if coins.iter().len() > 0         => {
            let new_amount: int = cents - coins[0];
            let coins_tailed: &[int] = coins.tail();
            count_change_idiomatic(cents, coins_tailed) + count_change_idiomatic(new_amount, coins)
        },
        _                                   => 0
    }
}

由于匹配中的n,我得到了未使用的变量警告,但我不确定如何在没有丑陋的if-else金字塔的情况下避免这种情况。可以吗?我在第二次实施中遗漏了哪些重要内容?

编辑:已经清理了一些以满足一些建议,但完好无损地进行了比较

3 个答案:

答案 0 :(得分:5)

为了不获取您没有用的变量的警告,您只是不使用它:

fn count_change_idiomatic(cents: int, coins: &[int]) -> int {
    match cents {
        _ if cents == 0                     => 1,
        _ if cents < 0                      => 0,
        _ if coins.iter().len() > 0         => {
            let new_amount: int = cents - coins[0];
            let coins_tailed: &[int] = coins.tail();
            count_change_idiomatic(cents, coins_tailed) + count_change_idiomatic(new_amount, coins)
        },
        _                                   => 0
    }
}

答案 1 :(得分:5)

您可以在向量上使用模式匹配来避免长度,索引和拖尾:

fn count_change_idiomatic(cents: int, coins: &[int]) -> int {
    match (cents, coins) {
        (0, _)                        => 1,
        _ if cents < 0                => 0,
        (_, [first, .. coins_tailed]) => {
            let new_amount = cents - first;
            count_change_idiomatic(cents, coins_tailed) + 
                count_change_idiomatic(new_amount, coins)
        }
        _                             => 0
    }
}

模式的..部分与向量的其余部分匹配(在这种情况下,除了第一个元素之外的所有部分)。

答案 2 :(得分:2)

这是对事物的重大简化,改进各种惯用事物:

fn count_change_naive(cents: int, coins: &[int]) -> int {
    if cents == 0 {
        1
    } else if cents < 0 {
        0
    } else if coins.len() > 0 {
        let new_amount = cents - coins[0];
        let denom_tailed = coins.tail();
        count_change_naive(cents, denom_tailed) + count_change_naive(new_amount, coins)
    } else {
        0
    }
}
  • 在没有必要时避免return;
  • 围绕if陈述
  • 中的条件没有括号
  • 四个空格而不是两个(标准的Rust社区风格)
  • 尽可能减少if / else内容的嵌套(else { if A { B } else { C } }else if A { B } else { C }

我用适当的信息做出了另一个改变:自由评论事物的意义。可能甚至将递归调用转移到它们自己的语句中(这通常会增强可读性并且没有运行时成本):

let ???1 = count_change_naive(cents, demon_tailed);
let ???2 = count_change_naive(new_amount, coins);
???1 + ???2