rust-lang / rfcs

RFCs for changes to Rust
https://rust-lang.github.io/rfcs/
Apache License 2.0
5.89k stars 1.56k forks source link

[Language] for-else and while-else #3361

Open igotfr opened 1 year ago

igotfr commented 1 year ago

when assigning to a variable, break in for and while isn't allowed, this proposal allow it using a else

Example:

fn main() {
  let result = for counter in 0..5 {
    if counter == 3 {
      break i
    }
  } else { -7 };

  println!("The result is {result}") // 3
}
fn main() {
  let result = for counter in 0..5 {
    if counter == 90 {
      break i
    }
  } else { -7 };

  println!("The result is {result}") // -7
}

Alternatives

https://rust-lang.github.io/rfcs/2046-label-break-value.html

PatchMixolydic commented 1 year ago

This was previously suggested in #3163, which was closed due to concerns over the clarity of the syntax.

igotfr commented 1 year ago

This was previously suggested in #3163, which was closed due to concerns over the clarity of the syntax.

when break is not reached, evaluates to value in else, what's the struggle?

SOF3 commented 1 year ago

@cindRoberta the behavior in most other languages only runs else if no iterations happened at all, no matter break or not

igotfr commented 1 year ago

@cindRoberta the behavior in most other languages only runs else if no iterations happened at all, no matter break or not

@SOF3 in other languages, for and while aren't expressions. It's a weird behaviour for and while ever return (), the behaviour that I proposed is the same of Zig, Zig uses else

I proposed a different behaviour than Python

https://ziglang.org/documentation/master/#for

read the comment:

// For loops can also be used as expressions.
// Similar to while loops, when you break from a for loop, the else branch is not evaluated.

I'm not creating nothing, it already exists

SOF3 commented 1 year ago

Yes, but that's exactly the reason why it is extremely confusing if someone ends up using it as a non-expression. This is just as confusing as case without break not falling through in golang because everyone is used to that fact.

igotfr commented 1 year ago

Yes, but that's exactly the reason why it is extremely confusing if someone ends up using it as a non-expression. This is just as confusing as case without break not falling through in golang because everyone is used to that fact.

if, for, while and loop in Rust are ever evaluating for a value, same when not binded to a variable. Just that for and while are ever evaluating to () and if and loop not

if the struggle is the confusion with Python, use other keyword than else

SOF3 commented 1 year ago

But what you can do with for-else can already be done with iterators right? break-else is basically the same as iter.find_map(...).unwrap_or_else(...).

igotfr commented 1 year ago

But what you can do with for-else can already be done with iterators right? break-else is basically the same as iter.find_map(...).unwrap_or_else(...).

@safinaskar what can to be done with for-else can already be done too with labels, for-else is just fill a gap of ever evaluate to ()

safinaskar commented 1 year ago

@cindRoberta , what you want is already possible thanks to recently stabilized "break from labeled blocks" ( see https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html ). Here is how we can write your example with recent stable Rust: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4981da6fe916fc970922ebcd8e639e2c

igotfr commented 1 year ago

@cindRoberta , what you want is already possible thanks to recently stabilized "break from labeled blocks" ( see https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html ). Here is how we can write your example with recent stable Rust: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4981da6fe916fc970922ebcd8e639e2c

https://rust-lang.github.io/rfcs/2046-label-break-value.html

sollyucko commented 1 year ago

Here's are the relevant links I've found:

Previously proposed in:

Alternative features and proposals:

Similar features or proposals in other languages with the semantics you're proposing:

Features or proposals with similar syntax but semantics to run the else if the loop never iterates: