While loop - conditional check in the middle


#1

This is something that has always occurred to me as missing from every language.
I don’t really know how or if it should be implemented, I just want to ask for your opinion.

There are 2 variants of a while loop -
while (cond) {} and do {} while (cond)
The prior will evaluate the condition and break if it does not evaluate to true BEFORE execution of the code block.
The latter will evaluate the condition and break if it does not evaluate to true AFTER execution of the code block.

What I always run into is the option to do this in the middle of the code block, without inverting the condition and then having a break.

Usually, the case looks something like this:

while (true) {
    val a = queue.poll()
    if (a == null) break
    // do something with a
}

It would be interesting to have a variant that changes the syntax of this.

loop {
    val a = queue.poll()
    condition (a != null)
    // do something with a
}

Here, the function condition will take a given boolean and break if it is false, in the middle of the loop its code.
It is possible to achieve this using inline functions and receivers but that would impact performance,
as you either need to make it use coroutines or throw an exception to stop in the middle of the block.

This would, in my opinion, be much cleaner than:

var item = queue.poll()
while (item != null) {
    // do something with a
    
    item = queue.poll()
}

Or:

var item: T? = null
while (queue.poll().also { item = it } != null) {
    // do something with a
    // oh wait the compiler doesn't understand that `item` cannot be `null`
}

Now, given this idea, you might ask: Is this feature necessary? Does this feature not bloat the language which already has a very rich feature set? Yes it does, and no it is obviously not necessary, but it does bring some cleaner code to the table which is something to consider. Any suggestions for improving the syntax or making it more backwards compatible so that it doesn’t look alien compared to existing loops are of course welcome.


#2

While I think the idea is interesting I don’t think there is any reason to add it to kotlin. In my experience this would be used only rarely and it would as you pointed out bloat the language.
Also I don’t see the problem with if(condition) break and I don’t think there is a good reason for adding a special syntax here.


#3

Note that break is an expression inside a loop, so in your case you can use it like:

while (true) {
    val a = queue.poll() ?: break
    // do something with non-nullable a
}