I’ve read this discussion with some interest. There appears to be an assumption that C-style for
loops is the most flexible and comprehensive way to implement loops, and all other variants are workarounds to cover carious use-cases of the traditional style.
The reason C’s for
is the way it is is because of hardware limitations back in 1972 when it was implemented on a PDP-7. This is no reason to hail it as being the optimal form of looping.
A lot of good arguments in favour of more extensive syntax in Kotlin, most of which I agree with. For most cases, there are already better ways to loop in Kotlin that are much more clear.
For the rest of this message, I’d like to address the argument that the C version is somehow flexible enough to do everything. This is simply not true, and if one looks further than just Java, there are much more interesting languages to take ideas from.
As someone who has been using Common Lisp for quite some time, the idea that the C-style loop is somehow comprehensive is a bit ridiculous. CL has arguably the most powerful looping construct of all languages, and if the goal is to be comprehensive, then CL is the direction that one should look, not C.
I’ve provide an example just to be clear. The CL loop
construct uses keywords to control behaviour, which is somewhat controversial even in CL circles because it makes it very verbose, but let’s focus on the functionality and not the actual syntax used to provide it.
Note that the newlines in the syntax are there for readability, you can write it all on one line if you want to.
First off, the traditional for(int i = 0 ; i < 5 ; i++) { print(i); }
:
(loop
for i from 0 below 5
do (print i))
Now, let’s loop i
from 0 to a
, and j
from 0 to b
, ending whenever either of them reach their bound. So basically for(int i = 0, j = 0 ; i < a && j < b ; i++, j++) { foo(i,j); }
:
(loop
for i from 0 to a
for j from 0 to b
do (foo i j))
How about something like the following in Java?
var list = new ArrayList<Integer>();
for(int i = 0 ; i < 5 ; i++) {
list.add(i);
}
The CL version:
(loop
for i from 0 below 5
collect i)
Here’s an example of a counter as well as an iteration over a list:
(loop
for i from 0 below a ; Loops from 0 until a
for v in list ; Set v to each element in list
until (equal v nil) ; If v is nil, then stop looping
collect (list i v)) ; Add a list containing the values i and v to the result
You can also combine exit checks before, after and in the middle of the loop. To do this in C you’d have to use break
:
(loop
for v in list
while (some-test)
collect v
until (some-other-test)
do (print v))
This is just a small sample of the things you can do with CL loop
. Here’s the full documentation if anyone is interested: CLHS: Section 6.1