Get rid of unwrap in "for in" loop

I have the below code using the WinReg crate. I'm trying to get rid of all "unwrap"s. Not sure how to do this inside a closure. Appreciate any help to educate me on this and thanks.

// collect all values from a given reg key
fn get_reg_values(hive: &str, hkey: &RegKey, key: &str) -> std::io::Result<()> {
    let n = match hkey.open_subkey(key) {
        Ok(n) => n,
        _ => return Ok(()),
    };
    let lwt = get_reg_last_write_time(&n)?;
    for (name, value) in n.enum_values().map(|n| n.unwrap()) {
        print_value(hive, key, name, &value.bytes, format!("{:?}", value.vtype), &lwt)?;
    }
    Ok(())
}

You could move it out of the closure by doing something like this:

    for value_result in n.enum_values() {
        let (name, value) = value_result?;
        print_value(hive, key, name, &value.bytes, format!("{:?}", value.vtype), &lwt)?;
    }
1 Like

Ugh, that is obvious and never even occurred to me. Thanks so much.

In more complicated situations where you - for some reason - need a mapped iterator, you itertools::process_results can be super useful

use std::error::Error;
use std::convert::TryFrom;

fn baz(i: impl Iterator<Item = u8>) {}

fn foo() {
    let v = vec![1,2,3i32];
    let u8s = v.into_iter().map(|n| u8::try_from(n).unwrap());
    baz(u8s);
}
// transformed to use `?` instead of `unwrap()`
fn foo1() -> Result<(), Box<dyn Error>> {
    let v = vec![1,2,3i32];
    itertools::process_results(v.into_iter().map(|n| u8::try_from(n)), |u8s| {
        baz(u8s);
    })?;
    
    Ok(())
}

In cases where you end up using .collect(), note that an iterator with Result<T, E> items can be collected into a Result<CollectionOf<T>, E>.

And finally, since for some iterators for_each-style methods are more efficient than a for loop, note that try_for_each is a way propagating Result or Option error cases.