Scalaでソート

List#sort

List(1, 3, 2).sort(_ < _) // List(1, 2, 3)

class List in scala - Scala Library

Sorting.stableSort

import scala.util.Sorting

val ar = Array(1, 3, 2)
Sorting.stableSort(ar)
ar                                                // Array(1, 2, 3)

Sorting.stableSort(ar, (a: Int, b: Int) => a > b)
ar                                                // Array(3, 2, 1)
import scala.collection.mutable
import scala.util.Sorting

val mm = mutable.Map(1 -> 70, 2 -> 50)
val sorted =                              // sorted: Array((2,50), (1,70))
  Sorting.stableSort(mm.toSeq,
    (a:(Int, Int), b:(Int, Int)) => a._2 < b._2)

object Sorting in scala.util - Scala Library
http://gist.github.com/244459

Scalaのテストを Eclipse+JUnit4でする

Eclipse 3.5.1 Galileo
JUnit 4.5 (Eclipseに入っていたもの)
Scala 2.7.7
  1. プロジェクトを作成する
  2. プロジェクトのプロパティ > Javaのビルド・パス > ソース
    1. フォルダの追加 > 新規フォルダの作成
      1. 「test」フォルダを作成して、「終了」、「OK」
      2. プロジェクト直下に「test」フォルダが追加される
  3. プロジェクトのプロパティ > Javaのビルド・パス > ライブラリー
    1. ライブラリーの追加
      1. JUnit > 次へ
        1. JUnit ライブラリー・バージョンを「JUnit4」にして、「終了」
    2. クラスフォルダの追加 > 新規フォルダの作成
      1. 拡張 > ファイル・システム内のフォルダにリンク
        1. 「bin」フォルダを選択して、「OK」
          1. フォルダ名を「out」に変更して、「OK」
          2. プロジェクト直下に「参照ライブラリー/out」フォルダが追加される
  4. プロジェクトのプロパティ > Javaのビルド・パス > 順序およびエクスポート
    1. 「プロジェクト名/out(クラスフォルダ)」を1番上に移動して、OK
  5. 「test」フォルダにテストを作成する
    1. テストのソースは、参考ページのものを使用する
  6. プロジェクトをクリーンする
  7. メニュー > デバッグの構成
    1. JUnit > 新規
      1. テスト > 選択されたプロジェクト、...すべてのテストを実行 > 検索
        1. 「プロジェクト/out」を選択して、「OK」
      2. テスト・ランナーを「JUnit4」に変更して、「適用」
    2. デバッグ

Scala List[Option]#flatMap

val list = List(Some(1), None, Some(3))

list.flatMap {        //=> List(1, 2, 3, 6)
  case Some(x) => List(x, x * 2)
  case None    => List()
}
list.map {            //=> List(List(1, 2), List(), List(3, 6))
  case Some(x) => List(x, x * 2)
  case None    => List()
}

list.flatMap{         //=>  List(2, 6)
  case Some(x) => Some(x * 2)
  case None    => None
}
list.map {            //=>  List(Some(2), None, Some(6))
  case Some(x) => Some(x * 2)
  case None    => None
}

list.flatMap(x => x)  //=> List(1, 3)
list.    map(x => x)  //=> List(Some(1), None, Some(3))

Scala Actor

アクターの生成・開始

extends Actor
import actors.Actor
class MyActor extends Actor {
  def act: Unit = {
    ...
  }
}
val myActor = new MyActor
myActor.start
actorメソッド

ただちに開始する

import actors.Actor._
val myActor = actor {
  ...
}

メッセージ受信

receive

常にスレッドを使用する
receiveの結果を返せる

val myActor = actor {
  val rr = receive {
    case i:Int =>
      println("receive " + i)
      "Int"
  }
  println("receive result " + rr)
}

myActor !  1
react

メッセージ処理中のみスレッドを使用する
reactの結果を返せない

val myActor = actor {
  react {
    case i:Int => println("react " + i)
  }
}

myActor !  1
loop

受信を繰り返す

val myActor = actor {
  loop {
    react {
      case i:Int => println("loop react " + i)
    }
  }
}

myActor !  1
myActor !  2

メッセージ返信

reply
val myActor = actor {
  react {
    case i:Int =>
      println("react " + i)
      reply(i * 2)
  }
}

val result = myActor !?  1
println("actor result " + result)

メッセージ送信

! ($bang)

送信のみ

myActor !  1
!? ($bang$qmark)

送信+返信を待つ

val result = myActor !?  1
println("actor result " + result)
!! ($bang$bang)

送信+返信を待たない
バックグラウンド処理

val myActor = actor {
  react {
    case i:Int =>
      (1 to 1000).toArray
      println("react " + i)
      reply(i * 2)
  }
}

val future = myActor !! 3
println("set " + future.isSet)
(1 to 1000000).toArray
println("set " + future.isSet)
println("actor result " + future())
set false
react 3
set true
actor result 6
!! ($bang$bang) + PartialFunction

future()のあとにPartialFunctionが呼ばれる

val future = myActor !! (3, { case any => println("partial function " + any) })
future()

Scala 正規表現

val p = "[0-9]+".r  //=> scala.util.matching.Regex = [0-9]+
p.pattern           //=> java.util.regex.Pattern = [0-9]+

find

val p = "[0-9]+".r

p.findAllIn("1 22")            //=> scala.util.matching.Regex.MatchIterator = non-empty iterator
p.findAllIn("1 22").toList     //=> List[String] = List(1, 22,)
p.findAllIn("a 1 22")          //=> scala.util.matching.Regex.MatchIterator = non-empty iterator
p.findAllIn("a 1 22").toList   //=> List[String] = List(1, 22,)
p.findAllIn("a")               //=> scala.util.matching.Regex.MatchIterator = empty iterator
p.findAllIn("a").toList        //=> List[String] = List()

p.findFirstIn("1 22")          //=> Option[String] = Some(1)
p.findFirstIn("a 1 22")        //=> Option[String] = Some(1)
p.findFirstIn("a")             //=> Option[String] = None

p.findPrefixOf("1 22")         //=> Option[String] = Some(1)
p.findPrefixOf("a 1 22")       //=> Option[String] = None
p.findPrefixOf("a")            //=> Option[String] = None

p.findFirstMatchIn("1 22")     //=> Option[scala.util.matching.Regex.Match] = Some(1)
p.findFirstMatchIn("a 1 22")   //=> Option[scala.util.matching.Regex.Match] = Some(1)
p.findFirstMatchIn("a")        //=> Option[scala.util.matching.Regex.Match] = None

p.findPrefixMatchOf("1 22")    //=> Option[scala.util.matching.Regex.Match] = Some(1)
p.findPrefixMatchOf("a 1 22")  //=> Option[scala.util.matching.Regex.Match] = None
p.findPrefixMatchOf("a")       //=> Option[scala.util.matching.Regex.Match] = None
val p = "[0-9]+".r
p.unapplySeq("1 22")           //=> Option[List[String]] = None

val p2 = "([0-9]+)".r
p2.unapplySeq("1")             //=> Option[List[String]] = Some(List(1))
p2.unapplySeq("1 22")          //=> Option[List[String]] = None

val p3 = "([0-9]+) ([0-9]+)".r
p3.unapplySeq("1")             //=> Option[List[String]] = None
p3.unapplySeq("1 22")          //=> Option[List[String]] = Some(List(1, 22))

val p2(n1) = "1"               //=> n1: String = 1
val p2(n2) = "1 22"            //=> scala.MatchError: 1 22

val p3(n3, n4) = "1"           //=> scala.MatchError: 1
val p3(n5, n6) = "1 22"        //=> n5: String = 1, n6: String = 22
val p = "[0-9]+".r
val m = p.findFirstMatchIn("abc123xyz").get  //=> m: scala.util.matching.Regex.Match = 123
m.matched     //=> String = 123
m.before      //=> java.lang.CharSequence = abc
m.after       //=> java.lang.CharSequence = xyz
m.start       //=> Int = 3
m.end         //=> Int = 6
m.source      //=> java.lang.CharSequence = abc123xyz
m.groupCount  //=> Int = 0
m.subgroups   //=> List[String] = List()

group

val p = "([a-z]+)([0-9]+)([a-z]+)?".r
val m = p.findFirstMatchIn("Aabc123Z").get  //=> m: scala.util.matching.Regex.Match = abc123
m.matched     //=> String = abc123
m.before      //=> java.lang.CharSequence = A
m.after       //=> java.lang.CharSequence = Z
m.start       //=> Int = 1
m.end         //=> Int = 7
m.source      //=> java.lang.CharSequence = Aabc123Z
m.groupCount  //=> Int = 3
m.subgroups   //=> List[String] = List(abc, 123, null)

m.group(1)    //=> String = abc
m.before(1)   //=> java.lang.CharSequence = A
m.after(1)    //=> java.lang.CharSequence = 123Z
m.start(1)    //=> Int = 1
m.end(1)      //=> Int = 4

m.group(2)    //=> String = 123
m.before(2)   //=> java.lang.CharSequence = Aabc
m.after(2)    //=> java.lang.CharSequence = Z
m.start(2)    //=> Int = 4
m.end(2)      //=> Int = 7

m.group(3)    //=> String = null
m.before(3)   //=> java.lang.CharSequence = null
m.after(3)    //=> java.lang.CharSequence = null
m.start(3)    //=> Int = -1
m.end(3)      //=> Int = -1

group name

val p = new scala.util.matching.Regex("""(\d+)([a-z]+)""", "kazu", "moji")
val m = p.findFirstMatchIn("100abc").get
m.groupNames     //=> Seq[String] = Array(kazu, moji)
m.group("kazu")  //=> String = 100
m.group(1)       //=> String = 100
m.group("moji")  //=> String = abc
m.group(2)       //=> String = abc

replace

val p = "[0-9]+".r
p.replaceAllIn("1 22", "X")      //=> String = X X
p.replaceAllIn("a 1 22", "X")    //=> String = a X X
p.replaceAllIn("a", "X")         //=> String = a

p.replaceFirstIn("1 22", "X")    //=> String = X 22
p.replaceFirstIn("a 1 22", "X")  //=> String = a X 22
p.replaceFirstIn("a", "X")       //=> String = a

http://java.sun.com/javase/ja/6/docs/ja/api/java/util/regex/Pattern.html

ScalaでHttpClient Get

HTTP GET

Scala 2.7.7
Apache HttpComponents HttpClient 4.0

GET

val page = "http://www.yahoo.co.jp/"
val client = new DefaultHttpClient
try {
  val uri = new URI(page)
  val get = new HttpGet(uri)
  val response: HttpResponse = client.execute(get)
  if (response.getStatusLine.getStatusCode == HttpStatus.SC_OK) {
    val file = new File("test.html")
    val ba = EntityUtils.toByteArray(response.getEntity)
    FileUtils.writeByteArrayToFile(file, ba)
  }
} catch {
  case e: UnknownHostException => e.printStackTrace
  case e: IOException          => e.printStackTrace
  case e: URISyntaxException   => e.printStackTrace
}
client.getConnectionManager.shutdown

ResponseHandler

class DownloadResponseHandler(uri: URI) extends ResponseHandler[Boolean] {
  override def handleResponse(response: HttpResponse): Boolean = {
    try {
      if (response.getStatusLine.getStatusCode == HttpStatus.SC_OK) {
        val file = new File("test.html")
        val ba = EntityUtils.toByteArray(response.getEntity)
        FileUtils.writeByteArrayToFile(file, ba)
      }
      return true
    } catch {
      case e: IOException => e.printStackTrace
    }
    return false
  }
}

val page = "http://www.yahoo.co.jp/"
val client = new DefaultHttpClient
try {
  val uri = new URI(page)
  val get = new HttpGet(uri)
  client.execute[Boolean](get, new DownloadResponseHandler(uri))
} catch {
  case e: UnknownHostException => e.printStackTrace
  case e: IOException => e.printStackTrace
  case e: URISyntaxException => e.printStackTrace
}
client.getConnectionManager.shutdown

(Java) ResponseHandler

class DownloadResponseHandler implements ResponseHandler<Boolean> {
  private URI uri;
  DownloadResponseHandler(URI uri) {
    this.uri = uri;
  }
  @Override
  public Boolean handleResponse(HttpResponse response) {
    try {
      if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
        File file = new File("test.html");
        byte[] ba = EntityUtils.toByteArray(response.getEntity());
        FileUtils.writeByteArrayToFile(file, ba);
      }
      return Boolean.TRUE;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return Boolean.FALSE;
  }
}

String page = "http://www.yahoo.co.jp/";
DefaultHttpClient client = new DefaultHttpClient();
try {
  URI uri = new URI(page);
  HttpGet get = new HttpGet(uri);
  client.execute(get, new DownloadResponseHandler(uri));
} catch (UnknownHostException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
} catch (URISyntaxException e) {
  e.printStackTrace();
}
client.getConnectionManager().shutdown();

gist: 221181 - Apache HttpComponents HttpClient Get
gist: 222254 - Apache HttpComponents HttpClient Get ResponseHandler

Apache HttpComponents HttpClient

Scala 2.7.6
Apache HttpComponents HttpClient 4.0 http://hc.apache.org/
Apache HttpComponents HttpCore 4.0.1
Apache Commons Logging 1.1.1 http://commons.apache.org/logging/
Apache Commons Codec 1.4 http://commons.apache.org/codec/
Apache Mime4j 0.6 http://james.apache.org/mime4j/
jcip-annotations http://www.jcip.net/

README.txtにはないが、jcip-annotationsが必要

error: error while loading DefaultHttpClient, class file 'C:\...\httpcomponents-client-4.0\lib\httpclient-4.0.jar(org/apache/http/impl/client/DefaultHttpClient.class)' is broken
(class net.jcip.annotations.ThreadSafe not found.)
error: error while loading AbstractHttpClient, class file 'C:\...\httpcomponents-client-4.0\lib\httpclient-4.0.jar(org/apache/http/impl/client/AbstractHttpClient.class)' is broken
(class net.jcip.annotations.ThreadSafe not found.)
C:\...\ApacheHttpClient.scala:5: error: org.apache.http.impl.client.DefaultHttpClient does not have a constructor
    val client = new DefaultHttpClient
three errors found