はじめに
クロージャって便利ですよね。私はクロージャと出会ったことで処理とイテレーションの分離の考え方を身に付けることができました。さて、今回はそのクロージャ生成時のパラメータ指定についてです。普段何気なく使ってしまっているクロージャですが、パラメータの受け渡し方などちょっとだけ奥が深いところがあった*1のでまとめてみました。間違いなどがありましたらご指摘ください。
(動作確認: Groovy Version: 1.8.0-rc-1 JVM: 1.6.0_22)
パターン1:パラメータ省略
def clos = { ... }
パラメータを省略した場合は第1引数を暗黙変数「it」で受け取れる。
使用例
def map = [a:1, b:2, c:3] map.each{ println "${it.key}/${it.value}" // key/value形式で出力 }
パターン2:パラメータ指定
def clos = { arg1, arg2 -> ... }
クロージャを受け取るメソッドが望む分だけパラメータを指定してクロージャを生成する方法。
使用例
def map = [a:1, b:2, c:3] map.each{ k, v -> println "$k/$v" // key/value形式で出力 }
また複数パラメータを受け取る場合でも、少なめに受け取るように省略して宣言しても問題ない。
たとえば、String#eachLine()メソッドはクロージャに
- 第1パラメータ:改行で区切った各行の文字列
- 第2パラメータ:行番号(0オリジン) *2
というパラメータを渡すように実装されているようですが、第2パラメータは受け取らなくてもよいようです。
使用例
// 第1引数のみ受け取る '''aaa bbb ccc'''.eachLine{ line -> println line // 行の内容を出力 } // 第2引数も受け取る '''aaa bbb ccc'''.eachLine{ line, no -> println "$no: $line" // 「行番号: 行の内容」 の形式で出力 }
パターン3:パラメータなし
def clos = { -> ... }
パターン3はあまり見ない形かもしれない。-> の左側を空にすることで明示的にパラメータがないことを示すことができる。
よって、パターン1と同じ感覚で使おうとするとエラーになる。間違ってパラメータを渡してくるようなメソッドにクロージャが渡された場合はエラーとなるので便利です。
使用例(エラーとなる)
def map = [a:1, b:2, c:3] map.each{ -> // エラー発生 => #each() はクロージャにパラメータを渡してきてしまうため println 'パラメータなんて必要ないんだからねっ!' }
なので、「引数は受け取らないよ!絶対受け取らないんだからねっ!」という時に使うと良い。
使用例
5.times { no -> Thread.start{ -> // スレッドだからパラメータはいらないよ! int sleepTime = 1000 * Math.random() as int sleep(sleepTime) println "I'm No.${no} thread (slept ${sleepTime}ms)." } } // 結果 // I'm No.0 thread (slept 130ms). // I'm No.2 thread (slept 472ms). // I'm No.1 thread (slept 552ms). // I'm No.4 thread (slept 642ms). // I'm No.3 thread (slept 997ms).
まとめ
ということで、パターン別にまとめてみましたがいかがでしたでしょうか。クロージャはGroovyの中でも奥が深い部分でもありますが、規則を覚えて使いこなしていけばこれほど便利な機能はないと思います。
関連がありそうな記事
Groovyでクロージャを期待するメソッド呼び出し時の挙動について - No Programming, No Life
Groovyでクロージャ内部で設定してもらった値を利用する - No Programming, No Life
Groovyでクロージャによって、渡す引数を変化させるメソッド - No Programming, No Life
GroovyでメソッドをMethodClosureとして取得する - No Programming, No Life
Groovyでクロージャを宣言する - No Programming, No Life
Groovyで処理とイテレーションの分離 - No Programming, No Life