Присвоение не допускается при выражении?
В Java мы обычно можем выполнять присвоение в рамках условия while
. Однако Котлин жалуется на это. Поэтому следующий код не компилируется:
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)
}
В соответствии с этим другим thread это кажется лучшим решением:
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);
}
Но это?
Ответы
Ответ 1
Нет, лучший способ, ИМО, был бы
val reader = BufferedReader(reader)
reader.lineSequence().forEach {
println(it)
}
И если вы хотите убедиться, что читатель правильно закрыт (как это было бы с оператором try-with-resources в Java), вы можете использовать
BufferedReader(reader).use { r ->
r.lineSequence().forEach {
println(it)
}
}
Ответ 2
Вот самое короткое решение на базе stdlib, которое также безопасно закрывает читателя:
reader.forEachLine {
println(it)
}
Ответ 3
И вот краткое общее решение в стиле Котлина Романа Елизарова:
while (true) {
val line = reader.readLine() ?: break
println(line);
}
Здесь break
имеет тип Nothing, который не влияет на вывод типа для line
.
Ответ 4
В случаях, когда вы просто хотите заменить while ((x = y.someFunction()) != null)
вы можете использовать следующее:
generateSequence { y.someFunction() }
.forEach { x -> /* what you did in your while */ }
generateSequence
будет извлекать все значения одно за другим, пока не будет достигнут первый null
. Вы можете заменить .forEach
на reduce
или fold
(или что-либо еще, что кажется подходящим ;-)), если вы хотите сохранить последнее значение или суммировать значения в другом месте.
Однако для вашего конкретного случая использования вы можете просто использовать то, что показал JB Nizet в своем ответе, или использовать useLines
:
reader.useLines {
it.forEach(::println)
}
.forEachLine
, вероятно, является следующим лучшим сокращенным решением для этой конкретной readLine
-problem (уже здесь ответили), если вы знаете, что просто хотите прочитать все строки и затем остановиться.
Ответ 5
(Этот пример для цикла while) Надеюсь, что этот пример поможет вам..
Меняться от
while ((c = is
.read(buffer))> 0) {sb.append(String (buffer, 0, c, Charset.forName(UTF8))))}
в
while ({c = is
.read(buffer); c}()> 0) {sb.append(String (buffer, 0, c, Charset.forName(UTF8))))}