Description

The idea is to have access to an index or counter in all the functional methods iterating over collections, by using an additional parameter in the closure passed in parameter of those methods. That way, we don't need to add as many *withIndex variant methods to the existing ones, but rather provide a convenient convention.

Some examples with each, and similarly by replacing each with find/findAll/any/every/collect and perhaps inject:

Paul King
added a comment - 06/Oct/09 1:05 AM - edited There is some significant overlap between this issue and GROOVY-1182 . Perhaps we can edit one to be the superset of the two issues and close the other as a duplicate.

(1)
We could change the language to allow method local global variables. Basically that means that changes to this variable will be kept. In that it is comparable with a field. But since you cannot declare a field in a closure this would allow field logic in closures without having to define a class. This idea would maybe also save some usages of fields.

(2)
We could give closures some kind of call counter (with possible reset) in case of iterating with "each" this would mean that every call increases the counter, so it is equal to an index. The bad side of this is, that we have to use a fixed name and logic like we have for owner or delegate.

blackdrag blackdrag
added a comment - 07/Oct/09 3:48 PM I have several alternative suggestions to the map idea:
(1)
We could change the language to allow method local global variables. Basically that means that changes to this variable will be kept. In that it is comparable with a field. But since you cannot declare a field in a closure this would allow field logic in closures without having to define a class. This idea would maybe also save some usages of fields.
(2)
We could give closures some kind of call counter (with possible reset) in case of iterating with "each" this would mean that every call increases the counter, so it is equal to an index. The bad side of this is, that we have to use a fixed name and logic like we have for owner or delegate.
both of these would be quite generic solutions

If this approach is taken, I would suggest that in the 2-arity-closure version of the each/find/etc methods the index to be the first parameter to the closure. Therefore, maps and lists can be treated the same way, as the first parameter of these 2-arity-closures will always be the "key" and the second the value.

Demian Ferreiro
added a comment - 04/Jun/11 12:52 AM If this approach is taken, I would suggest that in the 2-arity-closure version of the each/find/etc methods the index to be the first parameter to the closure. Therefore, maps and lists can be treated the same way, as the first parameter of these 2-arity-closures will always be the "key" and the second the value.
def printKeyValuePairs(col) {
col.each { k, v ->
println "$k: $v"
}
}
printKeyValuePairs [foo: "bar", baz: "wiz"]
printKeyValuePairs ["this", "would", "be", "cool"]
Would print:
foo: bar
baz: wiz
0: this
1: would
2: be
3: cool
Another approach could be adding an enumerate method to lists (as in Python ):
>>> ["foo", "bar"].enumerate()
[0:foo, 1:bar]
And then just use the map version of the each/filter/etc methods.
Or, maybe more groovylistic , have a type conversion from List to Map (I like this on better ^_^):
>>> ["foo", "bar"] as Map
[0:foo, 1:bar]

Masato Nagai
added a comment - 28/Oct/11 6:09 PM
I would suggest that in the 2-arity-closure version of the each/find/etc methods the index to be the first parameter to the closure.
It seems a good idea. If so, what about map.each with three parameters? Will the first parameter be the index just like others?:
map.each { index, key, value ->
}

Since we now have withIndex and indexed (see GROOVY-7175) I am going to close this. These methods can be used in combination with the standard each/find/findAll/collect variants to achieve the desired result. Please reopen if you have a use case that is not covered.

Paul King
added a comment - 17/Dec/14 10:43 PM Since we now have withIndex and indexed (see GROOVY-7175 ) I am going to close this. These methods can be used in combination with the standard each/find/findAll/collect variants to achieve the desired result. Please reopen if you have a use case that is not covered.