在多个闭包之一中捕获相同的变量

时间:2016-02-17 08:53:44

标签: closures rust

我有两个捕获相同Vec的闭包,我不知道如何在惯用的Rust中写这个:

use std::error;

fn get_token -> Box<Vec<u8>>() {...}
fn do_stuff(file: &str) -> std::io::Result<i32> {...}
fn do_other_stuff(a: &str, a: &str) -> std::io::Result<i32> {...}

enum MyError {
    IoError { token: Vec<u8>, reason: String ),
}

fn consumer() -> Result<MyError, ()> {
    let token = get_token();

    try!(do_stuff("a")
        .map_err(|e| MyError::IoError { token: token, reason: "foo".to_str() }));
    try!(do_other_stuff("b", "c")
        .map_err(|e| MyError::IoError { token: token, reason: "bar".to_str() }));
}

我可以使用map_err表达式替换match次调用,但我真的很难过:如何将Vec传递给多个闭包?

3 个答案:

答案 0 :(得分:3)

首先:请确保将来提供MCVE,在能够重现您的问题之前必须修复语法错误并不好:http://is.gd/tXr7WK

Rust不知道第二个闭包可以运行的唯一方法是第一个闭包没有运行并且永远不会运行。您可以等待let/else RFC被接受,实现和稳定,或者您可以按步骤创建错误,首先创建一个内部闭包,对该错误类型执行所有操作,而不会使用{{ 1}},然后运行闭包,然后将错误映射到自定义错误类型。

token

有一些奇怪的事情,闭包要求我们指定它返回|| -> _ { try!(do_stuff("a").map_err(|e| ("foo".to_owned(), e))); try!(do_other_stuff("b","c").map_err(|e| ("bar".to_owned(), e))); Ok(()) } ().map_err(|(reason, e)| MyError::IoError{ token: token, reason: reason }) 的东西,但我不确定它是什么。

答案 1 :(得分:3)

更直截了当的是不使用try!或闭包:

if let Err(e) = do_stuff("a") {
    return Err(MyError::IoError{token: token, reason: "foo".to_owned()});
}
if let Err(e) = do_other_stuff("b", "c") {
    return Err(MyError::IoError{token: token, reason: "bar".to_owned()});
}

这让Rust可以像你想要的那样进行简单的分析,并且比通过篮球跳舞更具可读性。

答案 2 :(得分:2)

您可以使用and_then()组合子来避免额外的关闭:

try!(do_stuff("a").map_err(|_| "foo" )
        .and_then(|_|
            do_other_stuff("b","c").map_err(|_| "bar")
        )
        .map_err(|e| MyError::IoError{token:token,reason:e.into()})
);