Scala 発火村(hack-a-thon)にいってきました

22(日)に行われた Scala 発火村に行ってきました。主催の id:yuroyoro さん、お疲れ様でした。
皆さん、黙々と学習&コーディングという感じでした。私はというと、twitter 上の TL 読むのに忙しくて*1、あまりコーディングできていなかったりします(汗


それでも、一応作れそうな範囲で作ったのが以下のコード。twitter で特定のハッシュタグをつけて発言した人の一覧を抜き出すプログラムです。多くの箇所を id:yuroyoro さんの http://d.hatena.ne.jp/yuroyoro/20091027/1256611681 を参考にしながらつくりました。

本当はフォローとリストへの追加もしたかったのですが、そこまで手が回りませんでしたorz

import scala.io.Source
import java.net.{URLEncoder, URL}
import xml.XML

// スクリプトにした方が使いやすいかも・・・
object RetrieveTagMembers {
  def main(args: Array[String]): Unit = {
    val Array(tag) = args
    val searchXml = {
      val url = "http://search.twitter.com/search.atom?q=%s&rpp=100".format(URLEncoder.encode("#"+tag))
      val source = Source.fromURL(new URL(url)) // fromURL(String) がなぜか発見できなかったので
      XML.loadString(source.mkString)
    }

    val authors = {
      val uriPattern = """http[s]?://twitter\.com/(.*)""".r
      (searchXml \\ "author").flatMap(_ \ "uri").flatMap(xml=>Some(xml.text)).flatMap {
        case uriPattern(author) => Some(author)
        case _ => None
      }
    }

    Set(authors: _*) foreach println
  }
}

モナド厨にすこしでもなりたいので、flatMap を連発してみましたw

flatMap(xml=>Some(xml.text)) の部分は、本当は flatMap(Some(_.text)) と書きたかったのですが、どうやらコンパイルとおらない模様。
プレースホルダ(_)をつかった無名関数では、残念ながら x => Some(x.text) とはならず、たぶんSome(x=>x.text)となってしまう。この辺は言語仕様6.23の後ろのほうに書いてあるっぽい。

An expression e of syntactic category Expr binds an underscore section u, if the following
two conditions hold: (1) e properly contains u, and (2) there is no other expression
of syntactic category Exprwhich is properly contained in e and which itself
properly contains u.

ちなみに使い方は以下のように、コマンドライン引数でtwitterハッシュタグ(#なし)を渡すだけ。

c:\>scala RetrieveTagMembers scalahack

*1:物理世界はものすごい静かだったのですが、twitter上はものすごいにぎやかという状態