URL: https://linuxfr.org/users/yboy360/journaux/sortie-de-groovy-4-0-0 Title: Sortie de Groovy 4.0.0 Authors: YBoy360 Date: 2022年01月31日T14:50:01+01:00 License: CC By-SA Tags: groovy Score: 11 [Groovy](https://groovy-lang.org/) est un langage typé optionnellement, dynamique, pouvant supporter la compilation statique. Il utilise la plateforme Java, il permet entre autres la composition de scripts portables (Windows, Linux, Mac avec gestion de dépendances), tout en disposant d’une syntaxe simple et abordable. Groovy simplifie également la création de DSL, la méta-programmation, la programmation fonctionnelle et la rédaction de tests. # Amélioration de l’existant # ## Utilisation exclusive du Parrot parser ## Il s'agit d'une version optimisée d'[ANTLR4](https://www.antlr.org/) en lieu et place de l’ancien parseur basé sur Antlr2, ce qui permet plus de flexibilité et rend la syntaxe compatible avec celle de Java (c.f. [Parrot Parser](https://groovy-lang.org/releasenotes/groovy-3.0.html#Groovy3.0releasenotes-Parrot)). ## Compatibilité à partir du Jdk 7+ ## L’un des avantages de Groovy étant le support d’ ancienne version du Jdk. # Nouvelles fonctionnalités (non-incubating) # Voir [New Features](https://groovy-lang.org/releasenotes/groovy-4.0.html#Groovy4.0-new) ## Switch expressions ## Similaire à ce que propose Java, sauf que la branche default n’est pas obligatoire, dans ce cas null est retourné. ```groovy def result = switch(i) { case 0 -> 'zero' case 1 -> 'one' case 2 -> 'two' default -> throw new IllegalStateException('unknown number') } ``` On peut toujours utiliser les anciennes expressions ```groovy def items = [10, -1, 5, null, 41, 3.5f, 38, 99, new Coord(x: 4, y: 5), 'foo'] def result = items.collect { a -> switch(a) { case null -> 'null' case 5 -> 'five' case new Custom() -> 'custom' case 0..15 -> 'range' case [37, 41, 43] -> 'prime' case Float -> 'float' case { it instanceof Number && it % 2 == 0 } -> 'even' case Coord -> a.with { "x: $x, y: $y" } case ~/../ -> 'two chars' default -> 'none of the above' } } ``` Pratique pour le pattern "visitor" : ```groovy import groovy.transform.Immutable interface Expr { } @Immutable class IntExpr implements Expr { int i } @Immutable class NegExpr implements Expr { Expr n } @Immutable class AddExpr implements Expr { Expr left, right } @Immutable class MulExpr implements Expr { Expr left, right } int eval(Expr e) { e.with { switch(it) { case IntExpr -> i case NegExpr -> -eval(n) case AddExpr -> eval(left) + eval(right) case MulExpr -> eval(left) * eval(right) default -> throw new IllegalStateException() } } } @Newify(pattern=".*Expr") def test() { def exprs = [ IntExpr(4), NegExpr(IntExpr(4)), AddExpr(IntExpr(4), MulExpr(IntExpr(3), IntExpr(2))), // 4 + (3*2) MulExpr(IntExpr(4), AddExpr(IntExpr(3), IntExpr(2))) // 4 * (3+2) ] assert exprs.collect { eval(it) } == [4, -4, 10, 20] } test() ``` ## Sealed Class ## La [GEP](https://groovy.apache.org/wiki/GEP-13.html) correspondante. ## Record-like classes ## La définition dans la langue de Shakespeare> model plain data aggregates with less ceremony ```groovy record Cyclist(String firstName, String lastName) { } def richie = new Cyclist('Richie', 'Porte') ``` ## Built-in type checkers ## Test de la validité des données pendant la phase de compilation, pour le moment limité aux expressions régulières : ```groovy @TypeChecked(extensions = 'groovy.typecheckers.RegexChecker') def whenIs2020Over() { def newYearsEve = '2020-12-31' def matcher = newYearsEve =~ /(\d{4})-(\d{1,2})-(\d{1,2}/ } ``` Conduit à une erreur à la compilation : ```bash 1 compilation error: [Static type checking] - Bad regex: Unclosed group near index 26 (\d{4})-(\d{1,2})-(\d{1,2} at line: 6, column: 19 ``` ## Built-in macro methods ## ```groovy println NV(num, list, range, string) ``` Affiche `num=42, list=[1, 2, 3], range=[0, 1, 2, 3, 4, 5], string=foo`. Le nom de la variable s'affiche avec son contenu. ```groovy println NVI(range) ``` Affiche `range=0..5`, c'est l'expression qui définit le range qui est affichée. NVD est une macro qui affiche le `dump()`. # Autres améliorations # ## Amélioration des performances liées à la gestion des GString ## * Mise en cache du résultat de `toString()` lorsque cela s'avère sûr ; * Ajout de la méthode `freeze()` pour forcer cette mise en cache. ## Enhanced Ranges ## Actuellement les "ranges" n'étaient que inclusifs (`3..5`) ou ouverts à droite (`4..<10`), depuis Groovy 4, les "ranges" peuvent être clos à gauche ou à droite. ## Décimal sans zéro en en-tête ## Maintenant le code suivant est valide : ```groovy def half = .5 def otherHalf = 0.5 // leading zero remains supported double third = .333d float quarter = .25f def fractions = [.1, .2, .3] ``` Pour les ranges, à droite, il faudra cependant conserver le zéro. # Autres nouveautés en "incubation" # ## Groovy Contracts ## Ajout d'annotation pour la programmation par contrats : ```groovy import groovy.contracts.* @Invariant({ speed()>= 0 }) class Rocket { int speed = 0 boolean started = true @Requires({ isStarted() }) @Ensures({ old.speed < speed }) def accelerate(inc) { speed += inc } def isStarted() { started } def speed() { speed } } def r = new Rocket() r.accelerate(5) ``` ## Groovy-Integrated Query ## Requête de type SQL sur les objets en mémoire (lists, maps, JSON ou XML) : ```groovy assert GQ { from p in json.prices join c in json.vitC on c.name == p.name orderby c.conc / p.price in desc limit 2 select p.name }.toList() == ['Kakuda plum', 'Kiwifruit'] ``` Voila, le nouveau parseur permettra de plus aisément étendre les fonctionnalités de ce langage, qui profite de l'infrastructure du monde Java pour rendre celui-ci plus accessible.

AltStyle によって変換されたページ (->オリジナル) /