groovy git commit: GROOVY-8870: Spread-dot operator on list of lists
Repository: groovy Updated Branches: refs/heads/GROOVY_2_5_X f3c2b77bc -> 62c72a773 GROOVY-8870: Spread-dot operator on list of lists Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/62c72a77 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/62c72a77 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/62c72a77 Branch: refs/heads/GROOVY_2_5_X Commit: 62c72a773fc6540c74d209dfc02475a617ac5f94 Parents: f3c2b77 Author: Paul King Authored: Wed Nov 7 14:11:54 2018 +1000 Committer: Paul King Committed: Wed Nov 7 14:18:09 2018 +1000 -- src/spec/doc/core-operators.adoc | 28 +-- src/spec/test/OperatorsTest.groovy | 49 + 2 files changed, 74 insertions(+), 3 deletions(-) -- http://git-wip-us.apache.org/repos/asf/groovy/blob/62c72a77/src/spec/doc/core-operators.adoc -- diff --git a/src/spec/doc/core-operators.adoc b/src/spec/doc/core-operators.adoc index 31f409d..716d1eb 100644 --- a/src/spec/doc/core-operators.adoc +++ b/src/spec/doc/core-operators.adoc @@ -422,8 +422,8 @@ include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=pattern_matcher_st === Spread operator -The Spread Operator (`*.`) is used to invoke an action on all items of an aggregate object. It is equivalent to calling the action on each item -and collecting the result into a list: +The Spread-dot Operator (`*.`), often abbreviated to just Spread Operator, is used to invoke an action on all items +of an aggregate object. It is equivalent to calling the action on each item and collecting the result into a list: [source,groovy] @@ -433,7 +433,14 @@ include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot,indent=0 <2> call the spread operator on the list, accessing the `make` property of each item <3> returns a list of strings corresponding to the collection of `make` items -The spread operator is null-safe, meaning that if an element of the collection is null, it will return null instead of throwing a `NullPointerException`: +The expression `cars*.make` is equivalent to `cars.collect{ it.make }`. +Groovy's GPath notation allows a short-cut when the referenced property +isn't a property of the containing list, in that case it is automatically +spread. In the previously mentioned case, the expression `cars.make` can +be used, though retaining the explicit spread-dot operator is often recommended. + +The spread operator is null-safe, meaning that if an element of the collection is null, +it will return null instead of throwing a `NullPointerException`: [source,groovy] @@ -450,6 +457,21 @@ The spread operator can be used on any class which implements the `Iterable` int include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot_iterable,indent=0] +Use multiple invocations of the spread-dot operator (here `cars*.models*.name`) when +working with aggregates of data structures which themselves contain aggregates: + +[source,groovy] + +include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot_multilevel,indent=0] + + +Consider using the `collectNested` DGM method instead of the spread-dot operator for collections of collections: + +[source,groovy] + +include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot_alternative,indent=0] + + Spreading method arguments There may be situations when the arguments of a method call can be found in a list that you need to adapt to the method http://git-wip-us.apache.org/repos/asf/groovy/blob/62c72a77/src/spec/test/OperatorsTest.groovy -- diff --git a/src/spec/test/OperatorsTest.groovy b/src/spec/test/OperatorsTest.groovy index 474f8b6..d4d34ee 100644 --- a/src/spec/test/OperatorsTest.groovy +++ b/src/spec/test/OperatorsTest.groovy @@ -356,6 +356,55 @@ assert composite*.id == [1,2] assert composite*.name == ['Foo','Bar'] // end::spreaddot_iterable[] ''' +assertScript ''' +import groovy.transform.Canonical + +// tag::spreaddot_multilevel[] +class Make { +String name +List models +} + +@Canonical +class Model { +String name +} + +def cars = [ +new Make(name: 'Peugeot', + models: [new Model('408'), new Model('508')]), +new Make(name: 'Renault', + models: [new Model('Clio'), new Model('Captur')]) +] + +def makes = cars*.name +assert makes == ['Peugeot', 'Renault'] + +def models = cars*.models*.name +assert models == [['408', '508'], ['Clio', 'Captur']] +assert models.sum() == ['408', '508', 'Clio', 'Captur'] // flatten one level +assert models.flatten() == ['408', '508', 'Clio', 'Captur'] // flatten all levels (one in this case)
groovy git commit: GROOVY-8870: Spread-dot operator on list of lists
Repository: groovy Updated Branches: refs/heads/master 7fd540fba -> bf87f243f GROOVY-8870: Spread-dot operator on list of lists Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/bf87f243 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/bf87f243 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/bf87f243 Branch: refs/heads/master Commit: bf87f243fb7ebcaf6c2d621773cc575411c531b7 Parents: 7fd540f Author: Paul King Authored: Wed Nov 7 14:11:54 2018 +1000 Committer: Paul King Committed: Wed Nov 7 14:12:09 2018 +1000 -- src/spec/doc/core-operators.adoc | 28 +-- src/spec/test/OperatorsTest.groovy | 49 + 2 files changed, 74 insertions(+), 3 deletions(-) -- http://git-wip-us.apache.org/repos/asf/groovy/blob/bf87f243/src/spec/doc/core-operators.adoc -- diff --git a/src/spec/doc/core-operators.adoc b/src/spec/doc/core-operators.adoc index 31f409d..716d1eb 100644 --- a/src/spec/doc/core-operators.adoc +++ b/src/spec/doc/core-operators.adoc @@ -422,8 +422,8 @@ include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=pattern_matcher_st === Spread operator -The Spread Operator (`*.`) is used to invoke an action on all items of an aggregate object. It is equivalent to calling the action on each item -and collecting the result into a list: +The Spread-dot Operator (`*.`), often abbreviated to just Spread Operator, is used to invoke an action on all items +of an aggregate object. It is equivalent to calling the action on each item and collecting the result into a list: [source,groovy] @@ -433,7 +433,14 @@ include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot,indent=0 <2> call the spread operator on the list, accessing the `make` property of each item <3> returns a list of strings corresponding to the collection of `make` items -The spread operator is null-safe, meaning that if an element of the collection is null, it will return null instead of throwing a `NullPointerException`: +The expression `cars*.make` is equivalent to `cars.collect{ it.make }`. +Groovy's GPath notation allows a short-cut when the referenced property +isn't a property of the containing list, in that case it is automatically +spread. In the previously mentioned case, the expression `cars.make` can +be used, though retaining the explicit spread-dot operator is often recommended. + +The spread operator is null-safe, meaning that if an element of the collection is null, +it will return null instead of throwing a `NullPointerException`: [source,groovy] @@ -450,6 +457,21 @@ The spread operator can be used on any class which implements the `Iterable` int include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot_iterable,indent=0] +Use multiple invocations of the spread-dot operator (here `cars*.models*.name`) when +working with aggregates of data structures which themselves contain aggregates: + +[source,groovy] + +include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot_multilevel,indent=0] + + +Consider using the `collectNested` DGM method instead of the spread-dot operator for collections of collections: + +[source,groovy] + +include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=spreaddot_alternative,indent=0] + + Spreading method arguments There may be situations when the arguments of a method call can be found in a list that you need to adapt to the method http://git-wip-us.apache.org/repos/asf/groovy/blob/bf87f243/src/spec/test/OperatorsTest.groovy -- diff --git a/src/spec/test/OperatorsTest.groovy b/src/spec/test/OperatorsTest.groovy index 474f8b6..d4d34ee 100644 --- a/src/spec/test/OperatorsTest.groovy +++ b/src/spec/test/OperatorsTest.groovy @@ -356,6 +356,55 @@ assert composite*.id == [1,2] assert composite*.name == ['Foo','Bar'] // end::spreaddot_iterable[] ''' +assertScript ''' +import groovy.transform.Canonical + +// tag::spreaddot_multilevel[] +class Make { +String name +List models +} + +@Canonical +class Model { +String name +} + +def cars = [ +new Make(name: 'Peugeot', + models: [new Model('408'), new Model('508')]), +new Make(name: 'Renault', + models: [new Model('Clio'), new Model('Captur')]) +] + +def makes = cars*.name +assert makes == ['Peugeot', 'Renault'] + +def models = cars*.models*.name +assert models == [['408', '508'], ['Clio', 'Captur']] +assert models.sum() == ['408', '508', 'Clio', 'Captur'] // flatten one level +assert models.flatten() == ['408', '508', 'Clio', 'Captur'] // flatten all levels (one in this case) +// end::spr