That’s exactly how I write my code, too. I call it the early-return convention. In this case it is early-break.
Explanation: reduce the number of nested structures (especially nested if), by introducing returns as early as possible.
That’s exactly how I write my code, too. I call it the early-return convention. In this case it is early-break.
Explanation: reduce the number of nested structures (especially nested if), by introducing returns as early as possible.
Java 8 stream API could be useful
https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html#lines--
Use this kind of code.
val reader = BufferedReader(reader)
var line = 1
while (line != null) {
line = reader.readLine()
if(line != null)
System.out.println(line)
else
break
}
Thank you so much
U helped me so much
I was trying for many hours then I found ur code
the clue with this
val line = reader.readLine()
inside the loop
my error was using
var line = reader.readLine()
outside the loop
this is bad practice… you just clutter namespace with garbage names ‘reader’ and ’ line ’
It’s a well known and easily readable construct from the days of C. Nothing unsafe about it all.
while(a=b++)
a perfectly good idiom.
It’s entirely correct. And why it’s a core part of just about every single language out there.
How about this.
val reader = BufferedReader(reader)
var line = reader.readLine()
while (line != null) {
System.out.println(line)
line = reader.readLine()
}
This does sound very sane to me: in most languages, things like break/if–else are straight statements, as
they can’t return a value, but in Kotlin, we have those keywords as expressions, even though they have no value.
Conversely, C et al allow assignments to be evaluated as expressions (as they have a natural ‘value’) but Kotlin does not
I don’t get it. Why this reversal ?
Don’t like it; it duplicates the reader.readLine() bit, which is a code smell for me, especially if that
line were doing something more complicated
I don’t like that at all; it uses break for a ‘normal’ exit from a function, something that will happen
eventually; I’d rather keep break for abnormal loop exiits
Thanks a lot… for this life saving code’s snippet…
How about this gives inline fun?
inline infix fun (() -> Unit).gives(crossinline test: () -> Boolean): Boolean {
this()
return test()
}
fun main(args: Array<String>) {
var i = 0
while({ i += 1 } gives { i < 10 }) {
println("Hello, world! $i")
}
}
That means you’re not restricted to the test being “is not null” as with the (admittedly useful) ?: break approach. Indeed, the action and test can both involve arbitrary operations. And it keeps the side-effect and the test “expression” cleanly separate, in a terse way.
Sadly https://youtrack.jetbrains.com/issue/KT-5837 means the receiver can’t be crossinlined.
Since this thread seems to be getting attention again, I want to include links to some helpful resources.
The primary use case discussed has been reading lines from a BufferedReader, which in Java is often solved using an assignment in a while loop.
You could use some of the previously suggested methods in order to read lines in a similar manner, but in Kotlin there are several built-in options worth considering:
Kotlin extensions to
Reader
forEachLine(),readLines(),useLines()and more…
Kotlin extensions to
BufferedReader
lineSequence()
Or this, just for fun. Maybe less efficient but avoids having to declare a variable outside the loop.
import java.io.BufferedReader
import java.io.StringReader
fun main() {
val reader = BufferedReader(StringReader("Foo".split("").joinToString("\n")))
for (line in { reader.readLine() } sequenceWhile { it != null }) {
println(line)
}
}
inline infix fun <T> (() -> T).sequenceWhile(crossinline test: (T) -> Boolean): Sequence<T> = sequence {
while (true) {
this@sequenceWhile().also { if (test(it)) { yield(it) } else return@sequence }
}
}
BTW, just as a quick hint, you could also use a .also with the assignment and it works just fine. So for your example, it will be like this:
BufferedReader reader = new BufferedReader(reader);
String line = null;
while (reader.readLine().also{ line = it } != null) {
System.out.println(line);
}
(This can also work with .apply, but IMO it looks nicer with the it instead of this
Thanks a lot! it’s the best one.
When I read such creativity, I feel like a dumb ass ![]()
It’s fun to read creative code, but it’s better to write boring code.
What’s creative today will be boring tomorrow.
This is a very long thread, which is started in 2013, and still kind of active, which alone shows that, this is not applicable only for a very small number of codebases. Apparently, this is a little bit of a headache which many developers noticed at a point.
I have been using Kotlin for 2.5 years and I find it a very fancy language. What I like most about it is being pragmatic while trying to tackle biggest challenges like null safety and immutability.
I read the whole thread and couldn’t find a neat solution. Either you can’t define the line only in the while loop scope, or you need to make it mutable, or you need to use a break which is also breaking the code flow! AFAIK, all of these are discouraged by Kotlin community.
The best one in the whole thread for me is something similar to @vitalyb 's suggestion. maybe this:
do {
val line = reader.readLine()
?.also{ println(it) }
} while (line != null)