2011-12-24 ScalaでXMLをパーズする 
ネット上にはなんていうか「試しにやってみました」程度の簡単な例しか転がっていないので多少複雑な例を。以下のようなXML(sample-1.xmlとする)があったとして
<?xml version="1.0" encoding="utf-8" ?> <ninjas> <ninja id="ninjaslayer"> <attacks> <attack name="Suriken"> <damage>10</damage> <times>1000</times> </attack> <attack name="Meia lua de compasso"> <damage>50</damage> <times>30</times> </attack> <attack name="Tsuyoi suriken"> <damage>100</damage> <times>2</times> </attack> <attack name="Evil Black Fire"> <damage>500</damage> <times>1</times> <condition>Controlled by Naraku</condition> <condition>Unconsious</condition> </attack> <attack name="Sacred Nunchaku"> <damage>1000</damage> <times>1</times> <condition>Synchronized with Naraku</condition> <condition>Clutch Situation</condition> </attack> </attacks> <name>Ninja Slayer</name> </ninja> <ninja id="forest-sawatari"> <attacks> <attack name="Machete"> <damage>50</damage> <times>10</times> </attack> <attack name="Bio takeyari"> <damage>50</damage> <times>10</times> </attack> </attacks> <name>Forest Sawatari</name> </ninja> <ninja id="frogman"> <attacks> <attack name="Bio Frogs Tongue"> <damage>50</damage> <times>100</times> </attack> <attack name="Makimono Jitsu"> <damage>300</damage> <times>30</times> </attack> </attacks> <name>Frogman</name> </ninja> <ninja id="frogman"> <attacks> <attack name="Bio Frogs Tongue"> <damage>50</damage> <times>100</times> </attack> <attack name="Makimono Jitsu"> <damage>300</damage> <times>30</times> </attack> </attacks> <name>Frogman</name> </ninja> <ninja id="genocide"> <attacks> <attack name="Buzzsaw"> <damage>500</damage> <times>100</times> </attack> </attacks> <name>Genocide</name> </ninja> <ninja id="evolver"> <attacks> <attack name="Ochoko Defence"> <damage>1</damage> <times>100</times> </attack> <attack name="Ju Jitsu"> <damage>50</damage> <times>100</times> </attack> <attack name="Evolution"> <damage>150</damage> <times>100</times> </attack> <attack name="Supersize"> <damage>150</damage> <times>10</times> </attack> <attack name="Monsterize"> <damage>750</damage> <times>1</times> <condition> Supersized </condition> </attack> </attacks> <name>Evolver</name> </ninja> </ninjas>
ニンジャ名の一覧をStringのリストで取りたい。どうするか。
import scala.xml._ val xm = XML.loadFile("sample-1.xml")
単純に
xm \\ "name"
とすると結果は
NodeSeq(<name>Ninja Slayer</name>, <name>Forest Sawatari</name>, <name>Frogman</name>, <name>Frogman</name>, <name>Genocide</name>, <name>Evolver</name>)
となるので
for(x <- xm \\ "name" ) yield x.text
としてあげるとこの式の値が
scala.collection.immutable.Seq[String] = List(Ninja Slayer, Forest Sawatari, Frogman, Frogman, Genocide, Evolver)
となり目的達成。
2011-12-15 multipart/form-dataのバウンダリ文字列生成(その後) 
この方がClojureっぽいよ!という指摘をいただきました。
char-rangeのところはおいといて(w
確かに昨日のソースは
(defn generateBoundary [] (let [chars "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"] (apply str "-------" (take 40 (repeatedly #(rand-nth chars))))))
にしたほうがよりClojureっぽいですね。
(rand-nth [coll])
(repeatedly f)
#(rand-nth [coll])
として無名関数化してrepeatedlyに渡している。
ただしこいつは
(repeatedly n f)
と書いて無限シーケンスの先頭要素n個を取ることもできるので
(defn generateBoundary [] (let [chars "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"] (apply str "-------" (repeatedly 40 #(rand-nth chars)))))
のようにtakeを省略できる。
乱数については(rand-nth [coll])以外にも(rand-int n) (0〜n-1までの整数の乱数を返す)のもあるのでJavaのRandomのオブジェクトを生成して使わないでもよいケースも多そう。
2011-12-14 Scalaでmultipart/form-dataのバウンダリ文字列生成 
multipart/form-dataでデータをアップロードする必要が出てきたのでScalaでこりこり書き始めた。
各パートの切れ目を表すboundary文字列を生成するプログラムとしてランダム文字列の生成を見つけた。
private String generateBoundary() { String chars = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; Random rand = new Random(); String boundary = ""; for (int i = 0; i < 40; i++) { int r = rand.nextInt(chars.length()); boundary += chars.substring(r, r + 1); } return "---------------------------" + boundary; }
これをほぼそのまま移してもScalaで動くんだが、せっかくなので多少関数型っぽくする。
private def generateBoundary :String = {
val chars = (('0' to '9') ++ ('a' to 'z') ++ ('A' to 'Z' )).mkString + "-_"
val rand = new scala.util.Random
"----------" + (for( i <- 0 until 40 ) yield chars(rand.nextInt(chars.length))).mkString
}
Scalaのfor文はなかなか強力。こうやって「再代入可能な変数を減らしていく」わけですな。
選択される文字一覧には範囲型の結合を使ってみたが、これはまあおまけ。
ついでにClojureでも書いてみたらこんな感じか。
(defn generateBoundary [] (let [chars "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"] [rnd (new java.util.Random)] (str "-------" (apply str (for [i (range 40)] (nth ccc (. rnd nextInt (count ccc))))))))
2011-10-08 Clojure ロゴをアイコンに貼り付ける (1.3.0対応) 
2011-10-06 前回の答え 
http.request(POST){
uri.path = 'mform.html'
body = [status : 'update!', source : 'gegegege']
requestContentType = groovyx.net.http.ContentType.URLENC
response.success = { resp ->
println("status: ${resp.statusLine}")
assert resp.statusLine.statusCode == 200
}
}
は
http.request(POST,TEXT){ req ->
uri.path = 'mform.html'
println(uri.path)
send URLENC, [status : 'update!', source : 'gegegege'] // will be url-encoded
response.success = { resp, xml ->
println("status: ${resp.statusLine}")
assert resp.statusLine.statusCode == 200
}
}
でうまく行った。ところで書いてて疑問だったんだけど、ここのuriとかsend URLENCとかってどこで定義されてるんだろう。一種のDSLになってるんでHTTPBuilderのどこかにあると思うんだけど。




