如何 return 借用状态以备后用的 Rust 闭包?
How to return a Rust closure that borrows state to use later?
我有一段相当简单的代码。我有一种感觉,我需要用一辈子的时间来完成这个,但我现在很困惑。
parse_string
是一个接受字符串引用的函数,returns是后面要用到的闭包,代码如下:
fn main() {
let parse_this = parse_string(&String::from("Hello!"));
println!("{}", parse_this("goodbye!"));
}
fn parse_string(string: &String) -> impl Fn(&str) -> &String {
return |targetString| {
// pretend there is parsing logic
println!("{}", targetString);
return string;
};
}
编译器错误:
error: cannot infer an appropriate lifetime
--> src/main.rs:7:12
|
6 | fn parse_string(string: &String) -> impl Fn(&str) -> &String {
| ------------------------ this return type evaluates to the `'static` lifetime...
7 | return |targetString| {
| ____________^
8 | | // pretend there is parsing logic
9 | | println!("{}", targetString);
10 | | return string;
11 | | };
| |_____^ ...but this borrow...
|
note: ...can't outlive the anonymous lifetime #1 defined on the function body at 6:1
--> src/main.rs:6:1
|
6 | / fn parse_string(string: &String) -> impl Fn(&str) -> &String {
7 | | return |targetString| {
8 | | // pretend there is parsing logic
9 | | println!("{}", targetString);
10 | | return string;
11 | | };
12 | | }
| |_^
help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 6:1
|
6 | fn parse_string(string: &String) -> impl Fn(&str) -> &String + '_ {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/main.rs:10:16
|
10 | return string;
| ^^^^^^
|
note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 7:12...
--> src/main.rs:7:12
|
7 | return |targetString| {
| ____________^
8 | | // pretend there is parsing logic
9 | | println!("{}", targetString);
10 | | return string;
11 | | };
| |_____^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 6:1
--> src/main.rs:6:1
|
6 | / fn parse_string(string: &String) -> impl Fn(&str) -> &String {
7 | | return |targetString| {
8 | | // pretend there is parsing logic
9 | | println!("{}", targetString);
10 | | return string;
11 | | };
12 | | }
| |_^
您有许多复合问题:
您需要一个明确的生命周期来将 string
参数的生命周期连接到 returned 闭包的 return 值的生命周期。现在,lifetime elision 导致它被推断为与闭包的 参数 相同。
您不能 return 通过函数引用临时对象。它需要是一个不同的变量。
您必须将 string
移动到闭包中以防止再次引用它,这不会足够长。
此外...
targetString
应该是 target_string
以遵循 Rust 习语。
return
不应在块的末尾使用以遵循 Rust 习语。
&str
通常优于 &String
fn main() {
let s = String::from("Hello!");
let parse_this = parse_string(&s);
println!("{}", parse_this("goodbye!"));
}
fn parse_string<'a>(string: &'a String) -> impl Fn(&str) -> &'a String {
return move |target_string| {
// pretend there is parsing logic
println!("{}", target_string);
string
};
}
另请参阅:
您需要向 parse_string
添加显式生命周期注释,以便编译器可以判断哪些生命周期相同,哪些可能不同。
Fn(&str) -> &String
将是 returns 与传入的 &str
生命周期相同的 &String
函数的类型;即 for<'b> Fn(&'b str) -> &'b String
。您需要说明返回的 &String
与传入 parse_string
的 &String
具有相同的生命周期:
fn parse_string<'a>(string: &'a String) -> impl Fn(&str) -> &'a String {
请注意 Fn(&str)
没有生命周期注释;这是因为传递给 闭包 的 &str
的生命周期与传递给 parse_string
.[=40= 的 &String
的生命周期无关]
为了parse_string
编译,您需要再做一处改动。如果编译器认为不需要移动闭包,则闭包会尝试借用它们的环境。借用 string
的闭包不能从 string
是局部变量的函数返回。要解决此问题,您 move
将捕获的变量放入闭包中:
move |target_string| {
// pretend there is parsing logic
println!("{}", target_string);
string
}
在函数的最后一个表达式中省略 return
在 Rust 中是惯用的。
另请注意,&String
是一种不常见的类型,因为它不提供 &str
不提供的表现力。在非通用代码中使用 &String
几乎总是错误的。有关详细信息,请参阅 。
综合起来,我会这样写 parse_string
:
fn parse_string<'a>(string: &'a str) -> impl Fn(&str) -> &'a str {
move |target_string| {
// pretend there is parsing logic
println!("{}", target_string);
string
}
}
你的 main
也需要一个小的调整:&String::from("Hello!")
引用了一个临时的 String
,它将在行尾立即删除,使引用无效。这很容易通过将 String
存储在一个变量中来解决,这样它就不会被删除,直到范围结束:
fn main() {
let hello = String::from("Hello!");
let parse_this = parse_string(&hello);
println!("{}", parse_this("goodbye!"));
}
我有一段相当简单的代码。我有一种感觉,我需要用一辈子的时间来完成这个,但我现在很困惑。
parse_string
是一个接受字符串引用的函数,returns是后面要用到的闭包,代码如下:
fn main() {
let parse_this = parse_string(&String::from("Hello!"));
println!("{}", parse_this("goodbye!"));
}
fn parse_string(string: &String) -> impl Fn(&str) -> &String {
return |targetString| {
// pretend there is parsing logic
println!("{}", targetString);
return string;
};
}
编译器错误:
error: cannot infer an appropriate lifetime
--> src/main.rs:7:12
|
6 | fn parse_string(string: &String) -> impl Fn(&str) -> &String {
| ------------------------ this return type evaluates to the `'static` lifetime...
7 | return |targetString| {
| ____________^
8 | | // pretend there is parsing logic
9 | | println!("{}", targetString);
10 | | return string;
11 | | };
| |_____^ ...but this borrow...
|
note: ...can't outlive the anonymous lifetime #1 defined on the function body at 6:1
--> src/main.rs:6:1
|
6 | / fn parse_string(string: &String) -> impl Fn(&str) -> &String {
7 | | return |targetString| {
8 | | // pretend there is parsing logic
9 | | println!("{}", targetString);
10 | | return string;
11 | | };
12 | | }
| |_^
help: you can add a constraint to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 6:1
|
6 | fn parse_string(string: &String) -> impl Fn(&str) -> &String + '_ {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0312]: lifetime of reference outlives lifetime of borrowed content...
--> src/main.rs:10:16
|
10 | return string;
| ^^^^^^
|
note: ...the reference is valid for the anonymous lifetime #2 defined on the body at 7:12...
--> src/main.rs:7:12
|
7 | return |targetString| {
| ____________^
8 | | // pretend there is parsing logic
9 | | println!("{}", targetString);
10 | | return string;
11 | | };
| |_____^
note: ...but the borrowed content is only valid for the anonymous lifetime #1 defined on the function body at 6:1
--> src/main.rs:6:1
|
6 | / fn parse_string(string: &String) -> impl Fn(&str) -> &String {
7 | | return |targetString| {
8 | | // pretend there is parsing logic
9 | | println!("{}", targetString);
10 | | return string;
11 | | };
12 | | }
| |_^
您有许多复合问题:
您需要一个明确的生命周期来将
string
参数的生命周期连接到 returned 闭包的 return 值的生命周期。现在,lifetime elision 导致它被推断为与闭包的 参数 相同。您不能 return 通过函数引用临时对象。它需要是一个不同的变量。
您必须将
string
移动到闭包中以防止再次引用它,这不会足够长。
此外...
targetString
应该是target_string
以遵循 Rust 习语。return
不应在块的末尾使用以遵循 Rust 习语。&str
通常优于&String
fn main() {
let s = String::from("Hello!");
let parse_this = parse_string(&s);
println!("{}", parse_this("goodbye!"));
}
fn parse_string<'a>(string: &'a String) -> impl Fn(&str) -> &'a String {
return move |target_string| {
// pretend there is parsing logic
println!("{}", target_string);
string
};
}
另请参阅:
您需要向 parse_string
添加显式生命周期注释,以便编译器可以判断哪些生命周期相同,哪些可能不同。
Fn(&str) -> &String
将是 returns 与传入的 &str
生命周期相同的 &String
函数的类型;即 for<'b> Fn(&'b str) -> &'b String
。您需要说明返回的 &String
与传入 parse_string
的 &String
具有相同的生命周期:
fn parse_string<'a>(string: &'a String) -> impl Fn(&str) -> &'a String {
请注意 Fn(&str)
没有生命周期注释;这是因为传递给 闭包 的 &str
的生命周期与传递给 parse_string
.[=40= 的 &String
的生命周期无关]
为了parse_string
编译,您需要再做一处改动。如果编译器认为不需要移动闭包,则闭包会尝试借用它们的环境。借用 string
的闭包不能从 string
是局部变量的函数返回。要解决此问题,您 move
将捕获的变量放入闭包中:
move |target_string| {
// pretend there is parsing logic
println!("{}", target_string);
string
}
在函数的最后一个表达式中省略 return
在 Rust 中是惯用的。
另请注意,&String
是一种不常见的类型,因为它不提供 &str
不提供的表现力。在非通用代码中使用 &String
几乎总是错误的。有关详细信息,请参阅
综合起来,我会这样写 parse_string
:
fn parse_string<'a>(string: &'a str) -> impl Fn(&str) -> &'a str {
move |target_string| {
// pretend there is parsing logic
println!("{}", target_string);
string
}
}
你的 main
也需要一个小的调整:&String::from("Hello!")
引用了一个临时的 String
,它将在行尾立即删除,使引用无效。这很容易通过将 String
存储在一个变量中来解决,这样它就不会被删除,直到范围结束:
fn main() {
let hello = String::from("Hello!");
let parse_this = parse_string(&hello);
println!("{}", parse_this("goodbye!"));
}