我如何 return 一个由采用 &'a mut self 的函数生成的迭代器(当在本地创建 self 时)?
How do I return an Iterator that's generated by a function that takes &'a mut self (when self is created locally)?
更新:post的标题已更新,答案已移出问题。简短的回答是你不能。请看我对这个问题的回答。
我正在关注错误处理博客 post here (github for it is here),我尝试对代码进行一些修改,以便 search
函数 returns Iterator
而不是 Vec
。这非常困难,我被困住了。
我已经走到这一步了:
fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &str)
-> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>,
FnMut(Result<Row, csv::Error>)
-> Option<Result<PopulationCount, csv::Error>>>,
CliError> {
let mut found = vec![];
let input: Box<io::Read> = match *file_path {
None => Box::new(io::stdin()),
Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
};
let mut rdr = csv::Reader::from_reader(input);
let closure = |row: Result<Row, csv::Error>| -> Option<Result<PopulationCount, csv::Error>> {
let row = match row {
Ok(row) => row,
Err(err) => return Some(Err(From::from(err))),
};
match row.population {
None => None,
Some(count) => if row.city == city {
Some(Ok(PopulationCount {
city: row.city,
country: row.country,
count: count,
}))
} else {
None
}
}
};
let found = rdr.decode::<Row>().filter_map(closure);
if !found.all(|row| match row {
Ok(_) => true,
_ => false,
}) {
Err(CliError::NotFound)
} else {
Ok(found)
}
}
编译器出现以下错误:
src/main.rs:97:1: 133:2 error: the trait `core::marker::Sized` is not implemented for the type `core::ops::FnMut(core::result::Result<Row, csv::Error>) -> core::option::Option<core::result::Result<PopulationCount, csv::Error>>` [E0277]
src/main.rs:97 fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &str) -> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>, FnMut(Result<Row, csv::Error>) -> Option<Result<PopulationCount, csv::Error>>>, CliError> {
src/main.rs:98 let mut found = vec![];
src/main.rs:99 let input: Box<io::Read> = match *file_path {
src/main.rs:100 None => Box::new(io::stdin()),
src/main.rs:101 Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
src/main.rs:102 };
...
src/main.rs:97:1: 133:2 note: `core::ops::FnMut(core::result::Result<Row, csv::Error>) -> core::option::Option<core::result::Result<PopulationCount, csv::Error>>` does not have a constant size known at compile-time
src/main.rs:97 fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &str) -> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>, FnMut(Result<Row, csv::Error>) -> Option<Result<PopulationCount, csv::Error>>>, CliError> {
src/main.rs:98 let mut found = vec![];
src/main.rs:99 let input: Box<io::Read> = match *file_path {
src/main.rs:100 None => Box::new(io::stdin()),
src/main.rs:101 Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
src/main.rs:102 };
...
error: aborting due to previous error
我也试过这个函数定义:
fn search<'a, P: AsRef<Path>, F>(file_path: &Option<P>, city: &str)
-> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>, F>,
CliError>
where F: FnMut(Result<Row, csv::Error>)
-> Option<Result<PopulationCount, csv::Error>> {
编译器出现这些错误:
src/main.rs:131:12: 131:17 error: mismatched types:
expected `core::iter::FilterMap<csv::reader::DecodedRecords<'_, Box<std::io::Read>, Row>, F>`,
found `core::iter::FilterMap<csv::reader::DecodedRecords<'_, Box<std::io::Read>, Row>, [closure src/main.rs:105:19: 122:6]>`
(expected type parameter,
found closure) [E0308]
src/main.rs:131 Ok(found)
我不能 Box
闭包因为那样它不会被 filter_map
接受。
然后我试了一下:
fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &'a str)
-> Result<(Box<Iterator<Item=Result<PopulationCount, csv::Error>> + 'a>, csv::Reader<Box<io::Read>>), CliError> {
let input: Box<io::Read> = match *file_path {
None => box io::stdin(),
Some(ref file_path) => box try!(fs::File::open(file_path)),
};
let mut rdr = csv::Reader::from_reader(input);
let mut found = rdr.decode::<Row>().filter_map(move |row| {
let row = match row {
Ok(row) => row,
Err(err) => return Some(Err(err)),
};
match row.population {
None => None,
Some(count) if row.city == city => {
Some(Ok(PopulationCount {
city: row.city,
country: row.country,
count: count,
}))
},
_ => None,
}
});
if found.size_hint().0 == 0 {
Err(CliError::NotFound)
} else {
Ok((box found, rdr))
}
}
fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode())
.unwrap_or_else(|err| err.exit());
match search(&args.arg_data_path, &args.arg_city) {
Err(CliError::NotFound) if args.flag_quiet => process::exit(1),
Err(err) => fatal!("{}", err),
Ok((pops, rdr)) => for pop in pops {
match pop {
Err(err) => panic!(err),
Ok(pop) => println!("{}, {}: {} - {:?}", pop.city, pop.country, pop.count, rdr.byte_offset()),
}
}
}
}
这给了我这个错误:
src/main.rs:107:21: 107:24 error: `rdr` does not live long enough
src/main.rs:107 let mut found = rdr.decode::<Row>().filter_map(move |row| {
^~~
src/main.rs:100:117: 130:2 note: reference must be valid for the lifetime 'a as defined on the block at 100:116...
src/main.rs:100 -> Result<(Box<Iterator<Item=Result<PopulationCount, csv::Error>> + 'a>, csv::Reader<Box<io::Read>>), CliError> {
src/main.rs:101 let input: Box<io::Read> = match *file_path {
src/main.rs:102 None => box io::stdin(),
src/main.rs:103 Some(ref file_path) => box try!(fs::File::open(file_path)),
src/main.rs:104 };
src/main.rs:105
...
src/main.rs:106:51: 130:2 note: ...but borrowed value is only valid for the block suffix following statement 1 at 106:50
src/main.rs:106 let mut rdr = csv::Reader::from_reader(input);
src/main.rs:107 let mut found = rdr.decode::<Row>().filter_map(move |row| {
src/main.rs:108 let row = match row {
src/main.rs:109 Ok(row) => row,
src/main.rs:110 Err(err) => return Some(Err(err)),
src/main.rs:111 };
...
error: aborting due to previous error
是我设计有误,还是我采用了错误的方法?我错过了一些非常简单和愚蠢的东西吗?我不确定从这里到哪里去。
Return迭代器是可能的,但它有一些限制。
为了证明这是可能的,两个示例,(A) 使用显式迭代器类型和 (B) 使用装箱 (playpen link).
use std::iter::FilterMap;
fn is_even(elt: i32) -> Option<i32> {
if elt % 2 == 0 {
Some(elt)
} else { None }
}
/// (A)
pub fn evens<I: IntoIterator<Item=i32>>(iter: I)
-> FilterMap<I::IntoIter, fn(I::Item) -> Option<I::Item>>
{
iter.into_iter().filter_map(is_even)
}
/// (B)
pub fn cumulative_sums<'a, I>(iter: I) -> Box<Iterator<Item=i32> + 'a>
where I: IntoIterator<Item=i32>,
I::IntoIter: 'a,
{
Box::new(iter.into_iter().scan(0, |acc, x| {
*acc += x;
Some(*acc)
}))
}
fn main() {
// The output is:
// 0 is even, 10 is even,
// 1, 3, 6, 10,
for even in evens(vec![0, 3, 7, 10]) {
print!("{} is even, ", even);
}
println!("");
for cs in cumulative_sums(1..5) {
print!("{}, ", cs);
}
println!("");
}
您遇到了 (A) 问题 -- 显式类型!我们从具有 |a, b, c| ..
语法的常规 lambda 表达式中获得的未装箱闭包具有独特的匿名类型。函数需要明确的 return 类型,所以这在这里不起作用。
return闭包的一些解决方案:
- 使用函数指针
fn()
,如示例 (A) 所示。通常你不需要闭包环境。
- 封箱。这是合理的,即使迭代器目前不支持调用它。不是你的错。
- 将迭代器装箱
- Return 自定义迭代器结构。需要一些样板文件。
您可以在示例 (B) 中看到我们必须非常小心地处理生命周期。上面说return值为Box<Iterator<Item=i32> + 'a>
,这个'a
是什么?这是盒子内任何东西所需的最短寿命!我们还将 'a
绑定到 I::IntoIter
上——这确保我们可以将其放入框内。
如果你只说 Box<Iterator<Item=i32>>
它会假设 'static
.
我们必须明确声明我们盒子中内容物的生命周期。为了安全起见。
这其实是你函数的根本问题。你有这个:DecodedRecords<'a, Box<Read>, Row>, F>
看到了,'a
!这种类型借用了一些东西。问题是它没有从输入中借用它。输入上没有 'a
。
您会发现它借用了您在函数执行期间创建的值,并且该值的生命周期在函数 returns 时结束。 We cannot return DecodedRecords<'a>
from the function, because it wants to borrow a local variable.
从这里去哪里?我最简单的答案是执行与 csv 相同的拆分。一部分(结构或值)拥有 reader,另一部分(结构或值)是迭代器并从 reader.
借用
也许 csv crate 有一个拥有解码器的解码器,该解码器拥有它正在处理的 reader 的所有权。那样的话就可以用它来打消借钱的烦恼了。
此答案基于 @bluss's + #rust 在 irc.mozilla.org
上的帮助
代码中 不 的一个问题,导致上面显示的最终错误,与 csv::Reader::decode
的定义有关(请参阅其source). It takes &'a mut self
, the explanation of this problem is covered in this 。这实质上导致 reader 的生命周期被限制在调用它的块中。解决这个问题的方法是将函数分成两半(因为我无法控制函数定义,如前一个答案 link 中所建议的那样。我需要 reader 的生命周期在 main
函数中有效,因此 reader 可以传递到search
函数。请看下面的代码(它肯定可以被清理得更多):
fn population_count<'a, I>(iter: I, city: &'a str)
-> Box<Iterator<Item=Result<PopulationCount,csv::Error>> + 'a>
where I: IntoIterator<Item=Result<Row,csv::Error>>,
I::IntoIter: 'a,
{
Box::new(iter.into_iter().filter_map(move |row| {
let row = match row {
Ok(row) => row,
Err(err) => return Some(Err(err)),
};
match row.population {
None => None,
Some(count) if row.city == city => {
Some(Ok(PopulationCount {
city: row.city,
country: row.country,
count: count,
}))
},
_ => None,
}
}))
}
fn get_reader<P: AsRef<Path>>(file_path: &Option<P>)
-> Result<csv::Reader<Box<io::Read>>, CliError>
{
let input: Box<io::Read> = match *file_path {
None => Box::new(io::stdin()),
Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
};
Ok(csv::Reader::from_reader(input))
}
fn search<'a>(reader: &'a mut csv::Reader<Box<io::Read>>, city: &'a str)
-> Box<Iterator<Item=Result<PopulationCount, csv::Error>> + 'a>
{
population_count(reader.decode::<Row>(), city)
}
fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode())
.unwrap_or_else(|err| err.exit());
let reader = get_reader(&args.arg_data_path);
let mut reader = match reader {
Err(err) => fatal!("{}", err),
Ok(reader) => reader,
};
let populations = search(&mut reader, &args.arg_city);
let mut found = false;
for pop in populations {
found = true;
match pop {
Err(err) => fatal!("fatal !! {}", err),
Ok(pop) => println!("{}, {}: {}", pop.city, pop.country, pop.count),
}
}
if !(found || args.flag_quiet) {
fatal!("{}", CliError::NotFound);
}
}
我在尝试让它工作时学到了很多东西,并且对编译器错误有了更多的了解。现在很清楚,如果这是 C,上面的最后一个错误实际上可能导致段错误,这将更难调试。我还意识到,从预先计算的 vec 转换为迭代器需要更多地考虑内存何时进入和离开范围;我不能只更改一些函数调用和 return 类型就结束了。
更新:post的标题已更新,答案已移出问题。简短的回答是你不能。请看我对这个问题的回答。
我正在关注错误处理博客 post here (github for it is here),我尝试对代码进行一些修改,以便 search
函数 returns Iterator
而不是 Vec
。这非常困难,我被困住了。
我已经走到这一步了:
fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &str)
-> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>,
FnMut(Result<Row, csv::Error>)
-> Option<Result<PopulationCount, csv::Error>>>,
CliError> {
let mut found = vec![];
let input: Box<io::Read> = match *file_path {
None => Box::new(io::stdin()),
Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
};
let mut rdr = csv::Reader::from_reader(input);
let closure = |row: Result<Row, csv::Error>| -> Option<Result<PopulationCount, csv::Error>> {
let row = match row {
Ok(row) => row,
Err(err) => return Some(Err(From::from(err))),
};
match row.population {
None => None,
Some(count) => if row.city == city {
Some(Ok(PopulationCount {
city: row.city,
country: row.country,
count: count,
}))
} else {
None
}
}
};
let found = rdr.decode::<Row>().filter_map(closure);
if !found.all(|row| match row {
Ok(_) => true,
_ => false,
}) {
Err(CliError::NotFound)
} else {
Ok(found)
}
}
编译器出现以下错误:
src/main.rs:97:1: 133:2 error: the trait `core::marker::Sized` is not implemented for the type `core::ops::FnMut(core::result::Result<Row, csv::Error>) -> core::option::Option<core::result::Result<PopulationCount, csv::Error>>` [E0277]
src/main.rs:97 fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &str) -> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>, FnMut(Result<Row, csv::Error>) -> Option<Result<PopulationCount, csv::Error>>>, CliError> {
src/main.rs:98 let mut found = vec![];
src/main.rs:99 let input: Box<io::Read> = match *file_path {
src/main.rs:100 None => Box::new(io::stdin()),
src/main.rs:101 Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
src/main.rs:102 };
...
src/main.rs:97:1: 133:2 note: `core::ops::FnMut(core::result::Result<Row, csv::Error>) -> core::option::Option<core::result::Result<PopulationCount, csv::Error>>` does not have a constant size known at compile-time
src/main.rs:97 fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &str) -> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>, FnMut(Result<Row, csv::Error>) -> Option<Result<PopulationCount, csv::Error>>>, CliError> {
src/main.rs:98 let mut found = vec![];
src/main.rs:99 let input: Box<io::Read> = match *file_path {
src/main.rs:100 None => Box::new(io::stdin()),
src/main.rs:101 Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
src/main.rs:102 };
...
error: aborting due to previous error
我也试过这个函数定义:
fn search<'a, P: AsRef<Path>, F>(file_path: &Option<P>, city: &str)
-> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>, F>,
CliError>
where F: FnMut(Result<Row, csv::Error>)
-> Option<Result<PopulationCount, csv::Error>> {
编译器出现这些错误:
src/main.rs:131:12: 131:17 error: mismatched types:
expected `core::iter::FilterMap<csv::reader::DecodedRecords<'_, Box<std::io::Read>, Row>, F>`,
found `core::iter::FilterMap<csv::reader::DecodedRecords<'_, Box<std::io::Read>, Row>, [closure src/main.rs:105:19: 122:6]>`
(expected type parameter,
found closure) [E0308]
src/main.rs:131 Ok(found)
我不能 Box
闭包因为那样它不会被 filter_map
接受。
然后我试了一下:
fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &'a str)
-> Result<(Box<Iterator<Item=Result<PopulationCount, csv::Error>> + 'a>, csv::Reader<Box<io::Read>>), CliError> {
let input: Box<io::Read> = match *file_path {
None => box io::stdin(),
Some(ref file_path) => box try!(fs::File::open(file_path)),
};
let mut rdr = csv::Reader::from_reader(input);
let mut found = rdr.decode::<Row>().filter_map(move |row| {
let row = match row {
Ok(row) => row,
Err(err) => return Some(Err(err)),
};
match row.population {
None => None,
Some(count) if row.city == city => {
Some(Ok(PopulationCount {
city: row.city,
country: row.country,
count: count,
}))
},
_ => None,
}
});
if found.size_hint().0 == 0 {
Err(CliError::NotFound)
} else {
Ok((box found, rdr))
}
}
fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode())
.unwrap_or_else(|err| err.exit());
match search(&args.arg_data_path, &args.arg_city) {
Err(CliError::NotFound) if args.flag_quiet => process::exit(1),
Err(err) => fatal!("{}", err),
Ok((pops, rdr)) => for pop in pops {
match pop {
Err(err) => panic!(err),
Ok(pop) => println!("{}, {}: {} - {:?}", pop.city, pop.country, pop.count, rdr.byte_offset()),
}
}
}
}
这给了我这个错误:
src/main.rs:107:21: 107:24 error: `rdr` does not live long enough
src/main.rs:107 let mut found = rdr.decode::<Row>().filter_map(move |row| {
^~~
src/main.rs:100:117: 130:2 note: reference must be valid for the lifetime 'a as defined on the block at 100:116...
src/main.rs:100 -> Result<(Box<Iterator<Item=Result<PopulationCount, csv::Error>> + 'a>, csv::Reader<Box<io::Read>>), CliError> {
src/main.rs:101 let input: Box<io::Read> = match *file_path {
src/main.rs:102 None => box io::stdin(),
src/main.rs:103 Some(ref file_path) => box try!(fs::File::open(file_path)),
src/main.rs:104 };
src/main.rs:105
...
src/main.rs:106:51: 130:2 note: ...but borrowed value is only valid for the block suffix following statement 1 at 106:50
src/main.rs:106 let mut rdr = csv::Reader::from_reader(input);
src/main.rs:107 let mut found = rdr.decode::<Row>().filter_map(move |row| {
src/main.rs:108 let row = match row {
src/main.rs:109 Ok(row) => row,
src/main.rs:110 Err(err) => return Some(Err(err)),
src/main.rs:111 };
...
error: aborting due to previous error
是我设计有误,还是我采用了错误的方法?我错过了一些非常简单和愚蠢的东西吗?我不确定从这里到哪里去。
Return迭代器是可能的,但它有一些限制。
为了证明这是可能的,两个示例,(A) 使用显式迭代器类型和 (B) 使用装箱 (playpen link).
use std::iter::FilterMap;
fn is_even(elt: i32) -> Option<i32> {
if elt % 2 == 0 {
Some(elt)
} else { None }
}
/// (A)
pub fn evens<I: IntoIterator<Item=i32>>(iter: I)
-> FilterMap<I::IntoIter, fn(I::Item) -> Option<I::Item>>
{
iter.into_iter().filter_map(is_even)
}
/// (B)
pub fn cumulative_sums<'a, I>(iter: I) -> Box<Iterator<Item=i32> + 'a>
where I: IntoIterator<Item=i32>,
I::IntoIter: 'a,
{
Box::new(iter.into_iter().scan(0, |acc, x| {
*acc += x;
Some(*acc)
}))
}
fn main() {
// The output is:
// 0 is even, 10 is even,
// 1, 3, 6, 10,
for even in evens(vec![0, 3, 7, 10]) {
print!("{} is even, ", even);
}
println!("");
for cs in cumulative_sums(1..5) {
print!("{}, ", cs);
}
println!("");
}
您遇到了 (A) 问题 -- 显式类型!我们从具有 |a, b, c| ..
语法的常规 lambda 表达式中获得的未装箱闭包具有独特的匿名类型。函数需要明确的 return 类型,所以这在这里不起作用。
return闭包的一些解决方案:
- 使用函数指针
fn()
,如示例 (A) 所示。通常你不需要闭包环境。 - 封箱。这是合理的,即使迭代器目前不支持调用它。不是你的错。
- 将迭代器装箱
- Return 自定义迭代器结构。需要一些样板文件。
您可以在示例 (B) 中看到我们必须非常小心地处理生命周期。上面说return值为Box<Iterator<Item=i32> + 'a>
,这个'a
是什么?这是盒子内任何东西所需的最短寿命!我们还将 'a
绑定到 I::IntoIter
上——这确保我们可以将其放入框内。
如果你只说 Box<Iterator<Item=i32>>
它会假设 'static
.
我们必须明确声明我们盒子中内容物的生命周期。为了安全起见。
这其实是你函数的根本问题。你有这个:DecodedRecords<'a, Box<Read>, Row>, F>
看到了,'a
!这种类型借用了一些东西。问题是它没有从输入中借用它。输入上没有 'a
。
您会发现它借用了您在函数执行期间创建的值,并且该值的生命周期在函数 returns 时结束。 We cannot return DecodedRecords<'a>
from the function, because it wants to borrow a local variable.
从这里去哪里?我最简单的答案是执行与 csv 相同的拆分。一部分(结构或值)拥有 reader,另一部分(结构或值)是迭代器并从 reader.
借用也许 csv crate 有一个拥有解码器的解码器,该解码器拥有它正在处理的 reader 的所有权。那样的话就可以用它来打消借钱的烦恼了。
此答案基于 @bluss's
代码中 不 的一个问题,导致上面显示的最终错误,与 csv::Reader::decode
的定义有关(请参阅其source). It takes &'a mut self
, the explanation of this problem is covered in this main
函数中有效,因此 reader 可以传递到search
函数。请看下面的代码(它肯定可以被清理得更多):
fn population_count<'a, I>(iter: I, city: &'a str)
-> Box<Iterator<Item=Result<PopulationCount,csv::Error>> + 'a>
where I: IntoIterator<Item=Result<Row,csv::Error>>,
I::IntoIter: 'a,
{
Box::new(iter.into_iter().filter_map(move |row| {
let row = match row {
Ok(row) => row,
Err(err) => return Some(Err(err)),
};
match row.population {
None => None,
Some(count) if row.city == city => {
Some(Ok(PopulationCount {
city: row.city,
country: row.country,
count: count,
}))
},
_ => None,
}
}))
}
fn get_reader<P: AsRef<Path>>(file_path: &Option<P>)
-> Result<csv::Reader<Box<io::Read>>, CliError>
{
let input: Box<io::Read> = match *file_path {
None => Box::new(io::stdin()),
Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
};
Ok(csv::Reader::from_reader(input))
}
fn search<'a>(reader: &'a mut csv::Reader<Box<io::Read>>, city: &'a str)
-> Box<Iterator<Item=Result<PopulationCount, csv::Error>> + 'a>
{
population_count(reader.decode::<Row>(), city)
}
fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode())
.unwrap_or_else(|err| err.exit());
let reader = get_reader(&args.arg_data_path);
let mut reader = match reader {
Err(err) => fatal!("{}", err),
Ok(reader) => reader,
};
let populations = search(&mut reader, &args.arg_city);
let mut found = false;
for pop in populations {
found = true;
match pop {
Err(err) => fatal!("fatal !! {}", err),
Ok(pop) => println!("{}, {}: {}", pop.city, pop.country, pop.count),
}
}
if !(found || args.flag_quiet) {
fatal!("{}", CliError::NotFound);
}
}
我在尝试让它工作时学到了很多东西,并且对编译器错误有了更多的了解。现在很清楚,如果这是 C,上面的最后一个错误实际上可能导致段错误,这将更难调试。我还意识到,从预先计算的 vec 转换为迭代器需要更多地考虑内存何时进入和离开范围;我不能只更改一些函数调用和 return 类型就结束了。