No Programming, No Life

プログラミング関連の話題や雑記

Groovyでクロージャ内部で設定してもらった値を利用する

はじめに

クロージャ(groovy.lang.Closure)を引数にとって、途中の処理を委譲するようなメソッドを定義し、呼び出し時にブロックのように呼び出すことはGroovyでは普通に行われます。
ただ、通常では#callメソッドに渡す引数がクロージャ内で -> の前に列挙した変数として受け取れるといった使い方くらいしかしないと思うのですが、ちょっと工夫することで、色々できることが分かりました。以下実験したソースを載せます。

ソース (動作確認: Groovy Version: 1.7.5 JVM: 1.6.0_20)


localValsという一時変数オブジェクトを生成して、そこへの参照でクロージャのdelegateを書き換えます。すると、クロージャ内部から一時変数オブジェクトのスコープが覗けるようになり、ここで定義してあるmapやthatなどにアクセスできるようになるという仕組み。

実行結果


$ groovy closureLocalValTest.groovy
0
closureLocalValTest@5f7779e3
closureLocalValTest@5f7779e3
closureLocalValTest$1@1167e3a5
This is that!
[count = 1]
[clos = This is that!This is that!This is that!]

まとめ

これは便利ですね。もともとはHTTPBuilderのクロージャ内でどこにも登場してこなかったresponseという変数にいきなりクロージャを設定しだすコードがあったのでどういう風にやるんだろう?という疑問から調べ始めたことです。

上記のサンプルコードでも試していますが、thatやmapのような暗黙変数が渡せるというのは非常に強力ですね。テンプレートメソッドパターンの強化版のようなイメージです。