Groovy Roadmap

4578d99b560b2a470e05288ef6766ac2?s=47 paulking
September 30, 2020

Groovy Roadmap

This talk looks at the latest features in Groovy 3.0 and the roadmap for 4. Groovy 3 includes the new Parrot parser, some steps on the path towards supporting Java modules and numerous other additions and enhancements. Groovy 4 is at alpha stage and includes further module re-working, bundled type checker extensions, bundled macro methods, a JavaShell, some additional AST transformations, and a myriad of other new miscellaneous features.

4578d99b560b2a470e05288ef6766ac2?s=128

paulking

September 30, 2020
Tweet

Transcript

  1. objectcomputing.com © 2018, Object Computing, Inc. (OCI). All rights reserved.

    No part of these notes may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior, written permission of Object Computing, Inc. (OCI) Groovy 3 Highlights, 4 Roadmap Presented by Dr Paul King © 2020 Object Computing, Inc. (OCI). All rights reserved.
  2. Dr Paul King OCI Groovy Lead V.P. and PMC Chair

    Apache Groovy Author: https://www.manning.com/books/groovy-in-action-second-edition Slides: https://speakerdeck.com/paulk/groovy-roadmap Examples repo: https://github.com/paulk-asert/upcoming-groovy Twitter: @paulk_asert
  3. Groovy Open Collective

  4. In previous episodes …

  5. Groovy by the numbers: Contributors and more

  6. Groovy by the numbers: Highlights Initial release – dynamic companion

    for Java Elvis op, joint compiler, ExpandoMetaClass Multi-assignment, grapes, AST transforms Power asserts, AST browser Command chains, functional enhancements Static nature, modules, indy support Meta-annotations, type checker extensions SAM coercion, DSL & groovysh improvements Closure type inference, traits, JDK8 Android support, many small improvements AST reworking, macros, macro methods Parrot parser (inc lambdas), split packaging
  7. Groovy by the numbers: Enhancements ❖ On-going innovation

  8. Groovy by the numbers: Releases

  9. Groovy by the numbers: Downloads Popular & growing 2016: 23M

    2017: 50M 2018: 103M 2019: 197M 2020h1: 147M currently: approx. 30M+ per month Will be close to ¾ billion downloads by year end
  10. 3.0 highlights

  11. Groovy 3.0 Themes ❖ Parrot parser ❖ Improved copy/paste with

    Java ❖ New syntax/operators ❖ JDK8 minimum and better JDK 9/10 JPMS support ❖ Other improvements ❖ GDK additions ❖ Additional documentation options
  12. Groovy 3.0 Themes ❖ Parrot parser ❖ Improved copy/paste with

    Java ❖ New syntax/operators ❖ JDK8 minimum and better JDK 9/10 JPMS support ❖ Other improvements ❖ GDK additions ❖ Additional documentation options
  13. Groovy 3.0 Themes ❖ Parrot parser ❖ Improved copy/paste with

    Java ❖ New syntax/operators ❖ JDK8 minimum and better JDK 9/10 JPMS support ❖ Other improvements ❖ GDK additions ❖ Additional documentation options (comments in AST/embedded)
  14. New operators: identity/negated variants import groovy.transform.EqualsAndHashCode @EqualsAndHashCode class Creature {

    String type } def cat = new Creature(type: 'cat') def copyCat = cat def lion = new Creature(type: 'cat') assert cat.equals(lion) // Java logical equality assert cat == lion // Groovy shorthand operator assert cat.is(copyCat) // Groovy identity assert cat === copyCat // operator shorthand assert cat !== lion // negated operator shorthand assert 45 !instanceof Date assert 4 !in [1, 3, 5, 7] Also: Elvis assignment operator and safe indexing
  15. Parrot: Java-style Lambdas import static java.util.stream.Collectors.toList (1..10).forEach(e -> { println

    e }) assert (1..10).stream() .filter(e -> e % 2 == 0) .map(e -> e * 2) .collect(toList()) == [4, 8, 12, 16, 20]
  16. Method ref examples: class variants with streams import java.util.stream.Stream import

    static java.util.stream.Collectors.toList // class::staticMethod assert ['1', '2', '3'] == Stream.of(1, 2, 3) .map(String::valueOf) .collect(toList()) // class::instanceMethod assert ['A', 'B', 'C'] == ['a', 'b', 'c'].stream() .map(String::toUpperCase) .collect(toList())
  17. More method ref examples: constructors // normal constructor def r

    = Random::new assert r().nextInt(10) in 0..9 // array constructor is handy when working with various Java libraries, e.g. streams assert [1, 2, 3].stream().toArray().class.name == '[Ljava.lang.Object;' assert [1, 2, 3].stream().toArray(Integer[]::new).class.name == '[Ljava.lang.Integer;' // works with multi-dimensional arrays too def make2d = String[][]::new def tictac = make2d(3, 3) tictac[0] = ['X', 'O', 'X'] tictac[1] = ['X', 'X', 'O'] tictac[2] = ['O', 'X', 'O'] assert tictac*.join().join('\n') == ''' XOX XXO OXO '''.trim()
  18. Method closures & method references @groovy.transform.CompileStatic def method() { Function<String,

    String> lower = String::toLowerCase println 'lower = ' + lower } // lower = MethodRefG$$Lambda$135/0x0000000801376440@5411dd90 def upper = String.&toUpperCase println 'upper = ' + upper // upper = org.codehaus.groovy.runtime.MethodClosure@7aa9e414 def plus = BigInteger.&add def fivePlus = plus.curry(5G).memoizeAtLeast(10) assert fivePlus(3G) == 8G assert fivePlus << 4G == 9G
  19. Parrot: Better Java syntax support • Try with resources •

    Enhanced try with resources (JDK9) • Arbitrary nested code blocks • Local variable var reserved type (JDK10) • Lambda param var (JDK11) • Default methods in interfaces
  20. Parrot: Java-style do…while // classic Java-style do..while loop def count

    = 5 def fact = 1 do { fact *= count-- } while(count > 1) assert fact == 120 Also: enhanced classic for loop and multi-assignment looping
  21. Parrot: Java-style array initialization def primes = new int[] {2,

    3, 5, 7, 11} assert primes.size() == 5 && primes.sum() == 28 assert primes.class.name == '[I' def pets = new String[] {'cat', 'dog'} assert pets.size() == 2 && pets.sum() == 'catdog' assert pets.class.name == '[Ljava.lang.String;' // traditional Groovy alternative still supported String[] groovyBooks = [ 'Groovy in Action', 'Making Java Groovy' ] assert groovyBooks.every{ it.contains('Groovy') }
  22. JPMS: split package redress groovy: groovy.xml.QName groovy.namespace.QName groovy-ant: groovy.util (includes

    AntBuilder) groovy.ant groovy-console: groovy.ui.ConsoleApplet groovy.inspect groovy.console groovy.inspect.swingui groovy.console.ui groovy.ui groovy.console.ui groovy-groovysh: org.codehaus.groovy.tools.shell org.codehaus.groovy.groovysh.tools Deprecated Copied and original deprecated
  23. JPMS: split package redress (cont’d) groovy-jmx: groovy.util.GroovyMBean groovy.jmx groovy-nio: org.codehaus.groovy.runtime.WritablePath

    org.apache.groovy.nio.runtime org.codehaus.groovy.runtime.NioGroovyMethods org.apache.groovy.nio.extensions.NioExtensions groovy-swing (SwingBuilder only produces new classes): org.codehaus.groovy.binding org.apache.groovy.swing.binding org.codehaus.groovy.runtime org.apache.groovy.swing.extensions groovy.model groovy.swing.model groovy.inspect.swingui org.apache.groovy.swing.table
  24. JPMS: split package redress (cont’d) groovy-test: org.codehaus.groovy.runtime.ScriptTestAdapter org.apache.groovy.test groovy.transform.NotYetImplemented groovy.test

    groovy.util (includes GroovyTestCase) groovy.test groovy.lang groovy.test groovy-xml: groovy.util (includes XmlParser & XmlSlurper) groovy.xml org.codehaus.groovy.tools.xml.DomToGroovy org.apache.groovy.xml.tools • Migrate over lifetime of Groovy 3 with some caveats • Don’t mix and match old and new versions of classes • Deprecated classes removed in 4.0 to make jars module friendly
  25. JPMS: remove illegal access warnings

  26. GDK improvements

  27. 4.0 Roadmap

  28. Important naming/structuring changes Maven coordinate change org.codehaus.groovy org.apache.groovy Legacy package

    removal groovy-xml: groovy.util (includes XmlParser & XmlSlurper) groovy.xml Module changes for groovy-all groovy-testng: was included, now optional groovy-yaml: was optional, now included
  29. Legacy consolidation Old parser removal Antlr 2 Antlr4 Classic bytecode

    generation removal Classic Indy
  30. Built-in type checkers: regex checker import groovy.transform.TypeChecked @TypeChecked(extensions = 'groovy.typecheckers.RegexChecker')

    def whenIs2020Over() { def newYearsEve = '2020-12-31' def matcher = newYearsEve =~ /(\d{4})-(\d{1,2})-(\d{1,2}/ } def newYearsEve = '2020-12-31' def matcher = newYearsEve =~ /(\d{4})-(\d{1,2})-(\d{1,2}/ // PatternSyntaxException
  31. Built-in type checkers: regex checker ~/\w{3/ // missing closing repetition

    quantifier brace ~"(.)o(.*" // missing closing group bracket Pattern.compile(/?/) // dangling meta character '?' (Java longhand) 'foobar' =~ /f[o]{2/ // missing closing repetition quantifier brace 'foobar' ==~ /(foo/ // missing closing group bracket Pattern.matches(/?/, 'foo') // dangling meta character '?' (Java longhand) def m = 'foobar' =~ /(...)(...)/ assert m[0][1] == 'foo' // okay assert m[0][3] // type error: only two groups in regex Pattern p = Pattern.compile('(...)(...)') Matcher m = p.matcher('foobar') assert m.find() assert m.group(1) == 'foo' // okay assert m.group(3) // type error: only two groups in regex
  32. Built-in macro methods def num = 42 def list =

    [1 ,2, 3] def range = 0..5 def string = 'foo' println NV(num, list, range, string) println NVI(range) println NVD(range)
  33. JavaShell import org.apache.groovy.util.JavaShell def opts = ['--enable-preview', '--release', '14'] def

    src = 'record Coord(int x, int y) {}' Class coordClass = new JavaShell().compile('Coord', opts, src) assert coordClass.newInstance(5, 10).toString() == 'Coord[x=5, y=10]'
  34. @POJO 3 true Point(x:1, y:3) Point(x:2, y:2) Point(x:3, y:1) 2

  35. Groovy 2.5: AST Transforms: @Immutable becomes meta-annotation @Immutable class Point

    { int x, y } @ToString(includeSuperProperties = true, cache = true) @EqualsAndHashCode(cache = true) @ImmutableBase @ImmutableOptions @PropertyOptions(propertyHandler = ImmutablePropertyHandler) @TupleConstructor(defaults = false) @MapConstructor(noArg = true, includeSuperProperties = true, includeFields = true) @KnownImmutable class Point { int x, y }
  36. Groovy 4.0: AST Transforms: @RecordType meta-annotation @RecordType class Point {

    int x, y } @RecordBase @ToString(cache = true, includeNames = true) @EqualsAndHashCode(cache = true, useCanEqual = false) @ImmutableOptions @PropertyOptions(propertyHandler = ImmutablePropertyHandler) @TupleConstructor(defaults = false) @MapConstructor @KnownImmutable @POJO class Point { int x, y }
  37. @RecordType Produces a class that: • is implicitly final •

    has a private final field firstName with an accessor method firstName(); ditto for lastName • has a default Cyclist(String, String) constructor • has a default serialVersionUID of 0L • has implicit toString(), equals() and hashCode() methods
  38. groovy-contracts module Design-by-contract

  39. Still being explored for future Groovy versions • Switch expressions

    • Additional destructuring/pattern matching within switch case expressions • Language integrated query • Smarter type checking: non-null, pure • Module definitions in Groovy
  40. Join us: groovy.apache.org

  41. objectcomputing.com © 2018, Object Computing, Inc. (OCI). All rights reserved.

    42 CONNECT WITH US 1+ (314) 579-0066 @objectcomputing objectcomputing.com THANK YOU Find me on twitter @paulk_asert © 2020 Object Computing, Inc. (OCI). All rights reserved.