将Map作为迭代器与Vector迭代器互换使用

  • 本文关键字:迭代器 互换 Vector Map rust
  • 更新时间 :
  • 英文 :


一个简单的程序,我要做的是从文件中获取行,或者如果文件不存在,则传入一个零长度迭代器:

use std::fs::File;
use std::io::{self, BufRead};
fn run_against_input(inp: &mut dyn Iterator<Item = String>) {
for i in inp {
println!("Input line: {}", i);
}
}
fn main() {
let file = File::open("data.txt");
let input: dyn Iterator<Item = String> = match file {
Ok(f) => io::BufReader::new(f).lines()
.map(|line| line.unwrap()),
Err(_) => Vec::new().into_iter()
};

run_against_input(&mut dyn input);
}

当我这样做时,我会得到以下错误:

Compiling playground v0.0.1 (/playground)
error: expected expression, found keyword `dyn`
--> src/main.rs:19:28
|
19 |     run_against_input(&mut dyn input);
|                            ^^^ expected expression
error[E0308]: mismatched types
--> src/main.rs:13:18
|
13 |           Ok(f) => io::BufReader::new(f).lines()
|  __________________^
14 | |             .map(|line| line.unwrap()),
| |______________________________________^ expected trait object `dyn Iterator`, found struct `Map`
|
= note: expected trait object `dyn Iterator<Item = String>`
found struct `Map<std::io::Lines<BufReader<File>>, [closure@src/main.rs:14:18: 14:38]>`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to 2 previous errors

我确实特别需要&mut引用我正在编写的代码中的Iterator(这是我面临的问题的一个小复制(,但我想这与手头的问题无关。我看到MapIterator上有一个impl,但我得到的错误是这不是Iterator<Item = String>的trait对象。我也试过这个:

let input: &mut dyn Iterator<Item = String> = match file {
Ok(f) => &mut io::BufReader::new(f).lines()
.map(|line| line.unwrap()),
Err(_) => &mut Vec::new().into_iter()
};

这当然不起作用,因为在我返回引用的语句中删除了临时值(这就是为什么我按照编译器的建议做了let绑定的事情(。

编辑链接到操场-https://play.rust-lang.org/?version=stable&mode=调试&edition=2021&gist=99b8105cc266e03db2d92cc22610962

您可以将每个分支的迭代器保存在match之外的一个单独变量中(也可以使用std::iter::empty()而不是Vec::new().into_iter()(:

use std::fs::File;
use std::io::{self, BufRead};
use std::iter;
fn run_against_input(inp: impl Iterator<Item = String>) {
for i in inp {
println!("Input line: {}", i);
}
}
fn main() {
let file = File::open("data.txt");
let mut lines;
let mut no_lines;
let input: &mut dyn Iterator<Item = String> = match file {
Ok(f) => {
lines = io::BufReader::new(f).lines().map(Result::unwrap);
&mut lines
},
Err(_) => {
no_lines = iter::empty();
&mut no_lines
},
};

run_against_input(input);
}

您可以使用Box而不是引用,因此该值是拥有的,不会被丢弃:

let mut input: Box<dyn Iterator<Item = String>> = match file {
Ok(f) => Box::new(io::BufReader::new(f).lines().map(|line| line.unwrap())),
Err(_) => Box::new(Vec::new().into_iter()),
};

操场

如果你喜欢,你也可以改变你的功能,用一个盒子代替一个参考:

fn run_against_input(inp: Box<dyn Iterator<Item = String>>) {

最新更新