BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース ApacheがGroovy 2.5とGroovy 3.0プレビュー版をリリース

ApacheがGroovy 2.5とGroovy 3.0プレビュー版をリリース

原文(投稿日:2018/07/12)へのリンク

Apache Foundationは先頃、Groovyのバージョン2.5をリリースした。次のような新機能を備えている。

  • AST変換の改善
  • 新たにマクロをサポート
  • その他の改善

Groovy 2.5にはJDK 7が必要である。また、JDK 9以降では軽度な警告が表示されるが、無視しても問題ない。

最近ではKotlinなど他のJVM言語に注目が集まっているが、Groovyも依然として大きな成長を遂げている。GroovyのコミッタであるOCIプリンシパルソフトウェアエンジニアのPaul King博士は、先日のウェビナで次のように述べている。

ダウンロード数で見れば、GroovyはJVM上ではいまだJavaに次いで2番目に人気のある言語であり、その数も増え続けています。今年の第1四半期には、昨年同時期の2倍に当たる9,000万件のダウンロードがありました。この数字が示すように、Groovyはいまだ多くの関心を集めているのです。

さらにGroovyは、過去12ヶ月間に30人の新しいコミッタを獲得している。

AST変換 – アノテーション

下の図に示すようにバージョン2.5では、既存のAST変換の多くが一貫性向上を目的として改善されるとともに、11の新たな変換が追加されている。追加された変換はGroovy 3.0のためのものだが、GAリリースよりも先に提供される可能性がある。

AST変換 – マクロ

前章で述べたように、Groovyには多数の組み込みAST変換が用意されている。独自のカスタム変換を開発することも可能だが、これまではGroovyの構文構造の内部表現に関する知識が必要であった。

バージョン2.5の新しいマクロ機能により、構文構造の内部表現を知る必要はなくなる。リリースノートの定義によれば、

マクロによって、コンパイル時のメタプログラミング拡張を開発するときに、コンパイラの内部表現ではなく、Groovyの構文を直接使用できるようになります。これによって変換の開発が、Groobyコンパイラのグルだけでなく、すべてのGroovyプログラマのものになりました。

@getinfo()メソッドを生成する@infoという変換を開発する場合を例にしよう。バージョン2.5より前は、次のようなコードを記述する必要があった。

    
...
def clazz = new MethodCallExpression(new VariableExpression("this"), "getClass", EMPTY_ARGUMENTS)
def body = new ExpressionStatement(new MethodCallExpression(clazz, "getName", EMPTY_ARGUMENTS))
classNode.addMethod('getInfo', ACC_PUBLIC, STRING_TYPE, EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body)
...
    

マクロを使えば、上のコードの最初の2行を次のように書き換えることができる。

    
def body = macro(true) {
    getClass().name
    }
    

詳細はリリースノートに記載されている。

Groovy 3.0

Groovy 3.0.0-alpha-3が6月末より公開されており、ベータ版が今年後半、リリース候補が2019年初頭に予定されている。

Groovy 3.0の利用にはJDK 8が必要で、JDK 9以降のサポートも改善されている。Parrot Parserと呼ばれる新たなパーザが、新しいGroovy構文をサポートする重要な新機能になる。

King博士がこの最新リリースについて、InfoQに説明してくれた。

InfoQ: デフォルトのIndyパーザとGroovy 3.0の新しいParrotパーザの違いについて説明して頂けますか?

Paul King: Groovyパーザの“Indy”と“Parrot”のフレーバについて説明するには、少し詳しい知識が必要になります。Groovyのパーザは、複数のフェーズで動作します。前半のフェーズではソースコードを取り込んで、それを内部抽象構文木(AST)表現に変換します。後半はASTをバイトコードに変換します。変換されたバイトコードは、Javaコンパイラが生成するバイトコードとほぼ同じ方法で、JVM上で実行されます。

“Parrot”パーザについて説明するためには、Groovy 3で完全に書き換えられたコンパイラの初期ステージについて説明しなければなりません。この部分は、近年普及しているテクノロジを採用して、より柔軟になるように再設計されています。この開発によってGroovyは、発展の容易な、絶好のポジションに立つことになります。すなわち、Javaとの“カット・アンド・ペースト”互換性のためにJavaの変更に対応することと、Groovyネイティブな変更を両立させることが可能になるのです。

まず“Indy”でのサポートについて説明しましょう。問題になるのは、コンパイラの後半ステージで生成されるバイトコードの種類です。Groovyのバージョン2.0から2.5では、“classic”バージョンと“Indy”バージョンのGroovyバイトコードの生成をサポートしています。Indyバージョンでは、JDK 7で導入された“INvoke DYnamic”バイトコード命令を使用します。invoke dynamicバイトコード命令は、さまざまな理由からJVMに追加されたものですが、Groovyのような動的言語のパフォーマンス改善が特にユースケースとして考えられていました。このバイトコードをサポートしたJDKの初期バージョンには少しバグがあって、一部のパフォーマンスは向上したものの、ハンドコードしたプリミティブの最適化など他の部分では、以前のバイトコード命令を使った方が依然として高速だったのです。このような理由から、私たちは両方のバリエーションをサポートしてきました。Groovy 3コンパイラのアルファ版でも両方のバージョンをサポートしていますが、Indyバリアントをデフォルトにして、他の最適化も部分的に取り込み、古いクラッシックフレーバを完全に取り除く作業が進行中です。

InfoQ: Groovyでは多数の組み込みAST変換が利用可能ですが、開発者が独自のカスタムAST変換を開発するユースケースとしては、特にどのようなものがあるのでしょう?

King: AST変換を使用するユースケースはたくさんあります。ボイラプレートコードの排除や、共通デザインパターンとコードスタイルの取り込み、宣言型プログラミングのサポート、などです。Groovyにたくさんの便利なAST変換がバンドルされているのは間違いありませんが、私たちがバンドルしようと努めているのは、一般的に適用可能と思われるような変換です。ですから、開発者が自分自身で作成する方が便利だと、明らかに思われる場合もあります。

  • 必要な変換が本質的に特殊目的である場合。そのような変換がGroovyに組み込まれることはありません。
  • 標準で提供されている変換の動作が気に入らず、動作のカスタマイズにアノテーション属性が使用できない場合。この場合は、選択肢がいくつかあります。メタアノテーション機能を使用してアノテーションの組み合わせをまとめて“バンドル”し、Springアノテーションなどと組み合わせる方法はそのひとつです。それでニーズを満たすことができなければ、自分自身で書くというのは適切な選択です。
  • 自身のドメインに固有のDSLを記述して、アノテーションをそのDSLに組み込みたい場合。DSLの記述時には、これが唯一の選択肢になります。
  • 独自のフレームワークを記述して、ユーザのコーディングがシンプルになるような、強力なアノテーションを提供したい場合。

AST変換をフレームワークで使用した例を紹介しましょう。Grailsには、grails-coreだけで約20のAST変換があります。Griffonにもたくさん追加されています。MicronautのAST変換処理は、100アノテーションを越える集約を処理することができます。

InfoQ: 新しいマクロ機能を使うことで、より多くの開発者が独自のカスタムAST変換を記述できるようになるのでしょうか?

King: マクロに慣れるまで、ある程度の時間が掛かるのは事実です。ですが、いろいろな例が現れれば、雪玉効果(snowball effect)のあることも珍しくありません。少し待たなくてはならないでしょう。いずれにせよ、Groovyのコードベースには、さまざまなものが追加されています。

InfoQ: 新しいJDKのリリース方法は、Groovy開発に何らかの形で影響したのでしょうか?

King: そうですね、リリースのペースが速くなることには確かによいことなのですが、多くのオープンソースプロジェクトにとっては、それに追いつくのが大変だという面もあります。Groovyでは、理にかなったものであれば、できる限り多くのJDKバージョンに合わせていきますが、バージョンが多くなるほど、実現は難しくなります。潜在的に作業が増えるという意味だけでなく、他のオープンソースにも依存しているので、互換性を維持するためには最新の状態を保ち、バージョン間で十分に一貫性を持った開発を行なう必要があるのです。おそらく、JPMSの影響が大きいと思います。JPMSの変更のいくつかは、Groovy 3.0のGAリリースまでに修正すべきToDoリストに残ったままです。

InfoQ: Groovy 3.0でJDK 11をサポートする計画はありますか?

King: 非公式ですが、すでにJDK 11をサポートしています。ビルドやテストスイートは、先日のJDK11 EAビルドで正常に動作します。Javaソースコードの互換性という面では、ローカル変数のラムダパラメータのdefのエイリアスとしてvarをすでにサポートしています(JEP 323)から、JDK 8上であっても、Groovyで次のようなラムダを定義することが可能です。

    
(var x, var y) -> x.process(y)
    

InfoQ: Groovy 2.5と近々登場するGroovy 3.0に関して、他に読者に伝えておきたいことはありますか?

King: Groovyの採用が増え続けていることを大変嬉しく思っていますし、将来のバージョンで導入したいことがたくさんあります。ロードマップ上に計画されているすべての機能の完成と、いくつかの大きなバグ修正作業に対する、Groovyコミュニティの忍耐と協力にも感謝しています。

エンジニアリング上の課題がいくつか残っていますが、Groovyにはすばらしい未来があります。コントリビューションの申し出や、メーリングリストでの議論に参加してくださる方々は大歓迎です。

InfoQ: あなたの現在の役職は何ですか、つまり、毎日どのようなことをしているのでしょうか?

King: メーリングリストや他のフォーラムでの議論への参加、コードベースへのコントリビューション、Groovyを使用する他のプロジェクトのサポートなど、多くの時間をGroovyの作業に使っています。

リソース

 
 

この記事を評価

採用ステージ
スタイル
 
 

この記事に星をつける

おすすめ度
スタイル

BT