MIA 勉強会: 開発環境構築
Mahout in Action の "1.4.1 Installing Mahout" には 0.5 をダウンロードしてきて IDE で開けって書いてあるけどよくわからないので本家サイトの方法を試します。
Quickstart (https://cwiki.apache.org/confluence/display/MAHOUT/Quickstart)
このページの Download and Installation はBuldingMahout (https://cwiki.apache.org/confluence/display/MAHOUT/BuildingMahout) にリンクされてる。まずビルドしろってことですね
ソースコードダウンロード
Latest (Recommended) だそうなのでこっち
svn co shttp://svn.apache.org/repos/asf/mahout/trunk mahout
pom.xml の version によると 0.6-SNAPSHOT とのこと
コンパイル & インストール
mvn -DskipTests install
時間節約のためテストスキップした方がよさそう
% ls -1 ~/.m2/repository/org/apache/mahout/ commons mahout mahout-buildtools mahout-collections mahout-core mahout-distribution mahout-examples mahout-integration mahout-math
いろいろできた
たぶん続く
MIA 勉強会
Mahout in Action 自習勉強会をはじめました。これからちょくちょく書いていく予定です。
Unfiltered on Heroku
Heroku で Scala がサポートされたので Unfiltered を動かしてみました。
https://github.com/akr4/heroku-unfiltered
package net.physalis.herokuunfiltered import unfiltered.request._ import unfiltered.response._ import unfiltered.netty._ import util.Properties import grizzled.slf4j.Logging object Hello extends cycle.Plan with cycle.ThreadPool with ServerErrorResponse with Logging { def intent = { case Path(Seg("hello" :: Nil)) & Params(params) => { debug(params) ResponseString("Hello %s".format(params("name").headOption.getOrElse("Unfiltered"))) } case Path(_) => ResponseString("Hello from Unfiltered!") } } object Main extends App with Logging { val port = Properties.envOrElse("PORT", "8080").toInt info("started on port:%d".format(port)) unfiltered.netty.Http(port).plan(Hello).run() }
Netty バインディングを使いました。
リッスンするポートを
Properties.envOrElse("PORT","8080")
で取得するのがポイントのようです。
Scala on Heroku についてはこちらが参考になります。
http://devcenter.heroku.com/articles/scala
git push したらデプロイできるし簡単でいいですねー。
github で dotfiles 管理はじめました
https://github.com/akr4/dotfiles
整理しながら少しずつ追加していくつもりです。
rake install
でシンボリックリンクを作ります。erb でメールアドレスなどを置換するようにしています。
こちらの方のを参考にして作りました。
https://github.com/ryanb/dotfiles
コレクションの sliding()
sliding() はコレクションをウィンドウをずらしながら参照する Iterator を返します。
scala> (1 to 5).iterator.sliding(3).toList res19: List[Seq[Int]] = List(List(1, 2, 3), List(2, 3, 4), List(3, 4, 5))
これの存在を最近知りました。
Daimon.scala (http://sites.google.com/site/daimonscala/) で Scala99 やった回にあったら便利だろうなあと思って同じものを作ろうとして時間切れになっていたのでした。
たとえば Scala99 Problem#8 は連続する同じ値の要素を 1 つにまとめる関数 compress を実装します。
scala> compress(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)) res0: List[Symbol] = List('a, 'b, 'c, 'a, 'd, 'e)
sliding を使えばこんな感じで。
def compress[A](list: List[A]): List[A] = { if (list.size < 2) list else list.head :: (for (List(a, b) <- list.sliding(2); if (a != b)) yield b).toList }
連続する要素が異なる場合だけ結果リストに追加します。
本家の模範回答はこちら
http://aperiodic.net/phil/scala/s-99/p08.scala
3 つめの模範回答のように foldRight で結果の head と比較してもいいんですけど、ウィンドウを動かしながらの方が個人的には理解しやすいです。
コレクションの iterate()
コレクションクラスのコンパニオンオブジェクトに定義されている iterate が便利ですね〜
このエントリ[Scala][joda-time] 期間でループ - Secret Staircase on はてなで 1 日ごとの Stream を作りましたが、iterate 使えばもっとシンプルに書けます。
Stream.iterate(LocalDate.today, 7)(_ + 1.days).foreach(println _)
Stream の場合は長さ指定のないのもあるから無限リスト作って takeWhile とかもおk
Stream.iterate(new LocalDate(2011, 1, 1))(_ + 1.days).takeWhile(_ < LocalDate.today).foreach(println _)
と、まあ基本的なことなんだろうけど知らないことばかりだなあ