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月18日 17:35

4月18日のトマト

Image347.jpg
忘れてはならないのは、このブログのタイトルが植物の成長の記録であったこと。

よく見ると小さな実がなってます。
タグ:トマト
カテゴリ:植物成長記録
2010/04/18 Sun 17:35 | 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) | テック | このブログの読者になる | 更新情報をチェックする
×

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