使用任意变量返回错误枚举

时间:2016-04-11 15:33:47

标签: vector error-handling rust

我在Rust中使用try!创建了一个函数,它试图以递归方式收集目录中的所有文件并将它们插入到向量中。因为函数使用try!来检查错误,所以编译器似乎期望从函数返回io::Result,并且不允许我包含向量,因为try!宏仅返回结果。我需要返回矢量。

代码如下:

mod os{
    use std::io;
    use std::fs::{self, DirEntry};
    //use std::fs;
    use std::path::Path;
    // one possible implementation of walking a directory only visiting files
    pub fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> (io::Result<()>,Vec<String>) {
        let mut filevec: Vec<String> = Vec::new();
        if try!(fs::metadata(dir)).is_dir() {
            for entry in try!(fs::read_dir(dir)) {
                let entry = try!(entry);
                if try!(fs::metadata(entry.path())).is_dir() {
                    try!(visit_dirs(&entry.path(), cb));
                } else {
                    cb(&entry);
                }
            }
        }
        (Ok(()),filevec)

    }
fn push_path_to_vec(p:&DirEntry,v:Vec<String>){
    v.push(p.path().to_str().unwrap().to_string());
}}

这是错误:

<std macros>:5:8: 6:42 error: mismatched types:
 expected `(core::result::Result<(), std::io::error::Error>, collections::vec::Vec<collections::string::String>)`
    found `core::result::Result<_, _>`
(expected tuple,
    found enum `core::result::Result`) [E0308]

我想知道是否有任何惯用的方式来做到这一点,我已经错过了。

1 个答案:

答案 0 :(得分:2)

visit_dirs的返回类型错误。该函数应返回Result,但现在它返回一个元组。由于try!仅适用于返回Result的函数,因此您的代码无法编译。您可以更改visit_dirs的返回值以便修复它:

pub fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<Vec<String>>

新定义意味着Vec<String>成功后会存储在Result中。通过一些小的调整,编译器接受代码(见下文)

mod os{
    use std::io;
    use std::fs::{self, DirEntry};
    //use std::fs;
    use std::path::Path;
    // one possible implementation of walking a directory only visiting files
    pub fn visit_dirs(dir: &Path, cb: &Fn(&DirEntry)) -> io::Result<Vec<String>> {
        let mut filevec: Vec<String> = Vec::new();
        if try!(fs::metadata(dir)).is_dir() {
            for entry in try!(fs::read_dir(dir)) {
                let entry = try!(entry);
                if try!(fs::metadata(entry.path())).is_dir() {
                    try!(visit_dirs(&entry.path(), cb));
                } else {
                    cb(&entry);
                }
            }
        }
        Ok(filevec)
    }
fn push_path_to_vec(p:&DirEntry,mut v:Vec<String>){
    v.push(p.path().to_str().unwrap().to_string());
}}