What do you guys prefer usually? (It's best if you...
# announcements
c
What do you guys prefer usually? (It's best if you pick the option you use when you don't need break/continue and don't “sequence” multiple extensions) 🔴 for-in loop
Copy code
for(element in collection) { ... }
🔷 forEach extension
Copy code
collection.forEach { element -> ... }
React with 🔴 or 🔷 to vote Feel free to reply and tell why you prefer that option
🔴 17
🔷 30
n
if it's part of a sequence, sure, I'll do forEach. but often I want break and continue to work, so I'll do 🔴 if I can
n
I guess the issue is that
for
gives you break/continue, but
forEach
chains far more nicely. So ultimately everyone probably uses both sometimes, makes it harder for the community to settle on one perhaps
y
@nanodeath if you write it as
run { collection.forEach {} }
break:
return@run
continue:
return@forEach
n
I...guess
c
@Youssef Shoaib [MOD] I don't think it's as readable though
n
I think I can usually rewrite it using filter and avoid control flow stuff
☝️ 4
y
I'd say that the continue equivalent is quite readable but the break one isn't so yeah I agree
n
Well, in the same way you can also do
something.map { ... }. map { .... }. map { ... }. let { for (element in it) { .... } }
i.e. you can get "nice" chaining for for loops by using scope functions. but it's clearly less natural.
I guess if
break
continue
were allowed in lambdas passed to
inline
functions we could have solutions with the best of both worlds
y
Personally imho I "prefer" forEach if I am already chaining some calls but I use for-in when I have a variable that has the collection in scope
c
I myself prefer for-in unless I chain extensions (like in the @Nir's message) I guess it's just more readable for me personally
n
I think for me if I just have a collection, I'll use a conventional for-loop, and if I have a sequence already, I'll use forEach
n
Yeah, I think most people here are saying similar things: regular for loop if you have a variable,
.forEach
if the collection/sequence is the result of a perhaps non-trivial amount of chaining
well, a sequence is just as nice to use in a for loop if you have a variable for it, but I guess when you say "sequence" you mean a bunch of chained calls
n
I'm going to vote for both 😛
y
Also, I think we can all agree on this, but when you have an index-based for loop (i.e. the classic
for(int i = 0; i < blablabla; i++)
java loop), using for-in is definitely superior to forEach
n
I dunno, it doesn't really make that much difference?
You have
forEachIndexed
☝️ 1
y
I didn't mean that. I meant if you have a
for(i in 0 until count)
then you never write it as
(0 until count).forEach { }
. I did explain it horribly sorry, but yeah I just mean if you're looping over an
IntRange
then you never use forEach
☝️ 1
👍 1
t
I prefer forEach. Because I like to use messages to get things done. I prefer message sends to more special interned language control constructs. Now and then again I'll use the other because of break/continue, but I usually use those a code smell detector and find I can rewrite the code to no longer need break/continue.
o
Most situations? (90+ %) -->
for
In a chain? Nullable? Need a quick index? -->
forEach(Indexed)
Kotlin style guide encourages the usage of the good ol'
for
unless you have a specific need for
forEach
. https://kotlinlang.org/docs/coding-conventions.html#loops
g
Looping code is vulnerable to errors: • "off-by-one" boundary overflow/underflow • improper initialization • accidental exit • infinite loops • forgetting to update a counter • updating the wrong counter • etc.... Loops generally require setting up accumulators, then running a gamut of 
if
break
continue
, and 
return
 statements, like some kind of mad obstacle race that involves as many state changes as possible. Different kinds of collections require different looping constructs - which adds more complexity. None of that has anything to do with why the loop was created in the first place which is to transform the underlying data in a collection (or array). With functional transformations, all those concerns disappear. Instead of thinking, “Oh, I need to process that stuff, I'll add an inner loop!” I'm thinking “What data structure would have the best performance characteristics for this transformation?” I can only think about a limited number of things at once. Each unnecessary concern takes precious thought power away from a more important one. https://github.com/GlenKPeterson/Paguro/wiki/Looping-vs.-Functional-Transformations
n
Almost none of the errors you mentioned can actually occur in this kind of for loop though, and it doesn't involve setting up an accumulator any more than .forEach. seems like a rather extreme take.
m
Neither. I try to refactor the code from “doing something” to “returning something”. In legacy code there are so many for/each loops that just build some collection … maybe not that much in Kotlin, but definitely in Java.