swi*_*end 2 iterator clone vector ownership rust
我有一个我不太了解的所有权问题.基本上我尝试在我的文件系统上创建一些硬链接,并在创建后删除它们.因此,我创建了一系列整数,我将其映射到我想要创建和销毁的实际文件名.我天真的解决方案看起来像这样:
use std::fs;
const src_file: &'static str = "a.txt";
const file_ext: &'static str = ".txt";
fn create_hardlink(dest_file: &str) {
fs::hard_link(&src_file, &dest_file);
}
fn main() {
let create = (0..10000).map(|x| x.to_string() + file_ext);
let remove = (0..10000).map(|x| x.to_string() + file_ext);
for file in create {
create_hardlink(&file);
}
for file in remove {
fs::remove_file(&file);
}
}
Run Code Online (Sandbox Code Playgroud)
但我真正想要实现的是一个解决方案,我不必重复自己来创建带有文件名的静态集合,并且可以重用files第二个for循环:
...
fn main() {
let files = (0..10000).map(|x| x.to_string() + file_ext);
for file in files {
create_hardlink(&file);
}
for file in files {
fs::remove_file(&file);
}
}
Run Code Online (Sandbox Code Playgroud)
所以当我尝试这个时,编译器会抱怨,第二次使用files是不可能的,
src/main.rs:20:17: 20:22 error: use of moved value: `files` [E0382]
src/main.rs:20 for file in files {
Run Code Online (Sandbox Code Playgroud)
因为files已经进入了第一个for循环:
src/main.rs:16:17: 16:22 note: `files` moved here because it has type `core::iter::Map<core::ops::Range<i32>, [closure@src/main.rs:14:36: 14:64]>`, which is non-copyable
Run Code Online (Sandbox Code Playgroud)
在阅读完解释后,rustc --explain E0382我决定更改代码如下:
...
fn main() {
let files = Rc::new(RefCell::new((0..10000).map(|x| x.to_string() + file_ext)));
for file in files.clone() {
create_hardlink(&file);
}
for file in files.clone() {
fs::remove_file(&file);
}
}
Run Code Online (Sandbox Code Playgroud)
但这不符合我的预期:
src/main.rs:16:5: 18:6 error: the trait `core::iter::Iterator` is not implemented for the type `alloc::rc::Rc<core::cell::RefCell<core::iter::Map<core::ops::Range<_>, [closure@src/main.rs:14:53: 14:81]>>>` [E0277]
src/main.rs:16 for file in files.clone() {
src/main.rs:17 create_hardlink(&file);
src/main.rs:18 }
note: in expansion of for loop expansion
src/main.rs:16:5: 18:6 note: expansion site
src/main.rs:16:5: 18:6 help: run `rustc --explain E0277` to see a detailed explanation
src/main.rs:16:5: 18:6 note: `alloc::rc::Rc<core::cell::RefCell<core::iter::Map<core::ops::Range<_>, [closure@src/main.rs:14:53: 14:81]>>>` is not an iterator; maybe try calling `.iter()` or a similar method
src/main.rs:16 for file in files.clone() {
src/main.rs:17 create_hardlink(&file);
src/main.rs:18 }
note: in expansion of for loop expansion
src/main.rs:16:5: 18:6 note: expansion site
src/main.rs:16:5: 18:6 note: required by `core::iter::IntoIterator::into_iter`
src/main.rs:16 for file in files.clone() {
src/main.rs:17 create_hardlink(&file);
src/main.rs:18 }
Run Code Online (Sandbox Code Playgroud)
我能做什么?我是否真的必须实现类似告诉我core::iter::Iterator的类型?我希望不是...alloc::rc::Rc<core::cell::RefCell<core::iter::Map<core::ops::Range<_>rustc --explain E0277
是否有一个简单的解决方案,如files静态定义static为const?或者我的方法是映射Range非生锈?
为什么我有类似的类型<core::iter::Map<core::ops::Range<_>而不是类似的类型<core::iter::String>?
我希望你能帮助我解决这个问题,并向我这样的新手启发Rust所有权原则.
据我所知,Rust迭代器只是前向迭代器,所以它们只能迭代一次.您可以将collect它们放入向量中或使用函数生成迭代器:
// 1st option
let files: Vec<_> = (0..10000).map(|x| x.to_string() + file_ext).collect();
for f in &files { ... } // Borrow `files`
// 2nd option
let files = || (0..10000).map(|x| x.to_string() + file_ext);
for f in files() { ... } // Call the closure to get an iterator
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
458 次 |
| 最近记录: |