-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support "do while" loops #1313
Comments
Not that while {
do_work();
condition
} { } |
Huh. Didn't know that. That isn't documented. Are the extra |
It's because while evaluates an expression, and an expression can be in On Thu, Oct 8, 2015, 12:58 PM mdinger [email protected] wrote:
|
It's not documented because it's more of a weird hack than it is something you should ever really write. |
Well, if that is to be the canonical form of it, it should probably be smarter and not require the extra brace set unless someone wants an extra expression. while {
do_work();
condition
} The extra brace is kinda inconsistent between expressions too. EDIT: It's not clear how similar the extra |
It's not a canonical form. It's cleverness permitted by the language On Thu, Oct 8, 2015, 1:27 PM mdinger [email protected] wrote:
|
If you want it to be more obvious, I usually do:
as an alternative to |
Me too but it just seems silly not to provide something this simple which is slightly nicer. I mean, loop {
if !condition { break }
do_work();
} |
I personally don't think that's enough of a reason to add new syntax. |
Could add something like:
It could also support stuff like: Currently, I don't think that do is a reserved keyword. |
Or: loop {
action();
more_code();
} while condition Just so there's a canonical, proper, and non-hacking way to check the condition at the bottom of the |
Ugh, based on my C++ experience do/while loops are 1) rarely needed, 2) ugly as hell, so I'd prefer to put additional sugar somewhere else. |
How is it ugly aside from a "looks different from a regular while" sense? It's the natural thing to do when you want to exit on a specific condition. It avoids break and it uses the same number of lines of code as a while loop. |
do {
do_work();
} while condition Is not ideal either, since the scoping rules don't allow condition to use local bindings from the body of the loop. In that way, the current loop-if is superior. |
@petrochenkov: What's wrong with for _ in 0..n {
do_work();
} ? |
@ticki |
👎 More complexity to the language grammar with not much to gain. |
You can write a reasonably clear macro that packages this up for you: macro_rules! do_loop {
(
$body:block
while $cond:expr
) => {
while { $body; $cond } { }
};
}
fn main() {
let mut i = 0;
do_loop! {
{
println!("i = {}", i);
i += 1;
}
while i < 10
}
} |
Wouldn't it work with while let ? |
@snuk182 |
Exceptionally strange to have |
|
If |
Not to go further off-topic but just to clarify: from a user's perspective it seems a keyword was essentially "wasted" on an unconditional loop that could be generated from a While |
underterminant version looks much nicer than dowhile and have the same functionality. i think dowhile is not necessary. actually after writing 2 years of c# i think rusts loop is much better cause it gives you the controll to break anywhere, not only in the beginning and end, also has nicer syntax |
FWIW, you could probably do this as a macro pretty easily. The implementation is left as an exercise to the reader, but something like:
Or, if you want to have a stronger separation:
While there's no way (that I can think of) to have the |
I think there's a simpler answer, try this
It functions like the break but is gentler. Now whether the optimizer will convert them into the same machine code or if not whether this or loop {break} is better I don't know. Might be interesting if someone who understands Rust better could explore an explain (^-^) |
I mean, yes, that works, but I think a lot of the whole point of useful control flow structures is that they don't require extraneous variables in order to work. |
If you're going to do that, don't even use a variable; just do
|
If you read the op again they explicitly say that's not ideal for them, though why I'm not sure. I agree that because loop is specifically designed to expect a break that using a loop{break;} probably makes just as much sense to the compiler as a do{} while{} would be and might even compile to the same as the example I gave (making the difference purely about human readability and code consistency) but as I said it might be worth comparing the two |
There's no need to put the loop condition check after the body. Adding // this does not work, don't try this in rust
do while condition {
do_work();
} |
One reason to put it after the body is that the condition of a do-while loop can (in most languages) depend on variables in the loop:
Syntatically, you could put the while condition at the beginning of the loop, but it would be confusing as a reader to see it depend on variables that are defined after the expression (even though the expression isn't evaluated until much later). |
In your example, |
If you're strictly using |
No, it doesn't – unfortunately. Though, if you're using the traditional C style of putting all variable declarations at the top of the function, you can do the equivalent just because everything's in scope everywhere. |
The The macro solution from #1313 (comment) isn't better in that regard. And rustfmt makes it even worse:
(Couldn't find an existing issue about that though and given rust-lang/rustfmt#2636 (comment) I don't have much hope it would be fixed anytime soon.) |
A do while is especially handy for checking input and the like. And it will be more readable than the current loop {
do_work();
if !condition {
break;
}
} I really like this syntax proposed by @mdinger: loop {
do_work();
} while condition |
The argument that it's unpopular to me is a pretty bad argument. I always miss do while in every language I learn. In rust because of very strict scope, it's even more useful. It's not a crucial feature, but it's also not worth ignoring for such a simple option that some developers in the community obviously love. Don't like it, don't use it, but why should the rest of us not have it? |
Because it makes the language more complex just by having it, and we don't want to just increase the complexity for a niche feature. |
If anyone wants to propose For now, there are variants of With that said, I think this issue can be closed. |
I want the "do ... while" loop also, why the Rust is so reluctant to do it, I have an example of using the "do ... while", and we use much in C, but now I have to make it with "while" statement, since the "loop" is so verbose. If you can abbreviate the function to fn, public to pub not bar, why not an elegant "do ... while"? The "loop" way
Workaround: set a precondition and go with "while" (let mut n = 1)
|
Sometimes you want to check the condition at the end and not the beginning.
These substitutes are less than ideal:
A
do while
loop would be nice in these cases.The text was updated successfully, but these errors were encountered: