132

を返す関数がありますResult:

fn find(id: &Id) -> Result<Item, ItemError> {
    // ...
}

次に、次のように使用します。

let parent_items: Vec<Item> = parent_ids.iter()
    .map(|id| find(id).unwrap())
    .collect();

map反復内で失敗した場合、どのように処理すればよいですか?

私は使用できることを知ってflat_mapいます。この場合、エラー結果は無視されます:

let parent_items: Vec<Item> = parent_ids.iter()
    .flat_map(|id| find(id).into_iter())
    .collect();

Resultのイテレータには、成功状態に応じて 0 または 1 のアイテムがあり、0flat_mapの場合は除外されます。

ただし、エラーを無視したくはありません。代わりに、コード ブロック全体を停止して新しいエラーを返すようにしたい (マップ内で発生したエラーに基づいて、または単に既存のエラーを転送する)。

Rustでこれを最もよく処理するにはどうすればよいですか?

4

4 に答える 4

167

Result を実装FromIteratorしているため、外側を移動できResult、イテレータが残りの処理を行います (エラーが見つかった場合の反復の停止を含む)。

#[derive(Debug)]
struct Item;
type Id = String;

fn find(id: &Id) -> Result<Item, String> {
    Err(format!("Not found: {:?}", id))
}

fn main() {
    let s = |s: &str| s.to_string();
    let ids = vec![s("1"), s("2"), s("3")];

    let items: Result<Vec<_>, _> = ids.iter().map(find).collect();
    println!("Result: {:?}", items);
}

遊び場

于 2014-10-14T21:43:24.790 に答える
2

この回答は、Rust の 1.0 より前のバージョンに関連しており、必要な機能が削除されました

std::result::foldこれには関数を使用できます。最初の に遭遇した後、反復を停止しますErr

私が書いたプログラムの例:

fn main() {
  println!("{}", go([1, 2, 3]));
  println!("{}", go([1, -2, 3]));
}

fn go(v: &[int]) -> Result<Vec<int>, String> {
    std::result::fold(
        v.iter().map(|&n| is_positive(n)),
        vec![],
        |mut v, e| {
            v.push(e);
            v
        })
}

fn is_positive(n: int) -> Result<int, String> {
    if n > 0 {
        Ok(n)
    } else {
        Err(format!("{} is not positive!", n))
    }
}

出力:

Ok([1, 2, 3])
Err(-2 is not positive!)

デモ

于 2014-10-14T19:53:46.203 に答える