2017-02-27 88 views
4

我正在使用future庫,我有一個未來實現Future<T, E>。我想用一個函數FnOnce(T) -> D來映射這個未來,其中D: From<E>。現在,當我希望wait()爲finsih這個未來,我會得到一個Result<Result<T, E>, D>,但我想要一個Result<T, D>等待結果映射未來

這裏是爲了更好地理解一些示例代碼:

struct ReadError; 

enum DownloadError { 
    Read(ReadError), 
    Parse(ParseError), 
} 

impl From<ReadError> for DownloadError { ... } 

fn parse(bytes: [u8; 4]) -> Result<i32, DownloadError> { ... } 

fn map_and_wait<F: Future<Item = [u8; 4]; Error = ReadError>>(f: F) -> Result<i32, DownloadError> { 
    match f.map(|x| parse(x)).wait() { 
     Ok(Ok(x)) => Ok(x), 
     Ok(Err(x)) => Err(x.into()), 
     Err(x) => Err(x), 
    } 
} 

什麼是這樣做的最簡單,最容易理解的方式(不match荷蘭國際集團)?

+0

這可能是比較容易回答,如果你提供一個完整的代碼示例,以及您想避免'match'ing。 –

+0

@PeterHall好的,我編輯了我的問題。 – torkleyy

回答

2

我發現了一個問題的答案:

您只需先wait未來去完成,使用?返回一個潛在的錯誤,然後將其應用於parse

parse(f.wait()?) 

這應該具有相同的語義,因爲在輪詢時,由map返回的Future執行其關閉。另一種解決方案是映射一個可能的錯誤,並使用and_then

f.map_error(|x| x.into()).and_then(|x| parse(x)).wait() 
+0

很高興你知道了。 '''真的收拾東西! –

+0

請注意,出於「期貨」的目的,組合通常應該優先於等待的明確調用,它可以擴展並保持異步性。 無論如何,後一行代碼可以更簡潔地寫爲'f.from_err()。and_then(parse).wait()'。 – dippi