使用此示例代码:
use std::fs::{File};
use std::io::{BufRead, BufReader};
use std::path::Path;
type BoxIter<T> = Box<Iterator<Item=T>>;
fn tokens_from_str<'a>(text: &'a str)
-> Box<Iterator<Item=String> + 'a> {
Box::new(text.lines().flat_map(|s|
s.split_whitespace().map(|s| s.to_string())
))
}
// Returns an iterator of an iterator. The use case is a very large file where
// each line is very long. The outer iterator goes over the file's lines.
// The inner iterator returns the words of each line.
pub fn tokens_from_path<P>(path_arg: P)
-> BoxIter<BoxIter<String>>
where P: AsRef<Path> {
let reader = reader_from_path(path_arg);
let iter = reader.lines()
.filter_map(|result| result.ok())
.map(|s| tokens_from_str(&s));
Box::new(iter)
}
fn reader_from_path<P>(path_arg: P) -> BufReader<File>
where P: AsRef<Path> {
let path = path_arg.as_ref();
let file = File::open(path).unwrap();
BufReader::new(file)
}
我收到此编译器错误消息:
rustc 1.18.0 (03fc9d622 2017-06-06)
error: `s` does not live long enough
--> <anon>:23:35
|
23 | .map(|s| tokens_from_str(&s));
| ^- borrowed value only lives until here
| |
| does not live long enough
|
= note: borrowed value must be valid for the static lifetime...
我的问题是:
如何解决这个问题(如果可能,不改变函数签名?)
关于更好的函数参数和返回值有什么建议吗?
最佳答案
一个问题是 .split_whitespace()
获取引用,但不拥有其内容。因此,当您尝试使用拥有对象构建 SplitWhitespace
对象时(调用 .map(|s| tokens_from_str(&s))
时),字符串 s
被丢弃,而 SplitWhitespace
仍在尝试引用它。我通过创建一个结构来快速修复此问题,该结构获取 String
的所有权并根据需要生成 SplitWhitespace
。
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::iter::IntoIterator;
use std::str::SplitWhitespace;
pub struct SplitWhitespaceOwned(String);
impl<'a> IntoIterator for &'a SplitWhitespaceOwned {
type Item = &'a str;
type IntoIter = SplitWhitespace<'a>;
fn into_iter(self) -> Self::IntoIter {
self.0.split_whitespace()
}
}
// Returns an iterator of an iterator. The use case is a very large file where
// each line is very long. The outer iterator goes over the file's lines.
// The inner iterator returns the words of each line.
pub fn tokens_from_path<P>(path_arg: P) -> Box<Iterator<Item = SplitWhitespaceOwned>>
where P: AsRef<Path>
{
let reader = reader_from_path(path_arg);
let iter = reader
.lines()
.filter_map(|result| result.ok())
.map(|s| SplitWhitespaceOwned(s));
Box::new(iter)
}
fn reader_from_path<P>(path_arg: P) -> BufReader<File>
where P: AsRef<Path>
{
let path = path_arg.as_ref();
let file = File::open(path).unwrap();
BufReader::new(file)
}
fn main() {
let t = tokens_from_path("test.txt");
for line in t {
for word in &line {
println!("{}", word);
}
}
}
关于rust - 借用的值活得不够长(BufReader lines() 到 String 的迭代器),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44510445/