Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Expression 在“return”的末尾加上分号会有区别吗?_Expression_Rust_Statements - Fatal编程技术网

Expression 在“return”的末尾加上分号会有区别吗?

Expression 在“return”的末尾加上分号会有区别吗?,expression,rust,statements,Expression,Rust,Statements,缔约国指出: 分号将任何表达式转换为语句,方法是丢弃其值并返回单位 在我做了一个实验之前,我以为我已经了解了这个概念: fn print_number(x: i32, y: i32) -> i32 { if x + y > 20 { return x } x + y } 这很好。然后,我在返回行的末尾添加了一个分号(returnx;)。据我所知,这会将行转换为语句,返回单位数据类型() 尽管如此,最终结果是一样的。我不是100%肯定我说的话,但这有点道

缔约国指出:

分号将任何表达式转换为语句,方法是丢弃其值并返回单位

在我做了一个实验之前,我以为我已经了解了这个概念:

fn print_number(x: i32, y: i32) -> i32 {
    if x + y > 20 { return x }      
    x + y 
}
这很好。然后,我在返回行的末尾添加了一个分号(
returnx;
)。据我所知,这会将行转换为语句,返回单位数据类型
()


尽管如此,最终结果是一样的。

我不是100%肯定我说的话,但这有点道理

还有一个概念正在发挥作用:可达性分析。编译器知道
return
expression语句后面的内容是不可访问的。例如,如果我们编译此函数:

fn test() -> i32 {
    return 1;
    2
}
fn print_number(x: i32, y: i32) -> i32 {
    if x + y > 20 {
        return x;
        ()
    } else {
        x + y
    }
}
我们得到以下警告:

警告:无法访问表达式
-->src/main.rs:3:5
|
3 |     2
|     ^
|
编译器可以忽略<代码>的“真”分支,如果<<代码>表达式以“<代码>返回< /代码>表达式结束,在确定<代码>类型时,只考虑“false”分支,如果表达式。

您还可以在中看到此行为。发散函数是不正常返回的函数(例如,它们总是失败)。尝试将
返回
表达式替换为
失败宏(扩展为对发散函数的调用)。事实上,
return
表达式也被认为是发散的;这是上述可达性分析的基础

但是,如果在
return
语句之后有一个实际的
()
表达式,您将得到一个错误。此功能:

fn test() -> i32 {
    return 1;
    2
}
fn print_number(x: i32, y: i32) -> i32 {
    if x + y > 20 {
        return x;
        ()
    } else {
        x + y
    }
}
给出以下错误:

错误[E0308]:类型不匹配
-->src/main.rs:4:9
|
4 |         ()
|^^应为i32,找到()
|
=注意:应为'i32'类型`
找到类型“%1”()`

最后,当出现分歧表达式(包括
return
表达式)后接分号时,编译器对它们的处理似乎有所不同:语句仍在分歧。

通常情况下,
if
表达式中的每个分支都应具有相同的类型。如果某个分支的类型未指定,编译器将尝试查找单个公共类型:

fn print_number(x: int, y: int) {
  let v = if x + y > 20 {
    3 // this can be either 3u, 3i, 3u8 etc.
  } else {
    x + y // this is always int
  };
  println!("{}", v);
}
在此代码中,
3
未指定,但
else
分支强制其具有
int
类型

这听起来很简单:有一个函数可以将两个或多个类型“统一”到公共类型中,否则它会在不可能的情况下给您一个错误。但是如果有一个
失败怎么办在分支中

fn print_number(x: int, y: int) {
  let v = if x + y > 20 {
    fail!("x + y too large") // ???
  } else {
    x + y // this is always int
  };
  println!("{}", v); // uh wait, what's the type of `v`?
}
我希望
失败不会影响其他分支,毕竟这是一个例外情况。由于这种模式在锈蚀中非常常见,因此引入了分叉型的概念。不存在正在发散的类型的值。(它也被称为“无人居住类型”或“无效类型”,具体取决于上下文。不要与“单位类型”混淆,后者具有单个值
()
),因为发散类型自然是任何其他类型的子集,编译器得出结论认为
v
的类型只是
else
分支的类型,
int

返回
表达式与
失败没有区别用于类型检查。它突然从当前的执行流中逃脱,就像
fail(谢天谢地,它不会终止任务)。但是,发散类型不会传播到下一个语句:

fn print_number(x: int, y: int) {
  let v = if x + y > 20 {
    return; // this is diverging
    () // this is implied, even when you omit it
  } else {
    x + y // this is always int
  };
  println!("{}", v); // again, what's the type of `v`?
}
注意,唯一的分号语句
x
相当于表达式
x;()
。通常
a;b
的类型与
b
相同,因此
x;()
只有在
x
不发散时才具有
()
类型,并且在
x
发散时才发散。这就是为什么你原来的代码不起作用

添加这样的特殊情况很有诱惑力:

  • 你为什么不把
    x;()
    x
    发散时发散
  • 当无法推断其类型时,为什么不为每个未指定的整数文本假定
    uint
    ?(注:这是过去的情况。)
  • 在统一多个特征对象时,为什么不自动找到公共超特征

事实是,设计类型系统并不困难,但验证它要困难得多,我们希望确保Rust的类型系统是经得起未来考验且长期存在的。如果它确实有用并且被证明对我们的目的是“正确的”,那么其中一些可能会发生,但不会立即发生。

如何不同?没有分号会有什么区别?没有分号,
return
表达式和发散表达式似乎与任何表达式都是类型兼容的,而且即使后跟分号,它们似乎也保留了这一特殊特性。这正是他们在IRC频道告诉我的。基本上,它对最终结果没有影响(至少在我的例子中是这样),但添加分号可以让人安心:)我觉得我更了解
如何返回
失败,并且发散函数工作。无论在
return x
中是否存在分号,我的代码示例都会编译。所以我想底线是:添加它不会有什么不同吗?我编辑了我的代码示例来进一步澄清我的问题。但是,
返回x
返回x最后似乎做了同样的事情,我不知道在这种情况下使用分号有什么区别。我的编辑是否会更改您问题的上下文?(仍在试图理解那些关于生锈的低级概念)。@sargas:你的编辑完全改变了这种情况。之前,函数的尾部是一个
if
表达式;现在,函数的尾部是
x+y
expre