2010年12月23日 23:31

ScalaSTMについていろいろ実験した結果

ScalaSTMについていろいろ実験した結果のメモ。
久しぶりのブログ更新だが。

val aa = Ref(...);

atomic { implicit txn =>

  val a = aa();

  // ここでなにか処理をする
  // この間に他のスレッドが aa() に書き込みをするとする

  // このあとに、読み込みまたは書き込みをする
  val b = aa(); // 読み込みをする
  // または
  aa() = ...; // 書き込みをする

  // するとこのタイミングで
  // scala.concurrent.stm.skel.RollbackError$
  // の例外が発生し
  // このあとのatomicブロックの残りのコードは
  // 実行されない
  ...; // 実行されず

  // scala.concurrent.stm.skel.RollbackError$ は
  // atomic の実装がキャッチして、
  // atomicブロックを再実行する

}

atomic { implicit txn =>

  val a = aa();

  // ここでなにか処理をする
  // この間に他のスレッドが aa() に書き込みをするとする

  try {
    aa() = ...; // 書き込みをする
  } catch {
    case e => ;
    // scala.concurrent.stm.skel.RollbackError$
    // をキャッチしてしまうと、
  }
  // このあとのコードは引き続き実行される
  ...;

  // たとえ RollbackError を例外を
  // キャッチして飲み込んでも、
  // ロールバックはされる
  // atomicブロックは再実行される

}

atomic { implicit txn =>

  ...;

  // atomic はネストすることができる
  atomic { implicit txn =>

    ...;

  } // 正しく処理されコミットされたとする

  ...;
  // ここでロールバックされる事態となった場合、
  // 内側の atomic で実行された内容も含めて
  // ロールバックされる

}
タグ:scala
カテゴリ:テック
2010/12/23 Thu 23:31 | Comment(1) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする

2010年08月25日 11:48

任意のURLにジャンプするためだけのフォーム

任意のURLにジャンプするためだけのフォーム
URL:
タグ:javascript
カテゴリ:テック
2010/08/25 Wed 11:48 | Comment(0) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする

2010年06月15日 17:49

iPadのUserAgent

iPadのUser Agentを確認したら、

Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; ja-jp) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10

であった。
3GモデルでもWiFiモデルでもまったく同じだった。
タグ:iPAD
カテゴリ:テック
2010/06/15 Tue 17:49 | Comment(0) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする

2010年04月18日 23:34

Scalaのメモ その5 JavaのListをScalaのListに変換

Scalaのメモその4の続き。

Javaの任意のクラスを利用できるので、リストは、ScalaのListArrayでなくても java.util.List も利用できる。ただ、ScalaのListArrayのほうが便利なので、java.util.List はやむを得ない場合のみの方がよさそう。

リストをforループに回すときは、mapメソッドやforeachメソッドを備えている必要があり、java.util.List はそのままではforループでは回せない。なので、java.util.List からScalaの scala.collection.jcl.BufferWrapper という型に変換してくれる scala.collection.jcl.Conversions.convertList メソッドを利用する。

scala.collection.jcl.BufferWrapperscala.Iterable というtraitを継承していて、それがmapメソッドやforeachメソッドを実装している。traitってのはJavaにない概念でまだあまり理解できていない。

scala.collection.jcl.Conversions.convertListimport文に書いておけば、暗黙の型変換というのが適用されて、特に何も考えなくても、forループで使えるようになる。暗黙の型変換ってのもJavaにない概念だ。型がマッチするように勝手にメソッド呼び出しを追加してくれるものらしい。

以下の2つの例は同じ意味になる。
import scala.collection.jcl.Conversions.convertList;

val list = new java.util.ArrayList[String]();
list.add("abc");
list.add("def");
for(word <- list){
	println(word);
}
val list = new java.util.ArrayList[String]();
list.add("abc");
list.add("def");
for(word <- scala.collection.jcl.Conversions.convertList(list)){
	println(word);
}
タグ:scala
カテゴリ:テック
2010/04/18 Sun 23:34 | Comment(0) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする

2010年04月13日 00:09

Scalaインタープリタのエラー scala.tools.nsc.MissingRequirementError その2

ScalaのインタープリタをJavaのプログラムから利用しようと、scala.tools.nsc.Interpreterinterpret を呼び出すと出てくる以下のエラー。

scala.tools.nsc.MissingRequirementError: object scala not found.
  at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:514)

Scalaがクラスファイルを見つけられるように、jarファイルのありかをScalaに教えてあげないといけないらしい。Scalaのclasspathの解説に説明があった。

英語なので全部は読めていないのだが、要するにScalaにクラスパスを教えなきゃいけない。jarファイルのありかはそもそもJava起動時に教えているので、なんでエラーが出るのかは不明だが(Eclipseから起動しているからなのか)、解決方法としては、Java起動時のコマンドラインオプションに -Dscala.home="C:\scala-2.8.0.Beta1-prerelease" を付ける方法もあるが、以下のコードでもできた。こっちの方法だとScala関連だけでなく、そのほかのライブラリやユーザ定義のクラスを呼び出そうとしたときのエラーも解決できる。

scala.tools.nsc.Settings settings = new scala.tools.nsc.Settings();
settings.classpath().value_$eq(System.getProperty("java.class.path"));
scala.tools.nsc.Interpreter interpreter = new scala.tools.nsc.Interpreter(settings, out);
interpreter.interpret(sourceCode);

value_$eq という変な名前のメソッドは、Scalaでは value_= という名前のメソッドで、valueというプロパティのセッターのようなものになる。

クラスファイルはクラスローダが探してくれるのになぜScalaに改めてクラスパスを教えなきゃいけないかというと、ここからは推測だが、Scalaはpackage名の途中でもそれがpackage名だと分かる必要があるから。

例えば、import org._ と書けば、名前がorg.で始まるパッケージが存在することをScalaは確認する必要がある。jarファイルの中を探索すればorgというディレクトリがあってその中にさらにディレクトリがあるので、orgがパッケージ名の一部だと分かる。orgというパッケージもクラスもあるわけではないので、jarファイルを見ない限り import org._ の妥当性を検証できない。もちろん org.w3c.dom.Element というクラス名を見れば、そのクラスはクラスローダで読み込めるので、結果としてorgがパッケージ名の一部だと分かるが、Scalaの場合は、それをクラスを読み込む前に分かるようにしなければいけない。Javaの場合は、パッケージのインポートはパッケージのフルネームかクラス名のフルネームで指定する必要があるので、このようなことがない。

この認識で合ってるかな。
タグ:scala java
カテゴリ:テック
2010/04/13 Tue 00:09 | Comment(0) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする

2010年04月10日 01:11

Scalaインタープリタのエラー scala.tools.nsc.MissingRequirementError: object scala not found.

ScalaのインタープリタをJavaのプログラムから利用しようと、scala.tools.nsc.Interpreterinterpret を呼び出すと、以下のようなエラーが出た。

scala.tools.nsc.MissingRequirementError: object scala not found.
  at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:514)

2.7.7 では出ず、2.8.0.Beta1 で出た。Scalaのバグなのか仕様なのかわからないが、とりあえず、Java起動時のコマンドラインオプションに -Dscala.home="C:\scala-2.8.0.Beta1-prerelease" というように、Javaのプロパティを設定すると解決した。(Windowsの場合)

参考:Scala のインタープリタをJavaから呼び出すには

2010/04/13追記
もっといい解決方法
タグ:scala java
カテゴリ:テック
2010/04/10 Sat 01:11 | Comment(0) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする

2010年03月27日 21:19

ScalaのインタープリタをJavaから呼び出すには

ScalaのインタープリタをJavaに埋め込むには、以下が参考。

to use Scala as a scripting engine
http://lampsvn.epfl.ch/trac/scala/ticket/874

scalaからappengineのapiをたたくシェルがようやくできたっぽい
http://d.hatena.ne.jp/marblejenka/20100301/1267455776

Embedding the Scala Interpreter
http://suereth.blogspot.com/2009/04/embedding-scala-interpreter.html

インタープリタのソースコード scala.tools.nsc
http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk/src/compiler/scala/tools/nsc/

2010/04/10追記
参考:scala.tools.nsc.MissingRequirementError: object scala not found.
タグ:scala java
カテゴリ:テック
2010/03/27 Sat 21:19 | Comment(0) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする

2010年03月27日 20:47

Scalaのメモ その4 リスト

Scalaのメモその3の続き。



配列は Array を使う。[] で要素の型を指定し、()で要素数を指定する。要素へのアクセスはJavaでは [] だが、Scalaでは () を使う。val で不変の変数を宣言しても配列自体は可変となるので、要素に代入が可能。
val a = new Array[Int](3);
a(0) = 3;
a(1) = 4;
a(2) = 5;
for(o <- a){
	println(o);
}



new で生成せずに、関数呼び出しと同じような構文で初期化された配列を生成することが可能。
val a = Array(1, 2, 3);
a(0) = 8;
for(o <- a){
	println(o);
}
// 8 2 3 が出力
引数で整数を指定しているので、a の型は Array[Int] と型推論される。



Listも配列だが、こちらは不変オブジェクト(イミュータブル)になるので、要素に代入しようとするとエラーになる。
val a = List(1, 2, 3);
// a(0) = 8; // この行を入れるとコンパイルエラーになる
for(o <- a){
	println(o);
}
// 1 2 3 が出力
a の型は List[Int] と型推論される。



List(1, 2.0, 3) とすると、要素に浮動小数点数が含まれるので、new List[AnyVal] という型に推論される。AnyValIntDoubleBooleanなどJavaのプリミティブ型のオブジェクトのスーパークラスだ。Javaのプリミティブ型もScalaではオブジェクトになっている。

さらに List(1, 2.0, "3") とすると、List[Any] という型に推論される。Anyは、どんな型のオブジェクトも収められる、全てのオブジェクトのスーパークラスだ。

AnyRef というのがあり、それがJavaの java.lang.Object と同じ。Any は、AnyValAnyRef の共通のスーパークラス。



::: は2つのリストを連結する。List は不変オブジェクトなので、2つのリスト自体は変化しないが、連結された新しいリストを式の評価結果として返す。

:: は1つの要素をリストの先頭に追加する。:: で複数の要素を並べた場合、最後はリストでなければいけない。NilList() と同じで空のリストを表すので、最後に Nil を置けばよい。Lispのリストみたいだ。
val a = List("green", "red", "yellow", "orange");
val b = List("white", "blue");
a ::: b
// List("green", "red", "yellow", "orange", "white", "blue")
"rubik" :: b
// List("rubik", "white", "blue")
"rubik" :: "cube"
// 最後がリストでないので、コンパイルエラーになる
"rubik" :: "cube" :: Nil
// List("rubik", "cube")



リストの先頭に要素を追加するのは、リストの大きさに寄らず一定のコストで実行できるが、リストの最後に追加するのはリストの大きさに比例するコストがかかるらしい。ますますLispのリストと同じだ。



タプル。複数の値をコンマ区切りで並べて括弧で囲むと、タプルになる。_1, _2,,, というようなフィールド名で要素にアクセスできる。関数から複数の値を返すときに便利だそうだ。タプルはJavaにはない。
val t3 = (3, "abc", 3.14);
println(t3._1); // 3
println(t3._2); // abc
println(t3._3); // 3.14
タプルの要素は個々のフィールドなので、同じ型である必要はなく、t3Tuple3[Int, java.lang.String, Double] という型に推論される。



マップは Map を使う。これは Array と違い、List と同様にイミュータブルである。Map にキーバリューを追加するには、+ で2値のタプルを追加する。
// var m = Map[String, String]; // () がないとコンパイルエラー
var m = Map[String, String]();
m += ("a" -> "abc"); // m += (("a", "abc")) と同じ意味。
m += (("b", "bcd"), ("c", "cde"));
// Map("a" -> "abc", "b" -> "bcd", "c" -> "cde")
"a" -> "abc"-> というメソッドを呼び出していて、2値のタプルを返す。なので、m += ("a" -> "abc")m += (("a", "abc")) と同じ意味。



要素へのアクセスは List と同様に括弧を使う。要素が見つからなかった場合は、java.util.NoSuchElementException がスローされる。この仕様は、java.util.Map と同じ。
m("b") // "bcd"
m("d") // throw java.util.NoSuchElementException



2010/04/18追記
その5に続く
タグ:scala
カテゴリ:テック
2010/03/27 Sat 20:47 | Comment(0) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする

2010年03月25日 01:03

Scalaのメモ その3 関数・演算子

Scalaのメモその2の続き。



関数に返値がない場合、Javaと違って、ScalaではUnitと書く。Javaのvoidと同じ意味かどうかは不明。
def summation(n: Int): Unit = {
	var sum = 0;
	for(index <- 1 to n){
		sum += index;
	}
	println(sum);
}
summation(100);



Unit の場合は、返値型と中括弧 { の前のイコールを省略できる。
def summation(n: Int){
	var sum = 0;
	for(index <- 1 to n){
		sum += index;
	}
	println(sum);
}
summation(100);



引数のない関数呼出は、() を省略できる。副作用を目的とした関数呼び出しは () を省略せず、副作用がなく返値の取得を目的とした関数呼び出しは、() を省略するのがScalaの慣例らしい。
def summation(){
	println(5050);
}
summation;
summation();

副作用のない引数のない関数呼び出しで () を省略する慣例となっているのは、プロパティを取得する方法の実装をメソッドからフィールドに変更しても、それを利用する側のソースコードを変更しなくてもすむように、らしい。例えば、文字列の長さを取得するのは、Javaでは str.length() だが、Scalaでは str.length でもよい。長さの取得がメソッドかフィールドなのかは覚えている必要がない。Javaの配列の長さは arr.length であて、arr.length() でないのは、非常に紛らわしい。() が必要かどうかを覚えるのは手間だ。



for文で使う toIntで定義されているメソッドの扱いらしい。toメソッドの返値は範囲を表す scala.Rainge.Inclusive というクラスのオブジェクト。untilメソッドも同様。以下の4つの例は全部同じ動きをする。
for(i <- 1 to 10){
	out.println(i);
}
val range = 1 to 10;
for(i <- range){
	out.println(i);
}
for(i <- (1).to(10)){
	out.println(i);
}
val range = (1).to(10);
for(i <- range){
	out.println(i);
}



引数が1つのメソッドは、2項演算子と同じ構文で呼び出せる。逆に2項演算子はメソッドの構文でも呼び出せる。2項演算子はメソッドとして定義されている。1 + 2(1).+(2) と同じでシンタックスシュガーに過ぎない。1 to 10(1).to(10) と同じなのもこの理屈による。



2010/03/27追記
その4に続く
タグ:scala
カテゴリ:テック
2010/03/25 Thu 01:03 | Comment(0) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする

2010年03月23日 00:40

Scalaのメモ その2

Scalaのメモの続き。



クラスのフィールにアクセス修飾子を付けなかった場合のデフォルトは public になる。フィールドを隠したい場合は private を付ける必要がある。

クラス定義の本体にフィールド定義と並列にコードを書くと、コンストラクタの中でそれが実行される。
class ComplexNumber(r: Double, i: Double){
	private val real: Double      = r;
	private val imaginary: Double = i;
	println(toString());
	override def toString(): String = {
		if(imaginary == 0)
			real.toString();
		else if(imaginary > 0)
			real + " + " + imaginary + " i";
		else
			real + " - " + (-imaginary) + " i";
	}
}
new ComplexNumber(1.0, 1.5); // ここで生成するだけでクラス定義中の println が呼び出される



Javaのプリミティブ型を1文字目大文字にしたものが、そのままScalaでも使える。Byte, Short, Int, Long, Float, Double, Boolean, Char, StringString はプリミティブ型ではないが)。Javaクラスファイルにコンパイルされるときには、プリミティブ型かラッパークラスに変換されている。



文字列はJavaと同じ構文のほか、Scala独自のものとして raw string 構文がある。""" で囲むとバックスラッシュはおろか改行もそのまま含めることができる。
val s1 = """12345
  67890""";
val s2 = """12345
  |67890""".stripMargin;
1つ目の例は、67890の前に改行とスペースが入る。ソースコードの見た目のためにインデントしたい場合は、2つ目の例のように、先頭に | をつけて、stripMargin を呼び出せばいい具合にしてくれるらしい。



Scalaの等価を調べる演算子 == はJavaでいうところのequalsメソッドと同じで、値が等しいかどうかをチェックしている。型が違っていても拡大変換されて比較されるようだ。
1==1 // true
1==1L   // true
1==1.0  // true
1=="1"  // false



2010/03/25追記
その3に続く
タグ:scala
カテゴリ:テック
2010/03/23 Tue 00:40 | Comment(0) | TrackBack(0) | テック | このブログの読者になる | 更新情報をチェックする
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。