匹配一段 str 或 String

Match a slice of str or String

我有一个函数可以根据切片取 &[&str]&[String] 和 return 不同的值。如果我添加 PartialEq 约束,使用 == 效果很好:

pub fn info1<'a, S>(path: &[S]) -> Option<String>
where
  S: PartialEq<&'a str>,
{
  if path == ["a", "b"] {
    return Some("It's a-b!".to_string())
  }
  None
}

但是如果我用 match:

就不行了
pub fn info2<'a, S>(path: &[S]) -> Option<String>
where
  S:  PartialEq<&'a str>,
{
  match path {
    ["a", "b"] => Some("It's a b!".to_string()),
    _ => None,
  }
}
error[E0308]: mismatched types
  --> src/lib.rs:16:6
   |
11 | pub fn info2<'a, S>(path: &[S]) -> Option<String>
   |                  - this type parameter
...
15 |   match path {
   |         ---- this expression has type `&[S]`
16 |     ["a", "b"] => Some("It's a b!".to_string()),
   |      ^^^ expected type parameter `S`, found `&str`
   |
   = note: expected type parameter `S`
                   found reference `&'static str`

Playground

有什么办法让它起作用吗?理想情况下不需要像 ["a".as_foo(), "b".as_foo()].

这样的东西

您不能为此使用 match

你的第一个版本没有问题。您可以使用 higher-ranked trait bound (for<'a>):

使其更通用
pub fn info1<S>(path: &[S]) -> Option<String>
where
    for<'a> S: PartialEq<&'a str>,
{
    if path == ["a", "b"] {
        Some("It's a-b!".to_string());
    } else {
        None
    }
}

我得到了一个有用的答案from the Rust Forum. It isn't possible to use match because patterns in match can only consist of structs, enums, slices and literals. The best description of that I found is here:

A pattern consists of some combination of the following:

  • Literals
  • Destructured arrays, enums, structs, or tuples
  • Variables
  • Wildcards
  • Placeholders

在这种情况下,像 "a" 这样的字符串文字是 &str,所以这确实是您可以 match 反对的唯一一种字符串(您可以看到人们基本上同样的问题,但没有切片 here)。在那种情况下,您可以在不分配的情况下解决它,因为您不需要构建引用切片 - 您只需要一个。

因为你肯定需要一片 &strs 所以除了分配一个 Vec<&str> as suggested by Skysch:

真的别无他法
pub fn info1<'a, S>(path: &[S]) -> Option<String>
where
  S: AsRef<str>,
{
  match &path.iter().map(|s| s.as_ref()).collect::<Vec<_>>()[..] {
    ["a", "b"] => Some("It's a b!".to_string()),
    _ => None,
  }
}

我认为即使使用 macro_rules! 你也无法使用 match 解决它。然而,可以制作一个使用 == 的类似于 match 的宏。