В другом вопросе пользователь предложил написать такой код:
def list = ['a', 'b', 'c', 'd']
def i = 0;
assert list.collect { [i++] } == [0, 1, 2, 3]
Такой код в других языках считается плохой практикой, потому что содержимое collect изменяет состояние своего контекста (здесь оно изменяет значение i
). Другими словами, закрытие имеет побочные эффекты.
Такие функции более высокого порядка должны иметь возможность запускать замыкание параллельно и снова собирать его в новый список. Если обработка в замыкании длительная, интенсивно использующая процессор, возможно, стоит выполнять их в отдельных потоках. Было бы легко изменить collect
для использования ExecutorCompletionService
для этого, но это нарушит код выше.
Другой пример проблемы: если по какой-то причине collect
просмотреть коллекцию, скажем, в обратном порядке, в этом случае результатом будет [3, 2, 1, 0]
. Обратите внимание, что в этом случае список не был восстановлен, 0 действительно является результатом применения замыкания к «d»!
Интересно, что эти функции задокументированы как «Итерации по этой коллекции» в JavaDoc коллекции, который предполагает, что итерация является последовательной.
Определяет ли спецификация groovy порядок выполнения функций более высокого порядка, таких как collect
или each
? Приведенный выше код не работает или все в порядке?