Assignment not allowed in while expression?

百般思念 提交于 2019-11-29 02:18:29

问题


In Java we can usually perform an assignment within the while condition. However Kotlin complains about it. So the following code does not compile:

val br = BufferedReader(InputStreamReader(
        conn.inputStream))

var output: String
println("Output from Server .... \n")
while ((output = br.readLine()) != null) { // <--- error here: Assignments are not expressions, and only expressions are allowed in this context
    println(output)
}

According to this other thread, this seems the best solution:

val reader = BufferedReader(reader)
var line: String? = null;
while ({ line = reader.readLine(); line }() != null) { // <--- The IDE asks me to replace this line for while(true), what the...?
  System.out.println(line);
}

But is it?


回答1:


No, the best way, IMO, would be

val reader = BufferedReader(reader)
reader.lineSequence().forEach {
    println(it)
}

And if you want to make sure the reader is properly closed (as you would with a try-with-resources statement in Java), you can use

BufferedReader(reader).use { r ->
    r.lineSequence().forEach {
        println(it)
    }
}



回答2:


And here is short Kotlin-style general solution by Roman Elizarov:

while (true) {
    val line = reader.readLine() ?: break
    println(line);
}

Here break has Nothing type that doesn't affect type inference for the line.




回答3:


Here is the shortest solution powered by stdlib that also safely closes the reader:

reader.forEachLine {
    println(it)
}



回答4:


In cases you just want to replace while ((x = y.someFunction()) != null) you may use the following instead:

generateSequence { y.someFunction() }
          .forEach { x -> /* what you did in your while */ }

generateSequence will extract you all the values one by one until the first null is reached. You may replace the .forEach with a reduce or fold (or anything else that seems appropriate ;-)) if you want to keep the last value or sum up the values to something else.

For your specific use case however you may just use what JB Nizet in his answer has shown or use useLines:

reader.useLines {
  it.forEach(::println)
}

.forEachLine is probably the next best short-hand solution to that specific readLine-problem (already answered here) if you know you just want to read all lines and then stop.




回答5:


(This Example for while loop ) Hope this example will help you..

Change from

while ((c = is.read(buffer)) > 0) { sb.append(String(buffer, 0, c, Charset.forName(UTF8))) }

to

while ({c = is.read(buffer);c}() > 0) { sb.append(String(buffer, 0, c, Charset.forName(UTF8))) }



来源:https://stackoverflow.com/questions/41537638/assignment-not-allowed-in-while-expression

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!