Groovyのメジャーバージョンが3になっていた

Chocolateyでインストールしたパッケージを更新すると、Groovyがv3.0.0になっていた。

プレビュー版が出たのは2018年みたい

GitHubのReleaseを見ると、v3.0.0は2020/2/7、v3.0.1が2/14にリリースされており、公式ページからはv3.0.1がダウンロードできた。

変更点がリリースノートに書いてあったので、ざっくり見てみる。

v3.0.0のドキュメントはこちら

Groovy 3での変更内容

パーサーの変更

Parrot Parserという新しいパーサーに変更された。

対応するJava構文の追加

do/whileループやJavaスタイルの配列の初期化、Java7で追加されたtry-with-resources構文、Java8で追加されたLambda構文、メソッド参照、インターフェースのデフォルトメソッドなどに対応。

staticでない内部クラスのインスタンス化なんてのもあった、今までできなかったのね。

Lambda構文は、動的Groovyの場合は同等なクロージャになる模様。 (e) → { println e }{e → println e} となる。静的Groovyではネイティブラムダ式をサポートするとのこと。

メソッド参照も、動的Groovyなら .& 演算子によるメソッド参照クロージャとなる模様。 String::toUpperCaseString.&toUpperCase となる。

演算子などの追加
  • in 演算子instanceof 演算子の否定形として、 !in および !instanceof が追加。
  • エルビス代入演算子 ?= の追加。代入しようとした変数がbooleanに変換してfalseとなる場合のみ代入される模様。 name = name ?: 'Anonymous' を、 name ?= 'Anonymous' と書ける。
  • アイデンティティ比較演算子 === および否定形の !== の追加。Java== 演算子にあたる is() メソッドがあったが、その演算子版。
  • 安全なインデックス操作 ?[] の追加。操作対象がnullの場合、値の取得や代入をしても例外が発生しなくなる模様。 Safe indexing という名称だが、捜査対象がMapの場合、map?['key'] のようにも使用できる。
  • Java10の var の導入。GroovyをJDK8で動かしていても使用可能。
  • ネストされたコードブロックに対応。ただし、記述位置によってはクロージャ宣言とみなされる場合もあるので注意。
Parrot Parserの無効化

起動オプションとして -Dgroovy.antlr4=falseJAVA_OPTS に設定することで、Parrot Parserを無効化し、従来のパーサー(Indy Parser)を有効にできる模様。

ただし、Indy ParserはGroovy 4で削除予定なので、非推奨とのこと。

GDKの改善

Javaクラスの拡張メソッドが、約80追加されたとのこと。

その他の改善

  • 組み込みGroovydoc。埋め込んだGroovydocは、AST変換などで参照可能とか。さらに、 /**@ で開始したGroovydocはクラスファイルに埋め込まれ、リフレクションで参照できる模様。
  • JSR308の改善。

パッケージ変更の分割

Java9のモジュールに準拠していないため、Groovy 2.x や 3.0 をJDK9以降で動作させるためには、Groovyをモジュールパスではなくクラスパスに追加する必要がある。

Groovy 4ではモジュールに完全準拠とするため、Groovy 3では移行準備として一部のクラスのパッケージを変更し、古いパッケージ配下には非推奨としてクラスをコピーした模様。

Groovy 4では非推奨クラスを利用するとコンパイルできなくなる可能性があるため、Groovy 3の間に新しいパッケージに移行してね、とのこと。

対象となるパッケージはリリースノートに記載あり。

その他の重大な変更

JDK13以降で動作させる場合、 CharSequence#stripIndent() ではなく CharSequence#stripIndent(true) を使ってね、とのこと。

JiraはこちらJavadocは(こちら)https://docs.groovy-lang.org/docs/groovy-3.0.0/html/groovy-jdk/java/lang/CharSequence.html

振り返り

Google翻訳したのを抜粋しただけなのはナイショ

AltJavaといえばすっかりKotlinかScalaな昨今、GradleもDSLをKotlinで書けるようになったりする中でのメジャーバージョンアップ。

対応するJavaの構文が増え、Java8以降は難しくなってしまった「拡張子をjavaからgroovyに変えれば動かせる」というソースコードレベルでの互換性が帰ってきた印象。

動的言語から強力な型推論の静的言語へのトレンドの流れに追従すべく、静的コンパイルできるようになったりしたものの、ここ数年はJava本体の成長が著しく、またSpring Bootのような生産性の高いフレームワークが定着したこともあり、Javaを直接書けばいい、という状況になっている気がする。

そうした中でのJavaソースとの互換性の向上は、単独のプログラミング言語としてではなく、メインJava、タッチGroovy、といったすみ分けを狙ったものなのでは、と感じた。

余談

Gradle Kotlin DSL入門 - Qiita より。

主観的な話で申し訳ないですが、Gradleのビルドスクリプト用途以外でGroovyを用いているという話を聞いたことが無いため、「Gradleのビルドスクリプト専用言語」の様な形で使っている人が大半でしょう。

おおう...

プロダクトコードとしては使っていないが、週1回は小人さんスクリプトなりSpockなりGebなりでGroovyをいじっている身としてはショック。

昔はNTTソフトウェアでGroovy/Grailsを推進していた時期があったようなんだが、今はどうなんだろう?

PDF2つの著者の方は、プログラミングGROOVYの著者の方だった。