{ owner.call() }
Groovy では木構造が次の形で表現できるらしい。
def tree = { [:].withDefault{ owner.call() } } def users = tree() users.harold.username = 'hrldcpr' users.yates.username = 'tim' def json = new groovy.json.JsonBuilder(users).toString() assert json == '{"harold":{"username":"hrldcpr"},"yates":{"username":"tim"}}'
これは harold cooper 氏の Python One Liner を
def tree(): return defaultdict(tree)
Tim Yates 氏が Groovy に翻訳して
def tree tree = { -> return [:].withDefault{ tree() } }
id:kiy0taka 氏が One Liner にリファクタリングされてこの形になったもの。
def tree = { [:].withDefault{ owner.call() } }
リンク
- one-line tree in python · GitHub
- A two-line tree in Groovy · GitHub
- A one-line tree in Groovy · GitHub
木構造を表わせることも面白いのだけど(それは別エントリで書く)
Groovy 的には Closure 内でその Closure 自身を参照する方法の意味もあるので単独のエントリにした。
以前は Closure の this は Closure 自身を指したが、JSRになった時点で this は Java と同じように、その Closure が定義されている Object を指すようになったそうだ。
def script = this ;{-> assert script == thisObject assert script == this }()
その後 this の変わりに Closure 自身を返すプロパティは定義されていない。
というわけで現時点(Groovy 1.8.6)では Closure.this == { owner.call() } というイディオムかなと思った。
Groovy では1つ書き方があれば適切かはともかくいくつか書き方があるわけで思いついたものを書いておく。
// 知らない人でも意味を把握しやすいと思った def tree = { [:].withDefault{ owner.call() } } // owner が自由変数なら owner() と書けるのだが、owner はプロパティで次の意味になるので書けない def tree = { [:].withDefault{ getOwner()() } } // 人によっては好みに合うかも def tree = { [:].withDefault(identity{it}) } def tree = { [:].withDefault(with{it}) } // obj.findAll() == obj def tree = { [:].withDefault(findAll()) } def tree = { [:].withDefault(collect()) } // タイプ数は思いついた中で最小 def tree = { [:].withDefault(grep()) } def tree = { [:].withDefault(find()) } // 1回しか呼ばれない memoize // 他に Closure の中で使われているケースがないか探したが見つからなかった (Github 調べ) def tree = { [:].withDefault(memoize()) } // 見た目はシンプルだが memoize と同じで人を惑わせる力がある def tree = { [:].withDefault(rcurry()) } // 演算子で書ければ... def tree = { [:].withDefault(rightShift{it}) } def tree = { [:].withDefault(leftShift{it}) }