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
commit e52fd0bcb248f0c349754e71446da09a41098bb5 Author: Paul King <[email protected]> AuthorDate: Tue May 13 21:57:41 2025 +1000 minor tweaks --- site/src/site/releasenotes/groovy-5.0.adoc | 59 +++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/site/src/site/releasenotes/groovy-5.0.adoc b/site/src/site/releasenotes/groovy-5.0.adoc index 5ef2e52..eaef3e1 100644 --- a/site/src/site/releasenotes/groovy-5.0.adoc +++ b/site/src/site/releasenotes/groovy-5.0.adoc @@ -31,7 +31,7 @@ introduces a new `main` method signature and compact source notation for Java cl Groovy 5 supports this new notation, as well as Groovy's traditional scripts, and an alternative abbreviated form. -Let's recap the story so far. First, a traditional Java class: +Let's recap the story so far. First, a traditional (Java) class: [source,java] ---- @@ -49,8 +49,9 @@ Second, a traditional Groovy script: println 'Hello, World!' ---- -Groovy scripts are given an implicit main method and implicit class definition. Variable declarations in scripts -are local variable declarations in the implicit main method unless annotated with `@Field`, in which case they become field definitions of the implicit class. +Groovy scripts are given implicit `main` and `run` methods and an implicit class definition. +Variable declarations in scripts are local variable declarations in the implicit `run` method +unless annotated with `@Field`, in which case they become field definitions of the implicit class. Third, the "instance main" method proposed for JEP 512 in Java with an implicit class definition: @@ -85,7 +86,7 @@ You may wonder why Groovy supports the JEP 512 notation when the traditional Gro is shorter? Firstly, there is Java compatibility, but also there are scenarios where we might like to use method or class annotations, and that is hard to do for an implicit method or an implicit class. -`TYPE` targeted annotations on the `main`, or `run`, method will be moved to the generated +`TYPE` targeted annotations on the `main` or `run` method will be moved to the generated script class. `METHOD` targeted annotations remain on the method. Classes created with an "instance main" method (like above) are JEP 512 compatible @@ -125,8 +126,9 @@ are treated like a normal Groovy script. Another important distinction for JEP 5 compatible classes is that fields (like `lower`, `foo`, and `bar` in the above example) don't need to be annotated with `@Field`. -An additional form is also supported which involves overwriting the `run` method -in a script. This provides an alternate form to the earlier shown `main` variants. +An additional form is also supported which involves supplying a `run` method +instead of a `main` method. +This provides an alternate form to the earlier shown `main` variants. The difference is that rather than producing a JEP 512 compatible class, Groovy produces a script class which extends the `Script` class in the normal way and has access to the normal script binding and context. The use case is again where you @@ -148,12 +150,15 @@ To summarise: * If you need access to the script binding or context, write a traditional class that extends the `Script` class, or a traditional Groovy script, or use the `run` method. * If you use the supported `main` or `run` method variants, you can have field definitions and other methods, -and you don't need `@Field`. Consider these if you don't like `@Field` or you want to use annotations. -* If you source file has any statements outside methods that aren't field declarations, -it will be treated as a traditional script. +and you don't need `@Field`. Consider these if you don't like `@Field` or you want to use annotations on the +implicit class or the main/run method. +* If your source file has any statements outside methods that aren't field declarations, +it will be treated as a traditional Groovy script. * Use the "instance main" method variant if you want the generated bytecode to follow JEP 512 conventions. You will need JDK25+ to run from Java, or JDK11+ to run from Groovy. +== Improved Web Content Creation + === Jakarta EE support The `groovy-servlet` module supports: @@ -184,6 +189,14 @@ easier. You can still obtain the older Javax EE versions of the relevant classes using the "javax" classifier when specifying your dependency on `groovy-servlet`. +== Improved Type Checking + +Groovy's type checking is extensible. This allows you to weaken or strengthen +type checking. In Groovy 5, we've added a type checker for format strings. +Errors in such strings are often not detected until runtime, but now you +can check them at compile time. It adds to the existing regex checking +capabilities. + === An Optional Type Checker for Format Strings The `format` methods in `java.util.Formatter`, and other similar methods, @@ -219,7 +232,9 @@ The goal of the `FormatStringChecker` is to eliminate a large number of such runtime errors. If the API call passes type checking, it will be guaranteed to succeed at runtime. -=== AST transform additions and improvements +== AST transform additions and improvements + +=== Making Operators More Groovy There is a new `OperatorRename` AST transform. This is very useful when using third-party libraries which use different @@ -246,6 +261,9 @@ For instance, you might like to rename: * `add` to `plus` if using Commons Math matrices * `sub` to `minus` if using Nd4j matrices +Groovy has excellent support for writing Domain Specific Languages (DSLs), +but using the `@OperatorRename` transform means we can skip constructing our own DSL in simple cases. + == Extension method additions and improvements Groovy provides over 2000 extension methods to 150+ JDK classes to enhance JDK functionality, with *350 new methods added in Groovy 5*. These methods reduce dependency on third-party libraries for common tasks, and make code more intuitive. Let's explore some highlights from those 350 new methods. @@ -294,10 +312,10 @@ and provides options for handling the case when the collections are different si [source,groovy] ---- -def gs = ['π Ά'].repeat(4) +def gs = ['π Ά'].repeat(5) def hs = ['π'].repeat(3) assert gs.interleave(hs).join() == 'π Άππ Άππ Άπ' -assert gs.interleave(hs, true).join() == 'π Άππ Άππ Άππ Ά' +assert hs.interleave(gs, true).join() == 'ππ Άππ Άππ Άπ Άπ Ά' ---- The `flattenMany` method is a close cousin to the @@ -410,6 +428,19 @@ nums.indices.every { } ---- +A known feature of some queues within the JDK Collections API, +is that the standard iterator for queues like `PriorityQueue` don't return elements in priority order. +Instead, the `poll()` method is used to return the next highest priority element. +The `drain` method provides an easy way to poll all the elements from a queue. + +[source,groovy] +---- +def letters = new PriorityQueue(String.CASE_INSENSITIVE_ORDER) +letters.addAll(['Z', 'y', 'X', 'a', 'B', 'c']) +assert letters.toList() == ['a', 'B', 'c', 'Z', 'X', 'y'] // uses iterator() +assert letters.drain() == ['a', 'B', 'c', 'X', 'y', 'Z'] +---- + ==== Checked collections Java, being statically typed, tries hard to ensure type safety at compile time @@ -542,9 +573,9 @@ assert (1..100000).iterator() .toList() == [3, 315, 2475] ---- -=== Additional primitive array extensions +=== Additional array extensions -There are over 220 added or enhanced extension methods on primitive arrays. +There are over 220 added or enhanced extension methods on Object and primitive arrays. For single dimension arrays, we have: `any`, `chop`, `collectEntries`, `countBy`, `each`, `eachWithIndex`, `equals`, `every`, `first`, `flattenMany`, `head`, `indexOf`, `indexed`, `init`, `injectAll`, `join`, `last`, `lastIndexOf`, `max`, `maxComparing`,
