This is an automated email from the ASF dual-hosted git repository. paulk pushed a commit to branch asf-site in repository https://gitbox.apache.org/repos/asf/groovy-website.git
The following commit(s) were added to refs/heads/asf-site by this push: new 81cf326 updated with a scan/cumulative sum example 81cf326 is described below commit 81cf326ba0cc48d6c580dfe9a153f8bdaece2ec3 Author: Paul King <pa...@asert.com.au> AuthorDate: Thu Jan 18 15:24:06 2024 +1000 updated with a scan/cumulative sum example --- site/src/site/blog/groovy-gatherers.adoc | 49 +++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/site/src/site/blog/groovy-gatherers.adoc b/site/src/site/blog/groovy-gatherers.adoc index 406eaf8..e229451 100644 --- a/site/src/site/blog/groovy-gatherers.adoc +++ b/site/src/site/blog/groovy-gatherers.adoc @@ -1,7 +1,8 @@ = Using Gatherers with Groovy Paul King :revdate: 2023-12-09T15:30:00+00:00 -:keywords: gatherers, jdk22, chop, collate, inject, ginq, streams, jep461 +:updated: 2024-01-03T22:00:00+00:00 +:keywords: gatherers, jdk22, chop, collate, inject, ginq, streams, jep461, fold, scan :description: This post looks at using Gatherers (JEP 461) with Groovy. An interesting feature being previewed in JDK22 is _Gatherers_ @@ -388,9 +389,9 @@ assert (1..8).stream().gather(windowMultiple(3, -1)).toList() == [[1, 2, 3], [4, 5, 6, 7, 8]] ---- -== Inject and fold +== Inject, fold and scan -Groovy's `inject` is a little different to the streams `reduce` intermediate operator. +Groovy's `inject` is a little different to the stream APIs `reduce` intermediate operator. The latter expects a binary operator which restricts the types of the elements being consumed and produced. @@ -401,7 +402,7 @@ The `inject` method can have different types for its arguments as shown here: assert (1..5).inject(''){ string, number -> string + number } == '12345' ---- -The `fold` built-in gatherer provides the equivalent functionality: +The `fold` built-in gatherer allows us to write the equivalent functionality for stream processing as shown here: [source,groovy] ---- @@ -411,6 +412,41 @@ assert (1..5).stream() .get() == '12345' ---- +Let's look at another `inject` example. This time _cumulative sum_. +If we have a sequence of numbers, the cumulative sum is another sequence +whose value at any index is determined by accumulating all the +numbers from the original sequence up to and including the index in question, e.g. the cumulative sum of `[1, 2, 3, 4]` is `[1, 3, 6, 10]`. + +This is again a good fit for Groovy's `inject`: + +[source,groovy] +---- +assert (1..5).inject([]) { acc, next -> + acc + [acc ? acc.last() + next : next] +} == [1, 3, 6, 10, 15] +---- + +This particular operation is deemed useful enough that Java actually +has a built-in library function for arrays: + +[source,groovy] +---- +Integer[] nums = 1..5 +Arrays.parallelPrefix(nums, Integer::sum) +assert nums == [1, 3, 6, 10, 15] +---- + +This particular operation isn't well suited to traditional streams, +but now with gatherers, we can use the `scan` built-in gatherer +to have similar functionality when processing streams: + +[source,groovy] +---- +assert (1..5).stream() + .gather(scan(() -> 0, Integer::sum)) + .toList() == [1, 3, 6, 10, 15] +---- + == Testing for a subsequence (fun with `inits` and `tails`) As a final example, let's have a look at how we might test @@ -579,3 +615,8 @@ likely pick whichever style makes sense. We are still in the early days of gatherers being available, so expect much more to emerge as this feature becomes more mainstream. We look forward to it advancing past preview status. + +.Update history +**** +*18/Jan/2024*: Updated with a scan/cumulative sum example. +****