groovy

Provide a collectAll() method for lists (WAS: Provide a 'SpreadAllDot' operator)

Details

  • Type: New Feature New Feature
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Fixed
  • Affects Version/s: 1.5, 1.5.1
  • Fix Version/s: 1.5.2
  • Component/s: None
  • Labels:
    None
  • Number of attachments :
    0

Description

Currently we have list*.method() that invokes the method on all items in the list.
It would be useful to also support list**.method() that invokes the method on all items in the list and recursively for any lists within the list.

def animalLists= [["ant", "mouse", "elephant"], ["deer", "monkey"]]
assert animalLists.size() == 2
assert animalLists*.size() == [3, 2]
assert animalLists**.size() == [[3, 5, 8], [4, 6]]

Activity

Hide
Guillaume Laforge added a comment -

Interesting idea.
Do you think it should be a new notation, or in this case, wouldn't a method taking a closure be enough?
Say, something like collection.recurse { it.method() }

Show
Guillaume Laforge added a comment - Interesting idea. Do you think it should be a new notation, or in this case, wouldn't a method taking a closure be enough? Say, something like collection.recurse { it.method() }
Hide
Paul King added a comment -

I guess I was thinking about the shortened form to augment Groovy's GPath notation. E.g., considering GROOVY-2387, we removed a layer of magical unwrapping, so now the example is longer to type. In that example, the last line would go from:

assert [5 * 1499, 499, 4 * 499] == invoices.items.collect{ it*.total() }.flatten()

to:

assert [5 * 1499, 499, 4 * 499] == invoices.items**.total().flatten()

which would look nicer. But if people think it is confusing or if it turms out too hard to implement, then the longer form is also a possibility. Perhaps a Collection.collectAll{ closure } or as per your suggestion.

Show
Paul King added a comment - I guess I was thinking about the shortened form to augment Groovy's GPath notation. E.g., considering GROOVY-2387, we removed a layer of magical unwrapping, so now the example is longer to type. In that example, the last line would go from:
assert [5 * 1499, 499, 4 * 499] == invoices.items.collect{ it*.total() }.flatten()
to:
assert [5 * 1499, 499, 4 * 499] == invoices.items**.total().flatten()
which would look nicer. But if people think it is confusing or if it turms out too hard to implement, then the longer form is also a possibility. Perhaps a Collection.collectAll{ closure } or as per your suggestion.
Hide
Guillaume Laforge added a comment -

The double star is interesting, a method is easier to implement and doesn't require IDE developers to catch up
I'm not really sold on either of these approaches.
I'd be happy to have some more feedback from others as well.

Show
Guillaume Laforge added a comment - The double star is interesting, a method is easier to implement and doesn't require IDE developers to catch up I'm not really sold on either of these approaches. I'd be happy to have some more feedback from others as well.
Hide
Paul King added a comment -

OK, I will have a bit more of a think about how to present the best possible case for it and then we can decide whether to dump the idea or not. It is meant to mimic the "node.**.xx" operator available for XML operations.

Show
Paul King added a comment - OK, I will have a bit more of a think about how to present the best possible case for it and then we can decide whether to dump the idea or not. It is meant to mimic the "node.**.xx" operator available for XML operations.
Hide
Paul King added a comment -

What about just a collectAll method for now?
We could always add the ** later if we find it truly useful:

def animalLists= [["ant", "mouse", "elephant"], ["deer", "monkey"]]
assert animalLists*.size() == [3, 2]
assert animalLists.collect{ it.size() } == [3, 2]
assert animalLists.collectAll{ it.size() } == [[3, 5, 8], [4, 6]]
// assert animalLists**.size() == [[3, 5, 8], [4, 6]] // potential future enhancement
Show
Paul King added a comment - What about just a collectAll method for now? We could always add the ** later if we find it truly useful:
def animalLists= [["ant", "mouse", "elephant"], ["deer", "monkey"]]
assert animalLists*.size() == [3, 2]
assert animalLists.collect{ it.size() } == [3, 2]
assert animalLists.collectAll{ it.size() } == [[3, 5, 8], [4, 6]]
// assert animalLists**.size() == [[3, 5, 8], [4, 6]] // potential future enhancement
Hide
Guillaume Laforge added a comment -

Yeah, collectAll() will do for now.

Show
Guillaume Laforge added a comment - Yeah, collectAll() will do for now.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: