`while let Ok(t) ... = try_read!(...)` to make neater reading loop

Viewed 126

Is it possible to make short, neat loop that will call , as long as result is Ok(x) and act on x ?

E.g. sth like :

use text_io::try_read;  // Cargo.toml += text_io = "0.1"
fn main() {
    while let Ok(t): Result<i64, _> = try_read!() {
            println!("{}", t);
    }
}

fails to compile.

If I try to provide type info, then it fails, when I don't provide , then obviously it's ambiguous how to resolve try_read!.

Here is working - but IMHO way longer - snippet:

use text_io::try_read;  // Cargo.toml += text_io = "0.1"
fn main() {
    loop {
        let mut tok: Result<i64, _> = try_read!();
        match tok {
            Ok(t) => println!("{}", t),
            Err(_) => break,
        }
    }
}
1 Answers

You can qualify Ok as Result::Ok and then use the "turbofish" operator to provide the concrete type:

fn main() {
    while let Result::<i64, _>::Ok(t) = try_read!() {
        println!("{}", t);
    }
}

(while let Ok::<i64, _>(t) also works, but is perhaps a bit more cryptic.)

Another option is to request the type inside the loop - rustc is smart enough to infer the type for try_read!() from that:

fn main() {
    while let Ok(t) = try_read!() {
        let t: i64 = t;
        println!("{}", t);
    }
}

The latter variant is particularly useful in for loops where the pattern match is partly hidden, so there is no place to ascribe the type to.

Related