In another question, a user suggested to write code like to that:
def list = ['a', 'b', 'c', 'd']
def i = 0;
assert list.collect { [i++] } == [0, 1, 2, 3]
Such code is, in other languages, considered bad practice because the content of collect changes the state of it's context (here it changes the value of i
). In other words, the closure has side-effects.
Such higher order functions should be able to run the closure in parallel, and assemble it in a new list again. If the processing in the closure are long, CPU intensive operations, it may be worth executing them in separate threads. It would be easy to change collect
to use an ExecutorCompletionService
to achieve that, but it would break the above code.
Another example of a problem is if, for some reason, collect
browse the collection in, say, reverse order, in which case the result would be [3, 2, 1, 0]
. Note that in this case, the list have not been reverted, 0 is really the result of applying the closure to 'd'!
Interestingly, these functions are documented with "Iterates through this collection" in Collection's JavaDoc, which suggests the iteration is sequential.
Does the groovy specification explicitly defines the order of execution in higher order functions like collect
or each
? Is the above code broken, or is it OK?