G*Magazine Vol.8

Groovy臨機応変(第四回)〜Groovy 2.4の新機能〜

今回は、Groovy 2.4の新機能を、現時点で公開されているGroovy 2.4 beta4までのリリースノートから抜粋して紹介します。

正式リリースまでにはさらに機能が追加されるでしょうから、正確にはGroovy 2.4の機能の一部ということになります。

(参考リンク)

(追記)

出稿タイミングの都合で本記事は2.4最終のリリースには対応していません。2.4最終版のリリースノートについては以下を参照ください。

Android対応

Groovy 2.4ではAndroidアプリケーションを開発できるようになりました。GroovyをAndroidで動作させるための試みは過去にもいくつかありましたが、今回はパッチなどではなく、公式のGroovyメインラインで対応されているのが特徴です。基本的には、Static Compile配下で動作する機能を使用します。このAndroid対応に合せてSwissKnife、grooid-toolsなどの開発用ライブラリもでてきています。(GROOVY-6861)

(参考リンク)

ライブラリの拡張

toUnique(),toSorted()の追加。

Listなど、Iterableなコレクションに対するGDKメソッドの追加です。(GROOVY-6945)

従来からJDKに存在したList#sort()は破壊的操作でしたが、toSortedはイミュータブルな、「ソートしたものを返す操作」です。また、toUnique()も同様に、重複要素を削除したものを返し、もとのコレクションを変更しません。またこれらはIterableなコレクション一般もしくは配列に対する適用も可能です。

Java8では、コレクションに対するsortメソッドが新規に追加されましたが、GDKのsortと名前が被るので、混乱を避けるためにという意味合いもあるようです。

例)

  assert [4,1,2,2,3,3,4].toUnique() == [4,1,2,3]
  assert [4,1,2,2,3,3,4].toSorted() == [1,2,2,3,3,4,4]

init(), dropRight()、takeRight()の追加

Scalaの同名メソッドの導入です。(GROOVY-6867)

メソッドの説明を以下に示します。

メソッド 意味 例(a = [1,2,3]のとき)
init() 末尾以外。 assert a.init()==[1,2]
dropRight() 末尾の指定個数を削除 assert a.dropRight(2) == [1]
takeRight() 末尾の指定個数を取得 assert a.takeRight(2) == [2,3]

System.currentTimeSecond()の追加

エポックからの経過「秒数」を返すメソッドSystem.currentTimeSecond()が追加されました。JDKのSystem.currentTimeMillisの1000分の1を返します。(GROOVY-6294)

groovy:000> System.currentTimeSeconds()
===> 1416000159
groovy:000> System.currentTimeMillis()
===> 1416000167901

Groovyshの拡張

groovyshが地道に拡張されています。

  • groovyshではメソッド補完が効くようになっているのですが、補完候補の表示にANSIのエスケープシーケンスを使って、インスタンスメソッドはボールド表示、staticメソッドやsuperクラスのメソッドは通常表示となるようになりました。(GROOVY-6563)
  • 以前のGroovyshでは、行の単位でGroovyの式を評価するため、シェル変数以外の型宣言した変数を行をまたがって使用することができませんでしたが、可能となります。(GROOVY-6623)

(例) 以下が可能となる。

   String s = "abc"
   println s
  • groovyshの起動時に、-eオプションで任意のGroovyコードを実行できるようになりました。また、コマンドラインに指定したgroovyスクリプトを読み込むようになりました。

(例)

   > cat test.groovy
   println "hello"
   > groovysh -e 'println 1+1' test.groovy
   Groovy Shell (2.4.0-beta-3, JVM: 1.8.0_25)
   Type ':help' or ':h' for help.
   --------------------------------------------------------------------------------------------------------------------------------
   groovy:000> println 1+1
   2
   ===> null
   groovy:000> :load test.groovy
   hello
   ===> null
   groovy:000>

SelfTypeアノテーション

トレイトの定義において、そのトレイトを実装するクラスが実装していなけれならないクラスもしくはインターフェースを@SelfTypeというアノテーションで指定できるようになりました。SelfTypeアノテーションによって、以下の利点が得られるようになります。

  • トレイトが、どんなクラス・インターフェース(およびそのサブクラス)に注入可能であるかを制約する。この制約を満していないクラスがそのトレイトを実装しようとするとコンパイルエラーとなる。
  • その結果、トレイトで定義するメソッド中で、使用できるはずのメソッド群が静的に予期できるようになり、実装クラスのメソッドを自由に呼び出せる。
  • トレイトのメソッド中でのthisの型が静的に確定するので、thisを他のメソッドに渡す際などに静的型チェック可能になる。

要は、トレイトと静的Groovy(@CompileSattic, @TypeChecked)との相性がより高まったということです。

コード例は以下のとおり。

import groovy.transform.*
import java.util.concurrent.CopyOnWriteArrayList

@CompileStatic
@SelfType(List)
trait LispLikeList {
    Object car() {
        first()
    }
    Collection cdr() {
        tail()
    }
}

class LispLikeCoWList<E> extends CopyOnWriteArrayList<E> implements LispLikeList {
    LispLikeCoWList(list) {
        super(list)
    }
}

def list1 = new LispLikeCoWList([1,2,3])
assert list1.car() == 1
assert list1.cdr() == [2,3]

(参考リンク)

Macro Groovy

その他、AST変換におけるASTの生成を簡易に書けるようにする「Macro Groovy」機能の、Groovy公式機能としての導入が検討されています。この過程で、ASTの木のパターンマッチングサポートも検討されているようです。

(参考リンク)

(注) 最終的にはMacro Groovyは2.4での導入は見送られました

G*Magazine Vol.8

Groovy臨機応変(第三回)〜Groovy 2.3の新機能〜
Groovy臨機応変(第四回)〜Groovy 2.4の新機能〜
Gradleプラグイン探訪
Grails Plugin探訪 〜第9回 CodeNarc plugin〜
リリース情報 2014.11.29
G*Magazine Vol.8- 第6章