No Programming, No Life

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

Groovyでリスト内包表記(その2)

はじめに

Groovyでリスト内包表記 - No Programming, No Lifeの記事にfujwaraさんより、Scalaでは以下のようにできるけど、Groovyではどうやればできるの?とコメントをいただきました。

手始めにGroovy流に書いてみる


うん、ほんとはこれでいいと思うんだけど…

頑張ってみる

これは、前回のジェネレータが複数だったり、フィルターが複数ある場合は面倒なのでやってませんという内容そのまんまなのですが、せっかくなのでトライしてみました。

解説

withComprehensions

GParsのwithPoolみたいな感じで、withComprehensionsで囲んだ中だけでリスト内包表記が使えるようにしてみました。

ListComprehensions.withComprehensions {
  // ここの中だけ、リスト内包表記が使える
}
内包表記

Scalaのfor式をなるべく頑張って模倣してみました。

Scala Groovyで頑張る
x <- xs 'x' << xs
if x > 3 'if' << { x > 3}
yield ... .yield{ ... }
実行
['x' << (0..10).toList(), 'if' << { x % 2 == 0}].yield{ x }

のように書くと、[0, 2, 4, 6, 8, 10] のリストが結果になります。

  • 'if' 以外に << したものがジェネレータになります。
    • いくつでも指定できます。
    • 指定した順番にネストしてジェネレートされます。
    • 指定した文字で、それぞれフィルタとイールドの中で参照できます。
  • 'if' に << したものがフィルタになります。いくつでも指定できます。
  • .yield{ } で結果を選択&整形します。

まだできないこと

リスト内包表記のネスト。これに関しては構造をちょっと考えないといけない。

まとめ

ということで、なんとなくそれっぽくできましたが、決して処理速度が早くなってるってわけでもないと思うので無理に使わなくても…と思ってしまう私なのでした。yieldのあたりがもう一工夫できそうですね。Scala風にyieldを使うんじゃなくてHaskellとかPythonのように | の左側に置いてみるとか。