Kotlin / KEEP

Kotlin Evolution and Enhancement Process
Apache License 2.0
3.42k stars 362 forks source link

Infinite loop #364

Open vmishenev opened 1 year ago

vmishenev commented 1 year ago

This issue is for discussion of the proposal to add an infinite loop for { ... }. The full text of the proposal is here.

Amejonah1200 commented 12 months ago

👀 Why does val result = for { break 42 } not return the type Int instead of Unit?

thumannw commented 10 months ago

Concerning infinite loop with break, what is the advantage of it being a Unit expression instead of just a statement?

needlesslygrim commented 9 months ago

I don't know if the keyword is still up for debate, but personally I think loop/repeat is a better choice. I see the reasoning in the full proposal is that it doesn't require introducing a new keyword, and that using while would make it look like the condition was missing. However, I personally have two questions:

  1. Doesn't for {} also have the same problem of looking like the condition is missing?
  2. Do loop or repeat not make better sense when read out loud? Saying for... print Hello World sounds a little strange, compared to normal use of for, for every item print item.name. I will admit that loop is also a little strange (although perhaps slightly better), loop... print Hello World, which is perhaps where repeat would be useful, but unlike for ( which I personally am familiar with because of Rust), is not used in any mainstream language I know of
Amejonah1200 commented 9 months ago

I don't know if the keyword is still up for debate, but personally I think loop/repeat is a better choice. I see the reasoning in the full proposal is that it doesn't require introducing a new keyword, and that using while would make it look like the condition was missing

  • @needlesslygrim

If the current version was Kotlin 0.x, I would've also suggested loop instead. Sadly, there are already code out there which might use loop or repeat (well, it exists in the std lib already!) and that code would break on upgrade. This is due to the fact that keywords have higher precedence than methods.

needlesslygrim commented 9 months ago

Ah, that makes sense. Maybe if there's ever a Kotlin 2.0 :^)

mgroth0 commented 9 months ago

Yeah I dislike for {} because it gramatically makes no sense and is confusing. Love this idea in general but I wish it could be better english like repeat or even forever. Actually I wrote this method for myself a while ago:

inline fun forever(op: Op) {
    contract {
        callsInPlace(op, AT_LEAST_ONCE)
    }
    do op() while (true)
}

And I really like the way it looks, because it is crystal clear when you write forever {} that it is an endless loop.

Amejonah1200 commented 9 months ago

The main benefit of such a "loop syntax" is: val result = for { break 42 }

As Kotlin already has the ability to create constructs like demonstrated by @mgroth0 above, if the ability of returning (more like breaking) a value isn't there, it is useless.

So I would propose to change this to loop constructs:

// returns either a string if broken or null if the condition is false or no more entries.
val result: String? = while(cond) { break "str" }
val result: String? = for(i in sequenceOf()) { break "str" }

The reason why a construct like

val result: Int = for (i in sequenceOf<Int>()) {} else 1

won't work, is because of these breaking cases:

for (i in sequenceOf<Int>()) if (true) else {} // is it `for ... else` or `if else`?
if (true) for (i in sequenceOf<Int>()) else {} // is it `if ... else` or `if { for ... else }`?
Peanuuutz commented 9 months ago

The reason why a construct like...

That's true. I guess in this case we would need to force the user to insert the brackets. Making them returning nullable is also an option. Either is OK to me.

rebokdev commented 8 months ago

maybe instead of for we could use repeat { ... } ? using for { ... } doesn't seem to make sense for me as there's nothing to loop through there should still be ability of break the difference between normal repeat and infinite one is easily noticeable so this shouldn't be a problem to only have break in the infinite one

daniel-rusu commented 5 months ago

The proposal to use for { ... } goes in the opposite direction and reduces clarity rather than improving it as for is usually used in the context of "for each element" or "for elements indexed by". Using loop { ... } or repeat { ... } would improve clarity otherwise the plain old while (true) { ... } is clearest.

needlesslygrim commented 5 months ago

I do agree with this, and although it may be difficult to work around due to pre-existing code, I feel that introducing a new loop construct would be better. I recently tried Go, which uses for for all loops, which is a major mistake in my opinion (for the reasons outlined in this thread), but at least it is consistently strange, where in Kotlin while loops do exist, so only unifying endless loops and iterator loops is quite strange to me.

To fix the problems around pre-existing code, maybe some kind of compiler flag could be introduced to allow use of the loop construct, or perhaps 'editions' could be introduced, functioning similarly to how they do in Rust, although this would be a major undertaking.

Peanuuutz commented 5 months ago

If we can solve the compatibility issue, I'm glad to have loop instead.

More agressively, we can leave out while completely because we can combine loop and if to get both while and do..while!