结果<T, E> 输入 Rust。为什么引用不能作为 T 或 E 传递?
Result<T, E> Type in Rust. why reference can't be passed as T or E?
我是 Rust 的新手,最近我读到了有关结果类型的内容。
喜欢这个概念并开始在我的应用程序中使用它。
我的第一次尝试是使用 &str。所以我的 return 类型看起来像这样:
pub fn calculate_risk_score(a: i32, b: i32) -> Result<i32, &str> {
return Ok(a + b);
}
这就是我遇到的错误:
以下代码有效:
pub fn calculate_risk_score(a: i32, b: i32) -> Result<i32, &'static str> {
return Ok(a + b);
}
现在我不认为我完全理解为什么将引用作为泛型传递是错误的。此外,我不明白为什么 static 解决了这个问题,我也不完全理解关于命名生命周期参数的解释。
我读了那些文章,但我想我仍然缺少一些东西。
https://doc.rust-lang.org/std/result/
https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html
所以我的问题:
- 为什么 &'static str 可以作为泛型类型传递而 &str 不能?
- 它和寿命有什么关系?为什么当我将它设置为 &str 时编译器无法确定引用的有效期?
1.为什么 'static
终生有效?
'static
生命周期有效,因为它意味着引用值在程序的整个生命周期内都存在。 Rust 中直接在源代码中编写的每个字符串的生命周期为 'static.
,例如let s = "hello world";
,因为它包含在已编译的二进制文件中,因此永远不会被删除。
2。为什么要明确生命周期以及如何解决?
编译器无法确定 returned 值存在多长时间,因为它期望明确的生命周期。一个简单的解决方法是 return 自有字符串(String
类型)而不是借用的字符串,或者只使用 &'static str
.
我建议您阅读 References and Borrowing and Validating References with Lifetimes 以更好地理解 Rust 中的生命周期是如何工作的。
要了解此函数签名的问题:
pub fn calculate_risk_score(a: i32, b: i32) -> Result<i32, &str> {
todo!()
}
...考虑一下 &str
是什么意思。这意味着:借用 某人字符串的一部分。如果允许这样的函数,可以这样调用它:
if let Err(e) = calculate_risk_score(foo, bar) {
// `e` is &str - who is it borrowed from, and how long is it valid?
// Can I put it in a container? Can I return it from this function?
// Can I put it in a global variable?
...
}
Lifetimes 通过将 returned 借用的生命周期与调用者提供的函数参数的生命周期联系起来,为这些问题提供了答案,因此必须知道其范围。这通常与 self
:
的范围一样简单
struct Parser {
last_error: String,
// ...
}
impl Parser {
// Equivalent to fn calculate_risk_scope<'a>(&'a self, a: i32, b: i32) -> Result<i32, &'a str>
fn calculate_risk_scope(&self, a: i32, b: i32) -> Result<i32, &str> {
if error {
return Err(self.last_error.as_str());
}
...
}
}
现在 &str
借用的生命周期与 &self
借用的生命周期相关联,即 returned 错误可以使用,只要对象被调用的方法有效且未修改。
对于原始函数,&str
是整个签名中唯一的引用,因此没有其他借用连接到它,编译器要求您提供明确的生命周期。它建议 'static
作为给定约束的合理选择,如果您使用的是被烘焙到可执行文件中且从未被释放的文字字符串,它确实有效。
请注意,编译器永远不会使用函数的 主体 来推断参数或 return 值的生命周期。这是有意的,并允许函数的签名构成不依赖于实现的 API 合约。当函数足够简单以至于它接收一个引用和 return 一个引用时,编译器将认为它们的生命周期是相连的,就好像它们被拼写为 fn calculate_risk_scope<'a>(&'a self, a: i32, b: i32) -> Result<i32, &'a str>
一样。这称为 lifetime elision 并且仅通过检查函数签名来工作,完全忽略其主体。 (主体当然必须符合签名中的生命周期。)
我是 Rust 的新手,最近我读到了有关结果类型的内容。 喜欢这个概念并开始在我的应用程序中使用它。
我的第一次尝试是使用 &str。所以我的 return 类型看起来像这样:
pub fn calculate_risk_score(a: i32, b: i32) -> Result<i32, &str> {
return Ok(a + b);
}
这就是我遇到的错误:
以下代码有效:
pub fn calculate_risk_score(a: i32, b: i32) -> Result<i32, &'static str> {
return Ok(a + b);
}
现在我不认为我完全理解为什么将引用作为泛型传递是错误的。此外,我不明白为什么 static 解决了这个问题,我也不完全理解关于命名生命周期参数的解释。 我读了那些文章,但我想我仍然缺少一些东西。
https://doc.rust-lang.org/std/result/
https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html
所以我的问题:
- 为什么 &'static str 可以作为泛型类型传递而 &str 不能?
- 它和寿命有什么关系?为什么当我将它设置为 &str 时编译器无法确定引用的有效期?
1.为什么 'static
终生有效?
'static
生命周期有效,因为它意味着引用值在程序的整个生命周期内都存在。 Rust 中直接在源代码中编写的每个字符串的生命周期为 'static.
,例如let s = "hello world";
,因为它包含在已编译的二进制文件中,因此永远不会被删除。
2。为什么要明确生命周期以及如何解决?
编译器无法确定 returned 值存在多长时间,因为它期望明确的生命周期。一个简单的解决方法是 return 自有字符串(String
类型)而不是借用的字符串,或者只使用 &'static str
.
我建议您阅读 References and Borrowing and Validating References with Lifetimes 以更好地理解 Rust 中的生命周期是如何工作的。
要了解此函数签名的问题:
pub fn calculate_risk_score(a: i32, b: i32) -> Result<i32, &str> {
todo!()
}
...考虑一下 &str
是什么意思。这意味着:借用 某人字符串的一部分。如果允许这样的函数,可以这样调用它:
if let Err(e) = calculate_risk_score(foo, bar) {
// `e` is &str - who is it borrowed from, and how long is it valid?
// Can I put it in a container? Can I return it from this function?
// Can I put it in a global variable?
...
}
Lifetimes 通过将 returned 借用的生命周期与调用者提供的函数参数的生命周期联系起来,为这些问题提供了答案,因此必须知道其范围。这通常与 self
:
struct Parser {
last_error: String,
// ...
}
impl Parser {
// Equivalent to fn calculate_risk_scope<'a>(&'a self, a: i32, b: i32) -> Result<i32, &'a str>
fn calculate_risk_scope(&self, a: i32, b: i32) -> Result<i32, &str> {
if error {
return Err(self.last_error.as_str());
}
...
}
}
现在 &str
借用的生命周期与 &self
借用的生命周期相关联,即 returned 错误可以使用,只要对象被调用的方法有效且未修改。
对于原始函数,&str
是整个签名中唯一的引用,因此没有其他借用连接到它,编译器要求您提供明确的生命周期。它建议 'static
作为给定约束的合理选择,如果您使用的是被烘焙到可执行文件中且从未被释放的文字字符串,它确实有效。
请注意,编译器永远不会使用函数的 主体 来推断参数或 return 值的生命周期。这是有意的,并允许函数的签名构成不依赖于实现的 API 合约。当函数足够简单以至于它接收一个引用和 return 一个引用时,编译器将认为它们的生命周期是相连的,就好像它们被拼写为 fn calculate_risk_scope<'a>(&'a self, a: i32, b: i32) -> Result<i32, &'a str>
一样。这称为 lifetime elision 并且仅通过检查函数签名来工作,完全忽略其主体。 (主体当然必须符合签名中的生命周期。)