`for` return value

I am learning Rust and when I was using for, I noticed that it hasn't a return value, so i though that if it returns a bool depending if break it's used or not, you can less and it will be clearer. I guess that any other type than bool is not a good idea to return, because the compiler wouldn't be abled to check if for will always return something, instead, for evals to a bool when it breaks, and the negate when it ends without a break.
I guess that this can also improve while.
For example, this codes can be improved with this language suggestion:

fn contains<T>(slice: &[T], find: &T) -> bool {
    for item in slice {
        
        if find == item {
            return true;
        }
    }
    false
}

or

fn contains<T>(slice: &[T], find: &T) -> bool {

    let result = false;

    for item in slice {
        
        if find == item {
            result = true;
            break;
        }
    }

    result
}

and a clearer code, using this feature (considering that for evals to true when it uses break):

fn contains<T>(slice: &[T], find: &T) -> bool {
    for item in slice {
        
        if find == item {
            break;
        }
    }
}

How about improving your code by using Iterator::find instead of a for loop? Your function can be reduced to a single, declarative line, without the need for changing the behaviour of for loops (which is very unlikely to happen, I'd argue):

fn contains<T: PartialEq>(slice: &[T], find: &T) -> bool {
    slice.iter().find(|x| *x == find).is_some()
}

Edit: Iterator::any would be even better, as @steffahn pointed out:

fn contains<T: PartialEq>(slice: &[T], find: &T) -> bool {
    slice.iter().any(|x| x == find)
}
3 Likes

why use .find(…).is_some() if you can use .any(…)? :wink:

6 Likes

Haha, valid question I don't have an answer for :smile:

If this is a feature request (which I'm not sure about since your question is full of grammatical errors that make it very hard to comprehend), then the answer is "probably not going to happen". Why should a for loop evaluate to a boolean? Why not an Option at that point? How does this carry its weight? (Hint: it doesn't, as changing the type of for-as-an-expression would break a ton of code that already relies on it being unit.)

Note that for actually has type () today:

fn main() {
    let _x: () = for _ in [1] {};
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=6dc419653afd0a1c0c2cbe04ecba4134

So making it do anything else is prone to being a breaking change.

It might be possible to find a way to make it be an Option, where breaking from it is Some or something, but overall the general opinion has been that it's net not worth the churn.

There's always https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html#break-from-labeled-blocks as a workaround for general block value stuff.

3 Likes

Generally proposed as for ... else, and had been rejected in Proposal: Else clauses for for and while loops by Starwort · Pull Request #3163 · rust-lang/rfcs · GitHub and another open dup in [Language] for-else and while-else · Issue #3361 · rust-lang/rfcs · GitHub that looks like it will get closed too.

Yes, probably Option is the best type to return from for and while, so None will be the default if there is no break; and Some(T) will be obvious when break is used. Sorry for my bad English, I do my best, but I am not a native speaker.

Returning an Option<T> from a loop, using the break as the conditional is not a good idea in my opinion. Rust already has a bad reputation of being hard to learn, so any syntax change that doesn't bring anything new to the table, and that deviates too much from the status quo in other programming languages would only cause more churned users.

The declarative alternative mentioned already by several others is a much, much better option. Loops should resolve to the Unit type.

1 Like

I don't think this is true. The best parts of Rust are actually those where it differs from "other languages" (say the mainstream OOP languages). What type a language construct has is… basically an axiom, an uninteresting detail, and there isn't anything hard to learn to it, because it's just defined like that, and you only have to accept and remember it – nothing complicated.

Even if the above were true, for evaluating to an Option wouldn't fall into this category either. The general idea makes sense, and it wouldn't be a bad approach, if only it worked like this from the beginning. But nowadays it would simply break too much code, and it's definitely not worth it.

3 Likes

I agree with the fact that this wouldn't be the case if loops have worked like this from the beginning. That's why I focused on syntax changes in my comment above.

But my opinion about the user churn isn't related to that. Users that don't have experience with expression-based languages sometimes experience churn because the paradigm shift makes them anxious. Can you imagine the mental burden that such newcomers would experience if they found out that the break keyword would be yet another way of controlling the evaluation of the expression?

We should me mindful about what language features does Rust benefit from. We don't want it to become the next Scala.

for yielding Option is nothing compared to switching to an expression language.

If someone isn't willing to learn the somewhat different paradigm, they can feel free to ignore Rust and continue writing Java for the rest of their lives.

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.