我正在开发我的第一个 Rust 应用程序,并且遇到了与借用值相关的问题。我的应用程序涉及使用多个返回
Result<DataFrame, ParseError>
的函数来解析不同类型的文本文件。 DataFrame 来自 Polars 库,ParseError 是我的自定义错误类型。
我有多个具有以下签名的文件解析函数:
fn parse_file<P: AsRef<Path>>(file_path: P) -> Result<DataFrame, ParseError>
这允许我传递字符串切片或对 std::path::Path 的引用。
有时,我会单独调用这些文件解析函数。其他时候,我想解析目录中的所有文件,所以我需要一个可以解析整个目录的函数。为此,我打算将文件解析函数作为参数传递。
这是我当前的实现:
type ParseFunction<P> = fn(P) -> Result<DataFrame, ParseError>;
fn parse_folder<P: AsRef<Path>>(
dir: P,
parse_function: ParseFunction<&Path>,
) -> Result<HashMap<String, DataFrame>, ParseError> {
let mut map: HashMap<String, DataFrame> = HashMap::new();
for entry in fs::read_dir(dir).map_err(|_| ParseError::ReadFolderError)? {
let file = entry.map_err(|_| ParseError::ReadFolderError)?;
let filename = file.file_name().to_string_lossy().into_owned();
let path = file.path().clone();
if filename.ends_with(".art") {
map.insert(
filename,
parse_function(&path)?,
);
} //parse_function should be done with path here
} //path is dropped here. Why is that not ok?
Ok(map)
}
这会产生错误:错误[E0597]:
path
寿命不够长
为什么 Rust 在这种情况下会给我错误“路径生存时间不够长”,以及编写 parse_folder 函数来处理这个借用问题的正确方法是什么?
我主要想了解借贷问题。我尝试了很多不同的事情。法学硕士不断自信地提出不起作用的建议。
这是我想如何使用 parse_folder 函数的示例:
pub fn parse_art_file<P: AsRef<Path>>(
file_path: P,
) -> Result<DataFrame, ParseError> {
match read_and_decode_lines(&file_path) {
// Attempt to read article parameters from the decoded lines
Ok(lines) => read_article_parameters(lines),
// Return an error if the file could not be read and decoded
Err(_) => Err(ParseError::InvalidFile(file_path.as_ref().to_string_lossy().into_owned())),
}
}
pub fn parse_art_folder<P: AsRef<Path>> (dir: P) -> Result<HashMap<String, DataFrame>, ParseError> {
parse_folder(dir, parse_art_file)
}
在
parse_folder
中,path
的类型是 PathBuf
(具有 impl AsRef<Path>
)。您可以直接传递 &path
,而不是将 parse_function
传递给 path
:
fn parse_folder<P: AsRef<Path>>(
dir: P,
parse_function: fn(file_path: PathBuf) -> Result<DataFrame, ParseError>,
) -> Result<HashMap<String, DataFrame>, ParseError> {
let mut map: HashMap<String, DataFrame> = HashMap::new();
for entry in fs::read_dir(dir).map_err(|_| ParseError::ReadFolderError)? {
let file = entry.map_err(|_| ParseError::ReadFolderError)?;
let filename_os = file.file_name();
let filename = filename_os.to_string_lossy();
if filename.ends_with(".art") {
map.insert(filename.to_string(), parse_function(file.path())?);
}
}
Ok(map)
}
我还将调用
to_owned/to_string
的地方也移到了if语句中。