Вырваться из лямбды в котлин - PullRequest
0 голосов
/ 31 мая 2018

Я пытаюсь добавить очень полезный метод расширения к классу Java InputStream, поскольку мы знаем, что для анализа потока требуется несколько строк кода, и в моем приложении нам нужно обрабатывать поток несколько раз.

Пока чтомоя функция расширения работает, но она действительно очень полезна для некоторых недостатков, с которыми мы сталкиваемся при использовании функции основного языка kotlin.

Моя функция расширения для потока Java, принимающая определение метода с одним аргументом.

fun InputStream.forEachLine(consumer: (line: String)->Unit){
    val reader = BufferedReader(InputStreamReader(this, Charset.defaultCharset()))
    var line: String? = null
    line = reader.readLine()
    while (line != null) {
        consumer(line)
        line = reader.readLine()
    }
}

//My Test is here
@Test
fun testExtnInputStreamForEachLine() {
    val stream = FileInputStream(File("c:\temp\sometextfile.txt"))
        stream.forEachLine {
            println(it)

            if(it.equals("some text")
            // I want to break the whole forEachLine block 

        }
}

В приведенном выше примере у меня есть следующие подходы:

  • return@forEachLine (это хорошо работает для пропуска той же обработки блока, аналогично продолжению)
  • создал run блок с меткой и попытка возврата на нее.(выдает ошибку времени компиляции)
  • break@withLabel (ошибка времени компиляции)
  • изменил метод, возвращающий boolean вместо Unit, и попытался вернуть false (ошибка времени компиляции)

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Возврат логического значения не работает, как я уже упоминал выше в вопросе.Создание моей функции расширения для Inline решило мою проблему.

Вместо

fun InputStream.forEachLine(consumer: (line: String)->Unit){

оно должно быть

inline fun InputStream.forEachLine(consumer: (line: String)->Unit){

Обратите внимание на ключевое слово Inline выше и теперь оно позволяет нам существовать из цикла с помощью возврата поддержкии вернитесь на этикетку.

0 голосов
/ 31 мая 2018

Изменить на: consumer: (line: String) -> Boolean вот так:

fun InputStream.forEachLine(consumer: (line: String) -> Boolean){
    val reader = BufferedReader(InputStreamReader(this, Charset.defaultCharset()))
    var line: String? = null
    line = reader.readLine()
    while (line != null) {
        if (consumer(line))
            break
        line = reader.readLine()
    }
}

//My Test is here
@Test
fun testExtnInputStreamForEachLine() {
    val stream = FileInputStream(File("c:\temp\sometextfile.txt"))
    stream.forEachLine {
        println(it)
        if(it.equals("some text")) true else false
    }
}
...