l'essentiel est invisible pour les yeux

Monday, March 16, 2009

[Scala] オブジェクトの初期化のシンタックスシュガー

Scalaでは、オブジェクトの作成〜オブジェクトのメソッド呼び出しによる初期化のための、シンタックスシュガーが用意されている。コンストラクタでオブジェクトを作成して、その後オブジェクトのメソッドを呼び出してオブジェクトを初期化する事はよく例を一つ紹介。

Jettyのハンドラーの初期化をシンタックスシュガーでコーディングした例。ブロック内のスコープは、オブジェクト内でのスコープと同じになるので、メソッドを呼ぶ事ができる。


before:
val handler = new ResourceHandler
handler.setResourceBase("/webapp")

after:
val handler = new ResourceHandler { setResourceBase("/webapp) }


ほんの少し気持いい。

Wednesday, March 11, 2009

[Scala Tips] Java型からScalaのラッパー型への明示的変換を仲介してくれるライブラリ

Scalaでは、Javaの型の多くをラップしたクラスにて再定義している。

byte型 -> scala.Byte
short型 -> scala.Short
int型 -> scala.Int
など。

そのため、ScalaからJavaのライブラリを利用していると、ライブラリのAPIの返り値がJavaの型で、Scalaのラッパークラスではないので変換が必要な事がよくある。例えば、java.util.List型は、ScalaのSeq[A]を継承していないので、enumerableではない。

このため、Scalaの標準ライブラリ中にいくつかの明示的な変換規則を定義してある。例えば、java.util.List[T]からList型への変換などは、scala.collection.jcl.Conversion.convertListを読みこむだけで、後はScalaの言語仕様の明示的な型変換機構により自動的に変換してくれる。


var primNumberList = new java.util.ArrayList[Int](3)
primNumberList.add(1)
primNumberList.add(3)
primNumberList.add(5)

// ScalaのSeq[A]を実装していないのでイテレーターとして扱えない
primNumberList.foreach { println(_) } // ERROR: エラー

// implicit conversionの読みこみ
import scala.collection.jcl.Conversions.convertList
primNumberList.foreach { println(_) }
1
3
5


java.util.ListからList型への変換以外にも、java.util.MapからMap, java.util.SetからSetなど、多数の明示的変換が定義されているので、必要に応じて読みこむと使用できる。

package scala.collection.jcl

object Conversions {
implicit def convertSet[T](set : java.util.Set[T]) = Set(set)
implicit def convertList[T](set : java.util.List[T]) = Buffer(set)
implicit def convertSortedSet[T](set : java.util.SortedSet[T]) = SortedSet(set)
implicit def convertMap[T,E](set : java.util.Map[T,E]) = Map(set)
implicit def convertSortedMap[T,E](set : java.util.SortedMap[T,E]) = SortedMap(set)

implicit def unconvertSet[T](set : SetWrapper[T]) = set.underlying
implicit def unconvertCollection[T](set : CollectionWrapper[T]) = set.underlying
implicit def unconvertList[T](set : BufferWrapper[T]) = set.underlying
implicit def unconvertSortedSet[T](set : SortedSetWrapper[T]) = set.underlying
implicit def unconvertMap[T,E](set : MapWrapper[T,E]) = set.underlying
implicit def unconvertSortedMap[T,E](set : SortedMapWrapper[T,E]) = set.underlying

}

Thursday, March 05, 2009

[Scala] タプルやシンボル式へ対応したDreadLocks 0.2の公開

DreadLocks 0.2を公開しました。今回のアップデートでは、テンプレート中のScala構文中でのタプルとシンボルへの対応とScalaInterpreterの実装をリファクタリングし事が主な変更点です。現在、対応している構文は、if-elseif-elseでの条件分岐、算術式の計算、変数へのメソッドの呼び出し、iterableなSeqやmapに対するループ等です。

Jarファイルは、dreadlocks-0.2.1.jarからダウンロード。

以下のような、タプルの要素への参照を含むforeachのループが書けます。
dreadlocks.txt


Hamburger Cafe:
<?sc cafes.foreach { cafe => ?>
* ${cafe._1} in ${cafe._2}
<?sc } ?>

Test.scala

val tmpl = examplTmplateFile("foreach2.shtml")
val source = Source.fromFile(tmpl).getLines.mkString
val template = Template(source)
val context = Context("cafes" -> List(("Authentic", "Akasaka, Tokyo"), ("FELLOWS", "Komazawa, Tokyo")))
val output = template.render(context)
Console.println(output)
// Hamburger Cafe:
// * Authentic in Akasaka, Tokyo
// * FELLOWS in Komazawa, Tokyo
//

Wednesday, March 04, 2009

[Scala] Sala用ベンチマーク測定ライブラリBenchmarkSuite

BenchmarkSuite - Scalaのベンチマークライブラリ
ページ中段BenchmarkSuiteよりGitHubへリンクしています。

Jarファイルは、BenchmarkSuite-1.0.jarから。

知ってるんだから。Scalaに標準のベンチマークライブラリscala.testing.Benchmark...が、測定したい対象の度にBenchmarkクラスを継承して実装しないといけないなど、APIがかなり硬派! LLでなまった体には正直キツイです。そこで、コードブロックを対象にベンチマークを測定するライブラリが、BenchmarkSuiteです。現在の所、実行時間のみ計測できるとてもシンプルなライブラリです。

使い方は、次の通りです。Benchmark.runに引数を一つ持つブロックを渡し、ブロック引数に対して、reportメソッドを呼ぶだけです。ラベルや実行回数を指定できます。


import org.scalalites.benchmark.Benchmark

Benchmark.run("Benchmark of ack:") { b =>
def ack(x: Int, y: Int): Int = x match {
case 0 => y + 1
case _ => y match { case 0 => ack(x - 1, 1); case _ => ack(x - 1, ack(x, y - 1))}
}
// run over the test named "ack(3, 2) x 50" 50 times
b.report("ack(3, 4) x 10", 10) { ack(3, 4) }

// If you don't pass second argument run benchmark once.
b.report("ack(3, 2)") { ack(3, 2) }
}

// Output
// Benchmark of ack:
// ack(3, 4) x 10 : 4.730000 sec (avg. 0.473000 sec)
// ack(3, 2) x 1 : 0.029000 sec


[Scala] Released Scala’s BenchmarkSuite Library(for English users)

Tuesday, March 03, 2009

[Scala] ScalaベースのテンプレートエンジンDreadLocks 0.1をリリース

DreadLocks - Scalaベースのテンプレートエンジン

Scalaのテンプレートエンジンを探していたけど見つからなかったので、DreadLocksテンプレートエンジンを実装しました。現在は、基本的なScalaの構文のみサポートしています。完全なScalaプログラムのサポートと高速化が次のリリースの目標としています(foreachやif文は実装済み)。ソースコードは、GitHub dreadlocks/trunkで、今後のマイルストーンとロードマップは、TwitterGoogle Groupsで確認できるので、よければどうぞ。

簡単なサンプルコードは、以下の通り。

hamburgers.txt:
Delicious hamburger restraunts in Japan:
<?sc restraunts.foreach { restraunt => ?>
* ${restraunt}
<?sc } ?>

Side menus:
<?sc if(haveSideMenu) { ?>
* ${sideMenus("potato")}
* ${sideMenus("coleslaw")}
<?sc } ?>

Hamburgers.scala
import org.scalalites.dreadlocks._
// You can specify instance of java.io.File, scala.io.Source or String to constructor of Template class.
val source = Source.fromFile("template_variable.shtml")
val template = Template(source)
val context = Context("restraunts" -> List("Baker Bounce", "Great Burger", "FELLOWS"),
"haveSideMenu" -> true,
"sideMenus" -> HashMap("potato" -> "French fries", "coleslaw" -> "Coleslaw"))

val output = template.render(context)
// Console.println(output)
// Delicious hamburger restraunts in Japan:
// * Baker Bounce
// * Great Burger
// * FELLOWS
//
// Side menus:
// * French fries
// * Coleslaw


高速化と完全なScala構文のサポートを引き続き目指します。

Released DreadLocks-0.1 template engine for Scala programmers (in english)