Kotlin:为什么我不能在循环防守中做任务?

Jir*_*ire 10 java kotlin

为什么这种语法无效?IntelliJ报告的错误是在这样的上下文中只允许表达式(第2行).我想知道是否有一些语法来解决这个问题,因为Java允许在循环功能中使用这种类型的赋值.

var c: Int;
while ((c = reader.read()) != 1) {
}
Run Code Online (Sandbox Code Playgroud)

Kar*_*l S 11

语法无效,因为c = reader.read()它不是Kotlin中的表达式 - 这可以防止所有==vs =bug.

你必须重写为:

while (true) {
    val c = reader.read()
    if (c == 1) break
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 有一些库实用程序可以从流和读取器中读取.无需手动完成. (3认同)
  • 你可以通过编写扩展函数来避免`while(true)`@Jire,正如Kotlin stdlib所做的那样.我在另一个答案中发布了一个这样做的例子. (2认同)

Jay*_*ard 8

注意: 另一个答案解释了语法问题,这里是使用while循环的替代方法.

关于Kotlin的一个好处是,你可以改变自己的世界,使其完全按照你想要的方式.因此,让我们创建一个扩展函数来完成其他答案中的基本功能,但要使其更具吸引力.

有了这个扩展功能:

inline fun Reader.readWhile(crossinline predicate: (Int) -> Boolean): Sequence<Char> {
    return generateSequence {
        val c = this.read()
        if (c != -1 && predicate(c)) {
            c.toChar()
        } else {
            null
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你现在可以简单地:

reader.readWhile { it != 1 }.forEach {
   // do something with each char
}
Run Code Online (Sandbox Code Playgroud)

如果你想自动关闭阅读器:

reader.use {
    reader.readWhile { it != 1 }.forEach {
       // do something with each char
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,您Char可以Int根据自己的需要决定顺序.您可以创建自己的useChars或forEachChar任何使您的代码按照您希望的方式生成的代码.有关其他扩展的示例,请参阅Kotlin API Refrence for kotlin.io,尤其是有关Reader想法的示例.

单元测试

扩展功能的单元测试:

@Test fun testSo32596261() {
    val reader = CharArrayReader(charArrayOf('A', 'B', 'C', 1.toChar(), 'D', 'E', 'F'))
    reader.use {
        assertEquals(listOf('A', 'B', 'C'), reader.readWhile { it != 1 }.toList())
    }
}
Run Code Online (Sandbox Code Playgroud)