generics - 如何结合 std::str::lines 和 std::io::lines?

标签 generics iterator rust traits

我想写一个函数来解析文本,但文本可能来自外部文件或内部&strparse 函数可能是这样的:

fn parse(lines: GenericLinesGenerator) {
   for line in lines {
       // parse content
   }
}

...它可以像这样被调用:

use std::io::BufReader;
use std::fs::File;
let fin = BufReader::new(File::open("info.txt").expect("not found"));
parse(TransformFromIO(fin.lines()))

let content: &'static str = "some\nlong\ntext";
parse(TransformFromStr(content.lines()))

是否可以实现这样的parse功能?

最佳答案

两个迭代器不产生相同的值:

impl<B: BufRead> Iterator for io::Lines<B> {
    type Item = Result<String>;
}
impl<'a> Iterator for str::Lines<'a> {
    type Item = &'a str;
}

您必须以某种方式处理这种差异。最重要的区别是 io::Lines 可以失败。您的程序必须决定如何处理它;我选择了中止程序。

接下来您需要做的是接受任何可以转换为迭代器的类型,并且迭代器产生的值必须转换为您可以处理的类型。 &str 似乎是共同点。

这可以通过使用 IntoIterator 来解决和 Borrow :

use std::borrow::Borrow;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;

fn parse<I>(lines: I)
where
    I: IntoIterator,
    I::Item: Borrow<str>,
{
    for line in lines {
        println!("line: {}", line.borrow());
    }
}

fn main() {
    parse("alpha\nbeta\ngamma".lines());

    println!("----");

    let f = File::open("/etc/hosts").expect("Couldn't open");
    let b = BufReader::new(f);
    parse(b.lines().map(|l| l.expect("Bad line!")));
}

检查 The Rust Programming Language关于 where clauses 的部分有关特质界限的更多信息。

关于generics - 如何结合 std::str::lines 和 std::io::lines?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37028476/

相关文章:

c# - 通过遗传继承的静态成员可访问性

c# - Ninject - 管理泛型类型的不一致性?

java - 调用不带参数的泛型函数

c# - 是否有可用于 + 运算符的通用约束?

git - 无法将文件夹 www 添加到 github 存储库

error-handling - 使用 xml-rs xml::reader::Error 返回自定义错误

javascript - Ramda.map over Immutable.List 如何返回列表而不是数组?

C++11:基于范围的 for 循环遍历由模板化迭代器描述的范围

c++ - 'auto *const' 具有 std::_Array_iterator<char, 48> 类型的不兼容初始值设定项

rust - 我如何安全地使用可变借用的对象?