Rust中map/PLAT_map中变量的生存期
我认为我对生命周期有很好的理解,但我所读的内容与编译器在闭包方面所说的不符;) 我有一个带有签名的函数:Rust中map/PLAT_map中变量的生存期,rust,Rust,我认为我对生命周期有很好的理解,但我所读的内容与编译器在闭包方面所说的不符;) 我有一个带有签名的函数: fn split_to_words(content: &str) -> Vec<String> 并使用迭代器: let acc: Vec<String> = content.lines() .filter(|x| !x.is_empty()) .map(|x| x.to_lowercase()) .flat_map(
fn split_to_words(content: &str) -> Vec<String>
并使用迭代器:
let acc: Vec<String> = content.lines()
.filter(|x| !x.is_empty())
.map(|x| x.to_lowercase())
.flat_map(|x: String| x.split_whitespace())
.map(|x| x.to_string())
.collect();
查看整个错误消息很有帮助:
error: `x` does not live long enough
note: reference must be valid for the method call at ...
note: ...but borrowed value is only valid for the scope
of parameters for function at ...
调用flat\u map
时,将字符串的所有权传递给闭包。但是,闭包尝试返回一个迭代器,该迭代器包含对字符串的引用。由于每个字符串
都将在闭包调用结束后解除分配,因此对它的引用将无效,因此编译器阻止您执行此操作
我可能会将用于循环变量或类似版本:
fn split_to_words(content: &str) -> Vec<String> {
let lines = content.lines()
.filter(|x| !x.is_empty())
.map(|x| x.to_lowercase());
let mut result = Vec::new();
for line in lines {
for word in line.split_whitespace() {
result.push(word.to_string());
}
}
result
}
fn main() -> () {
println!("{:?}", split_to_words("hello world"));
}
fn拆分为单词(内容:&str)->Vec{
让lines=content.lines()
.filter(|x |!x.为_空()
.map(|x | x.to_lowercase());
让mut result=Vec::new();
排队{
用于第行中的单词。拆分_空格(){
result.push(word.to_string());
}
}
结果
}
fn main()->(){
println!(“{:?}”,拆分为单词(“你好世界”);
}
但在这种情况下,我认为你可以这样写:
fn split_to_words(content: &str) -> Vec<String> {
content.split_whitespace().map(str::to_lowercase).collect()
}
fn拆分为单词(内容:&str)->Vec{
content.split_whitespace().map(str::to_lowercase.collect())
}
换行符是空白,因此不需要使用行
。这也消除了空白值的可能性。查看整个错误消息会很有帮助:
error: `x` does not live long enough
note: reference must be valid for the method call at ...
note: ...but borrowed value is only valid for the scope
of parameters for function at ...
调用flat\u map
时,将字符串的所有权传递给闭包。但是,闭包尝试返回一个迭代器,该迭代器包含对字符串的引用。由于每个字符串
都将在闭包调用结束后解除分配,因此对它的引用将无效,因此编译器阻止您执行此操作
我可能会将用于循环变量或类似版本:
fn split_to_words(content: &str) -> Vec<String> {
let lines = content.lines()
.filter(|x| !x.is_empty())
.map(|x| x.to_lowercase());
let mut result = Vec::new();
for line in lines {
for word in line.split_whitespace() {
result.push(word.to_string());
}
}
result
}
fn main() -> () {
println!("{:?}", split_to_words("hello world"));
}
fn拆分为单词(内容:&str)->Vec{
让lines=content.lines()
.filter(|x |!x.为_空()
.map(|x | x.to_lowercase());
让mut result=Vec::new();
排队{
用于第行中的单词。拆分_空格(){
result.push(word.to_string());
}
}
结果
}
fn main()->(){
println!(“{:?}”,拆分为单词(“你好世界”);
}
但在这种情况下,我认为你可以这样写:
fn split_to_words(content: &str) -> Vec<String> {
content.split_whitespace().map(str::to_lowercase).collect()
}
fn拆分为单词(内容:&str)->Vec{
content.split_whitespace().map(str::to_lowercase.collect())
}
换行符是空白,因此不需要使用行
。这也消除了空白值的可能性。您的迭代器样式代码与命令式样式代码不完全相同:在命令式代码中,您在之前将空格拆分为小写,而在迭代器代码中,您的做法正好相反。事实证明,以前执行split_whitespace
更有效,因为split_whitespace
不需要分配字符串
;它只返回给定字符串片段中的片段。另一方面,to_lowercase
需要分配一个新字符串,因此通过最后一次分配,我们可以保存一个分配
let acc: Vec<String> = content.lines()
.filter(|x| !x.is_empty())
.flat_map(|x| x.split_whitespace())
.map(|x| x.to_lowercase())
.collect();
let acc:Vec=content.lines()
.filter(|x |!x.为_空()
.flat_映射(| x | x.split_空格())
.map(| x | x.to_小写()
.收集();
您的迭代器样式代码与命令式样式代码并不完全相同:在命令式代码中,您在之前将空格拆分为小写,而在迭代器代码中,您的做法正好相反。事实证明,以前执行split_whitespace
更有效,因为split_whitespace
不需要分配字符串
;它只返回给定字符串片段中的片段。另一方面,to_lowercase
需要分配一个新字符串,因此通过最后一次分配,我们可以保存一个分配
let acc: Vec<String> = content.lines()
.filter(|x| !x.is_empty())
.flat_map(|x| x.split_whitespace())
.map(|x| x.to_lowercase())
.collect();
let acc:Vec=content.lines()
.filter(|x |!x.为_空()
.flat_映射(| x | x.split_空格())
.map(| x | x.to_小写()
.收集();
我不知道str::to_lowercase
,它看起来类似于Java中的操作方式。谢谢!我在想,这样做会很好!我不知道str::to_lowercase
,它看起来类似于Java中的操作。谢谢!我在想,这样做会很好!