といっても全然最近ではないのですが。 🙂
前のエントリでも書きましたが恥ずかしながら Ruby とかやったことがなく、実はいつだったか Ruby のソースをみたときに処理は分かれど、ライブラリの中身がどうやっているのか理解できず、ショックで引退を考えたことがありましたので最近ようやく勉強を始めました(笑)
ちょっと仕事に近いところというところで、Ruby じゃなくて Groovy でやってます。
Groovy In Action は絶版になっているのか Amazon ですごい値段がついていましたが、ジュンク堂で無事ゲット。 2008 年の本なのでぼくがみても現行バージョンと変わっているなと思う点もありますが(HashMap が LinkedHashMap になっている等)、それほど困ることはなさそうです。 この本は技術書としてもとても面白かったです。 🙂
Groovy はマップ・リスト操作、動的系の機能とクロージャなどのシンタックスを限りなく最小限に抑えている他、JDK にリフレクションで追加する形でクロージャを用いて処理を差し込むパターンのメソッドが多数用意してあるため、ソースから冗長な記述を削除できすっきりとしたソースをかくことができるようです。
というわけで Groovy In Action を読んで仕掛けが何となく分かったので、試しに RSS から画像を取得してファイル保存するプログラムをかいてみました。
// @Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.1')
import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.Method.*
import static groovyx.net.http.ContentType.*
rssUrl = "http://feedblog.ameba.jp/rss/ameblo/nakagawa-shoko/rss20.xml"
pUrl = /<img [^>]*src\s*=\s*[\"']?([^\"'> ]+.jpg)/
pFile = /([^\/]+?\.jpg)$/
new HTTPBuilder(rssUrl).request(GET, XML) {
response.success = { res, rss ->
rss.channel.item.each {
it.description.text().eachMatch(pUrl) {
filename = it[1].toURI().path =~ pFile
new HTTPBuilder(it[1]).request(GET, BINARY) {
response.success = { res2, image ->
new File("./file/${filename[0][0]}").bytes = image.bytes
}
}
}
}
}
}
もうちょっと短く書く方法もあるとは思うですが、例えば PHP でかいた場合と違って、http アクセス失敗とか File のオープンクローズとかの処理がソース上に現れていないにもかかわらず、これでうまくいってしまうであろうところが良いですね。
XML パースにはダイナミックランゲージの機能が使われているのが分かります。 あとは String の eachMatch にクロージャ渡せるとか便利です。
- メソッドの引数の括弧は省略できる。 また、一番外側の引数がクロージャだった場合は括弧にいれなくてOK。
- インスタンスのフィールドは getter/setter が勝手に生成され、プロパティみたいにフィールド名かけばアクセスできる。
他にもコンストラクタにマップ渡すとフィールドを key/value で初期化できるとか、その際のマップの記述は [] つけなくていいとか、なんだか知らないとぱっと見分からないことでいっぱいだったりするのですが、慣れると便利そうです。
動的型付け、動的言語機能は IDE がほぼ無力になるのでドキュメントとにらめっこするのがちょっと大変ですし、ランタイムエラーをやっぱり出しがちですが、どこで苦労するかのバランスは悪くないように思いました。
というわけで実行。
[tegaki]わーい。 とれた。[/tegaki]
…引退します。。(笑)
そのリラックマの紙袋の中身がなんなのかが気になりますw
答えはのちほど、くいっくにて。。 今また買ってきたです。:)