Лучший шаблон для моделирования “продолжается” в закрытии Groovy

67
задан Opal 13 March 2018 в 08:23
поделиться

3 ответа

Можно только поддерживать, продолжаются чисто, не повреждаются. Особенно с материалом как eachLine и каждый. Неспособность поддерживать повреждение имеет отношение, как те методы оценены, нет никакого соображения, взятого для того, чтобы не заканчивать цикл, который может быть передан к методу. Вот то, как поддерживать, продолжаются -

Лучший подход (предполагающий, что Вам не нужно получающееся значение).

revs.eachLine { line -> 
    if (line ==~ /-{28}/) {
        return // returns from the closure
    }
}

, Если Ваш образец действительно настолько прост, это хорошо для удобочитаемости.

revs.eachLine { line -> 
    if (!(line ==~ /-{28}/)) {
        // do what you would normally do
    }
}

другая опция, моделирует то, что продолжение обычно делало бы на уровне байт-кода.

revs.eachLine { line -> 
    while (true) {
        if (line ==~ /-{28}/) {
            break
        }
        // rest of normal code
        break
    }

}

Один возможный способ поддерживать повреждение через исключения:

try {
    revs.eachLine { line -> 
        if (line ==~ /-{28}/) {
            throw new Exception("Break")
        }
    }
} catch (Exception e) { } // just drop the exception

можно хотеть использовать пользовательский тип исключительной ситуации, чтобы не маскировать другие реальные исключения, особенно если у Вас есть другая обработка, продолжающаяся в том классе, который мог бы выдать реальные исключения, как NumberFormatExceptions или IOExceptions.

71
ответ дан shemnon 24 November 2019 в 14:40
поделиться

Закрытия не могут повредиться или продолжиться, потому что они не конструкции цикла/повторения. Вместо этого они - инструменты, используемые для обрабатывания/интерпретирования/обрабатывания повторяющейся логики. Можно проигнорировать данные повторения путем простого возврата из закрытия, не обрабатывая как в:

revs.eachLine { line -> 
    if (line ==~ /-{28}/) {
            return
    }

}

поддержка Повреждения не происходит на уровне закрытия, но вместо этого подразумевается семантикой вызова метода, принял закрытие. Короче говоря это означает вместо того, чтобы назвать "каждого" на чем-то как набор, который предназначается для обработки всего набора, который необходимо назвать, находят, который обработает, пока определенное условие не соблюдено. Большинство (все?) времена Вы чувствуете потребность повредить от закрытия, что Вы действительно хотите сделать, находка особое условие во время Вашего повторения, которое заставляет метод находки соответствовать не только Вашим логическим потребностям, но также и Вашему намерению. Печально часть API испытывает недостаток в поддержке метода находки... Файл, например. Возможно, что все время потратил утверждение, должен ли язык включать, повреждают/продолжают, возможно, был хорошо потрачен, добавив метод находки к этим заброшенным областям. Что-то как firstDirMatching (Закрытие c) или findLineMatching (Закрытие c) имело бы большое значение и ответило бы 99 + %, "почему я не могу повредиться от...?" вопросы, которые открываются в списках рассылки. Однако это тривиально для добавления этих методов самостоятельно через MetaClass или Категории.

class FileSupport {
   public static String findLineMatching(File f, Closure c) {
      f.withInputStream {
         def r = new BufferedReader(new InputStreamReader(it))
         for(def l = r.readLine(); null!=l; l = r.readLine())
             if(c.call(l)) return l
         return null
      }
   }
}

using(FileSupport) { new File("/home/me/some.txt").findLineMatching { line ==~ /-{28}/ }

Другие взломы, включающие исключения и другое волшебство, могут работать, но представить дополнительные издержки в некоторых ситуациях и свернутый удобочитаемость в других. Истинный ответ должен посмотреть на Ваш код и спросить, выполняете ли Вы действительно итерации или ищете вместо этого.

15
ответ дан Cliff 24 November 2019 в 14:40
поделиться

Если вы предварительно создаете статический объект Exception в Java, а затем выбросите (статическое) исключение изнутри замыкания, затраты времени выполнения будут минимальными. Реальные затраты связаны с созданием исключения, а не с его выбросом. По словам Мартина Одерски (изобретателя Scala), многие JVM могут фактически оптимизировать инструкции throw до одиночных переходов.

Это можно использовать для имитации прерывания:

final static BREAK = new Exception();
//...
try {
  ... { throw BREAK; }
} catch (Exception ex) { /* ignored */ }
10
ответ дан 24 November 2019 в 14:40
поделиться