web-dev-qa-db-ja.com

while式での割り当ては許可されていませんか?

Javaでは、通常、while条件内で割り当てを実行できます。ただし、Kotlinはそれについて不平を言っているため、次のコードはコンパイルされません。

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);
}

しかし、そうですか?

17
PedroD

いいえ、最善の方法はIMOです

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

そして、(Javaのtry-with-resourcesステートメントの場合のように)リーダーが適切に閉じられていることを確認したい場合は、

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

そして、これがコトリン風の短い将軍 solution であり、Roman Elizarovによるものです。

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

ここでbreakには Nothing typeがあり、これはlineの型推論をnull不可の文字列として促進するのにも役立ちます。

12
Vadzim

以下は、リーダーを安全に閉じるstdlibによる最短のソリューション powered です。

reader.forEachLine {
    println(it)
}
11
Vadzim

while ((x = y.someFunction()) != null)を置き換えるだけの場合は、代わりに次のコマンドを使用できます。

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

generateSequence は、最初のnullに到達するまで、すべての値を1つずつ抽出します。 .forEachreduce または fold (または他の適切と思われるもの;-))を保持したい場合最後の値または値を別の値に合計します。

ただし、特定のユースケースでは、 JB Nizetの回答 が示しているものを使用するか、または useLines を使用できます。

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

.forEachLine は、その特定のreadLine- problem(すでに回答済み here )に対する次の最良の簡単な解決策です。すべての行を読んで停止したい場合は、 。

2
Roland