【问题标题】:"if let" vs "unwrap_or_else" for callback call\"if let\" vs \"unwrap_or_else\" 用于回调调用
【发布时间】:2022-08-14 10:58:02
【问题描述】:

谁能解释为什么这个 Rust 代码编译得很好:

if let Err(why) = match cmd.name {
    \"info\" => info,
    \"ping\" => ping,
    \"profile\" => profile,
    _ => panic!(),
}(&ctx, &cmd)
.await
{
    println!(\"An error occured while handling command: {}\", why);
}

...但是这段代码不会(编译器说我需要在关闭匹配块后使用分号):

match cmd.name {
    \"info\" => info,
    \"ping\" => ping,
    \"profile\" => profile,
    _ => panic!(),
}
(&ctx, &cmd)
    .await
    .unwrap_or_else(|why| println!(\"An error occured while handling command: {}\", why))

我发现的唯一解决方案是在调用它之前使用一个临时变量来存储回调,但我不明白为什么只有在第二个代码示例中才需要这样做:

let callback = match cmd.name {
    \"info\" => info,
    \"ping\" => ping,
    \"profile\" => profile,
    _ => panic!(),
};
callback(&ctx, &cmd)
    .await
    .unwrap_or_else(|why| println!(\"An error occured while handling command: {}\", why))

我怀疑它与声明与表达式有关,但我似乎无法弄清楚。

  • 你试过(match cmd.name { ... })(&ctx, &cmd)吗?此外,传递给unwrap_or_else 的闭包必须返回与Ok 相同的类型。
  • @PitaJ 它确实有效,但你知道为什么吗? (运算符优先级?)
  • @prog-fh 我相信这是因为当 match 语句位于赋值的右侧时,它被认为是一个表达式。但是当直接使用这个值时,Rust 解析器需要在你立即调用它之前确定匹配是一个表达式。也就是为什么括号让编译器高兴。

标签: rust callback


【解决方案1】:

https://doc.rust-lang.org/stable/reference/statements.html#expression-statements

仅由block expression 或控制流表达式组成的表达式,如果在允许语句的上下文中使用,则可以省略尾随分号。这可能会导致它在被解析为独立语句和作为另一个表达式的一部分之间产生歧义;在这种情况下,它被解析为一个语句。 ExpressionWithBlock 表达式用作语句时的类型必须是单元类型。

match 是一个控制流表达式,你看到的是上面描述的歧义。因为它是作为语句编译的,所以它的类型应该是(),这就是你看到错误的原因。

【讨论】:

    猜你喜欢
    • 2015-03-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多