Rust模式匹配在向量上的应用

37
教程 展示了一些非常基本的模式匹配示例,例如匹配整数以模拟 C 风格的 switch 语句。教程还展示了如何对元组类型进行基本解构和结构解构。
似乎应该可以对向量进行模式匹配,但我无法弄清楚它的正确语法,并且我没有找到任何示例。
例如,在 Haskell 中,您可以轻松地解构列表:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr func initValue []     = initValue
foldr func initValue (x:xs) = func initValue $ foldr initValue func xs

因此,从大致的翻译来看,能够做到以下几点会很不错:

fn foldr<A, B>(func: fn(A, B) -> B,
               initValue: B,
               vals: [A]) -> B {
  alt vals {
    [] { ret initValue; }
    _  {
      let h = vec::head(vals),
          t = vec::tail(vals);
      ret foldr(func, func(initValue, h), t);
    }
  }
}
<注意:我知道你可以在这里使用if语句,但我只是用它作为一个在向量上进行模式匹配的例子。>

目前返回:

patterns.rs:10:4: 10:5 error: constant contains unimplemented expression type
patterns.rs:10     [] { ret initValue; }
                ^
error: aborting due to previous errors

在解构使用{ .. }定义的结构体和( .. )定义的元组的教程中有一个例子,因此似乎应该内置支持向量,因为它们也包含特殊语法[ .. ]。如果我使用向量的方式不正确,请随时纠正我。

有点离题,但对于尾调用,你应该使用“be”而不是“ret”。 - Ian B.
@ian-b 有趣的是,教程语言参考似乎已经过时了,它们提到be作为一个关键字,但目前并没有任何参考。 - ash
2个回答

47

您需要使用切片模式

fn vec_alt<T>(vals: Vec<T>) -> &'static str {
    match vals[..] {
        [a, b] => "two elements",
        [a, b, c] => "three elements",
        _ => "otherwise",
    }
}

1
Clippy不喜欢这个:"错误:对向量进行索引可能会导致崩溃"。 - skainswo
4
如果没有指定 T: Copy,你需要添加一个引用:match &vals[..]。如果没有 &,你就试图将非复制切片 vals[..] 移动到匹配中。(在匹配中不需要模式的引用;我假设有一个自动解引用开关发生了。) - BallpointBen
2
切片模式是如何组合的?例如,如何匹配Option<Vec<Vec<u8>>>? - user239558

8

我希望能够提供更多关于如何最好地在向量上使用模式匹配的一般建议,但是以下是你可以使用它们来测试空向量的方法(至少我认为这就是该Haskell代码正在做的事情...):

use std;
import std::io::println;

fn main() {
    let empty: [int] = [];
    println(vec_alt(empty));
    println(vec_alt([1,2,3]));
}

fn vec_alt<A>(vals: [A]) -> str {
    alt vals {
        x if x == [] { "empty" }
        _ { "otherwise" }
    }
}

请注意,尝试简单地将[]作为参数传递会失败,因为编译器无法为向量推断类型。似乎可以在未声明的情况下传递[()](一个内部带有nil的向量),但是alt语句似乎无法测试头表达式是否与[()]匹配(它只是转到默认值)。
总的来说,向量目前似乎有些粗糙。如果您有特定的用途,Rust似乎不支持,请告知开发人员: https://mail.mozilla.org/listinfo/rust-dev 还可以参考参考手册以获得更正式的定义和一些更多的示例来帮助澄清事情: http://doc.rust-lang.org/doc/rust.html#alternative-expressions

6
我认为目前还不支持这个。我提交了一个RFC来扩展解构以支持向量。在那个问题中,我有另一个例子,认为它有助于展示问题。无论如何,这将是一个不错的功能。希望将来能够实现类似这样的功能。 - ash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接