【问题标题】:Does Rust 2018 support "if let" chaining?Rust 2018 是否支持“if let”链接?
【发布时间】:2018-11-10 02:17:55
【问题描述】:

我正在解析每个枚举类型的标记向量。这意味着我会得到很多代码,例如:

if v.len() >= 3 {
    if let Token::Type1(value1) = &v[0] {
        if let Token::Type2(value2) = &v[1] {
            if let Token::Type(value3) = &v[2] {
                return Parsed123(value1, value2, value3);
            }
        }
    }
}

这很丑 - 我已经知道我可以这样做让它变得更好一点:

if v.len() >= 3 {
    if let (Token::Type1(value1), Token::Type2(value2), Token::Type3(value3)) =
        (&v[0], &v[1], &v[2])
    {
        return Parsed123(value1, value2, value3);
    }
}

但老实说,它并没有好多少。

但是,有一些已解决的问题/RFC 以更符合人体工程学的方式链接这些条件和“如果让”位 - Tracking issue for eRFC 2497 "if- and while-let-chains take 2"Support && in if let expressions - 这让我可以写如下内容:

if v.len() >= 3 &&
    let Token::Type1(value1) = &v[0] && 
    let Token::Type2(value2) = &v[1] && 
    let Token::Type3(value3) = &v[2]
{
    return Parsed123(value1, value2, value3);
}

但是,我似乎无法使用edition="2018"(确切版本为1.32.0-nightly (653da4fd0 2018-11-08))在我的夜间Rust 副本中编译它。因此,要么我的语法错误,要么我误解了 RFC / 问题,而这个功能还没有落地。无论哪种方式,我都希望了解有关此功能的一些信息。

【问题讨论】:

  • 你可能会觉得this library很有趣。
  • @Michail 这个库看起来棒极了!我想知道这是否可以通过宏来实现。我认为值得自己回答并添加了一个。希望你没事。
  • if let [Token::Type1(value1), Token::Type2(value2), Token::Type3(value3), ..] = v 怎么样?
  • @L.F.这当然是现在的一个选择。这仅在 2020 年 3 月 12 日的 1.42.0 中稳定锈蚀。您可以在此处查看发行说明。 blog.rust-lang.org/2020/03/12/Rust-1.42.html#subslice-patterns.
  • 哦,对了..是时候学习一些历史了。

标签: rust


【解决方案1】:

RFC #2497not been implemented yetGitHub issue you linked 仅用于描述to deal with the ambiguity 的方式。

要启用上一节中的第二种解释,必须在 Rust 2015 中发出警告,通知用户 [...] 都将成为硬错误,在 2018 版稳定的第一个 Rust 版本中,没有let_chains 功能已经稳定。

所以不,您还不能使用该语法,而是使用元组作为解决方法,就像您已经做过的那样。

if v.len() >= 3 {
    if let (Token::Type1(value1), Token::Type2(value2), Token::Type3(value3)) =
        (&v[0], &v[1], &v[2])
    {
        return Parsed123(value1, value2, value3);
    }
}

【讨论】:

  • 值得注意的是,当 RFC 实施时,Rust 2015 和 2018 都将支持它。
  • 啊,所以 let 这个位置的表达式是实验性的,请参阅问题 #53667 github.com/rust-lang/rust/issues/53667> 了解更多信息 rustc(E0658) 表示“抱歉,未实现” ..
【解决方案2】:

虽然 2018 年(和 2015 年)尚不支持 RFC #2497 是正确的,但我觉得 Michail 提到的 if_chain 库值得回答。

if_chain 库提供了一个宏,可以将一些几乎采用 RFC #2497 形式的代码转换为有效的 Rust。

你可以写:

if_chain! {
    if v.len() >= 3;
    if let Token::Type1(value1) = &v[0]; 
    if let Token::Type2(value2) = &v[1]; 
    if let Token::Type3(value3) = &v[2];
    then {
        return Parsed123(value1, value2, value3);
    }
}

编译器将其视为:

if v.len() >= 3 {
    if let Token::Type1(value1) = &v[0] {
        if let Token::Type2(value2) = &v[1] {
            if let Token::Type(value3) = &v[2] {
                return Parsed123(value1, value2, value3);
            }
        }
    }
}

【讨论】:

    【解决方案3】:

    正如 L.F. 在 cmets 中提到的,2020 年现在有另一种选择。它仍然没有给我们链接if let,但确实允许我们在切片上进行匹配——这足以使这个例子变得非常整洁。代码现在可以写成

    if let [Token::Type1(value1), Token::Type2(value2), Token::Type3(value3), ..] = v {
       return Parsed123(value1, value2, value);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-04
      • 2014-09-24
      • 2013-04-10
      • 1970-01-01
      • 1970-01-01
      • 2013-10-27
      相关资源
      最近更新 更多