Rust 2018是否支持"if let"链接?

Mic*_*son 7 rust

我正在解析一个令牌的矢量,每个枚举类型.这意味着我得到了很多代码:

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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这非常难看 - 我已经知道我可以做到这一点,使它更好一点:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

然而,有一些封闭的问题/ RFC用于链接这些条件,并且"如果让"位在感觉更符合人体工程学的方式 - eRFC 2497的跟踪问题"if- and while-let-chains取2"并且支持&& in if让表达式 - 这会让我写下这样的东西:

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);
}
Run Code Online (Sandbox Code Playgroud)

但是,我似乎无法在我的夜间Rust的副本中编译edition="2018"(确切的版本是1.32.0-nightly (653da4fd0 2018-11-08)).所以要么我的语法错误,要么我误解了RFC /问题,而且这个功能还没有登陆.无论哪种方式,我都喜欢这个功能的一些信息.

hel*_*low 11

RFC 2497#没有实现.您链接GitHub问题仅用于描述如何处理歧义.

为了在上一节中启用第二种解释,必须在Rust 2015中发出警告,通知用户两者都将成为硬错误,在第一版的Rust中,2018版本是稳定的,没有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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,当实施RFC时,Rust 2015和2018都将支持它。 (2认同)

Mic*_*son 5

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

编译器将其视为:

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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*son 5

正如 LF 评论中提到的,2020 年现在有了另一种选择。它仍然没有给我们 chained if let,但确实允许我们在切片上进行匹配 - 这足以使这个例子变得非常简洁。现在代码可以写成

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