我正在尝试使用
parquet
库在函数中创建一个记录迭代器对象,可以使用我自己的称为 RecordIterator
的特征进行迭代。看起来像这样:
fn blah(dataset_info: DatasetInfo, file: File) -> Result<Box<dyn RecordIterator<Item=Record>>, Box<dyn Error>> {
let reader = SerializedFileReader::new(file).unwrap();
let iter = (&reader).get_row_iter(None).unwrap();
let column_type = *dataset_info.column_type.clone();
let iterator = ParquetRecordIterator {
iterator: iter,
column_type: column_type,
i: 0,
};
Ok(Box::new(iterator))
}
问题是,因为 iter 的生命周期附加到它所创建的 SerializedFileReader 变量,所以返回 ParquetRecordIterator (实现 RecordIterator 特征)对象会抱怨一个错误:
cannot return value referencing local variable `reader` [E0515]
我理想情况下不想破坏这里的抽象,那么您建议如何实现这个功能?实际上,我想打破读取器和迭代器之间的生命周期链接,但不确定如何最好地做到这一点,或者使用不同的 parquet API 来做到这一点。
我尝试将文件读取器包装在
Box::new
中,希望生命周期不会与堆中的对象绑定,但不幸的是,这似乎不起作用。
我没有尝试过任何库来处理自引用结构,因为似乎不推荐它们,所以我希望有一种标准方法来解决这个问题。
我没有尝试过查看其他镶木地板库。
这是 Rust 中的一个难题,因为你本质上是在尝试创建一个 self-referential 结构。
幸运的是,您通常不需要解决这个问题,因为您使用的库提供了对此用例的直接支持:
impl IntoIterator for SerializedFileReader<File>
。所以:
fn blah(dataset_info: DatasetInfo, file: File) -> Result<Box<dyn RecordIterator<Item=Record>>, Box<dyn Error>> {
let reader = SerializedFileReader::new(file).unwrap();
let iter = reader.into_iter();
let column_type = *dataset_info.column_type.clone();
let iterator = ParquetRecordIterator {
iterator: iter,
column_type: column_type,
i: 0,
};
Ok(Box::new(iterator))
}