Is there any way to express `while let Some(..) = .. && true`

Is there any way to express things like: while let Some(..) = .. && true

I wrote my code as below:

// some external variable: a
while let Some(&(x, y, z)) = stk.last() {
    if cmp(x, a) {
        stk.pop();
        // do my thing ...
    } else {
        break;
    }
}

I wish to avoid else break block, because it's not very necessary and kinda verbose.I thought it'll be nice if I can put cmp(x, a) in the same line with while let, but this is not allowed.

2 Likes

No, a pattern match is not a boolean, so you can't just and it with a boolean. The current spelling is probably the cleanest. There is also:

loop {
    match stk.last() {
        Some(&(x, y, z)) if cmp(x, a) => {
            stk.pop();
            // do your thing
        }
        _ => break
    }
}

and if you are entering an obfuscated code contest, then you could even write

while match stk.last() {
    Some(&(x, y, z)) if cmp(x, a) => {
        stk.pop();
        // do your thing
        true
    }
    _ => false
} {}

to dispose with the extra level of indentation. (Of course, any time you realize you could, you may want to first ask yourself whether you should.)

4 Likes

There's an RFC to add if let and while let chains, RFC 2497:

Summary

Extends if let and while let -expressions with chaining, allowing you to combine multiple let s and bool -typed conditions together naturally. After implementing this RFC, you'll be able to write, among other things:

...

while let Ok(user) = read_user(::std::io::stdin())
    && user.name == "Alan Turing"
    && let Ok(hobby) = read_hobby_of(&user)
{
    if hobby == "Hacking Enigma" {
        println!("Yep, It's you.");
        return Some(read_encrypted_stuff());
    } else {
        println!("You can't be Alan! ");
    }
}

return None;
9 Likes

(repost because I replied to the wrong person)

With the caveat that I don't know exactly what your code is doing...

If stk.pop returns an Option, couldn't you just use filter on the result? Then it would turn into a None and break your loop.

2 Likes

Thank you for your idea, let me explain the program:

  1. loop-check the last item in the stk vector.
  2. if the last item hits that condition (cmp), then pop this item out and do some stuff.
  3. or else just break the loop.

Your solution will do loop-pop, which is not what I mentioned above, sorry I didn't make it clear earlier.

2 Likes

Yes, match + if is what I finally adopted yesterday.

My friend send me a solution like this:

while matches!(stk.last(), Some(&(x, ..)) if cmp(x, a)) {
    if let Some((x, y, z)) = stk.pop() {
        // --snip---
    }
}

I believe it’s close to your second solution. Your post really enlightened me more about it. :smiling_face_with_three_hearts:

I'm currently on mobile so I can't test it, but shouldn't something like the following work?

if let (Some(a), true) = (function_returning_optional(), condition()){...}

Ah, I missed the key point that the condition depends on the return of the function. Another option would be something like:

if let Some(a) = function_returning_optional().filter(condition) {...}
1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.