ScalaでApache Commons Mathを使う
Scalaで科学計算をしようとしたんだけど、Scalaのデファクトスタンダードっぽいライブラリがない。
仕方ないので、Javaのライブラリを読み込むことにした。
JavaにはApache Commons Mathという良さげなライブラリがあったので、それを使うことにした。
Math - Download Apache Commons Math
上のリンクからBinariesを選んでダウンロードすればOK。
アーカイブを解凍して、含まれているcommons-math-3.3.3.jar(バージョンは適宜読み替えて)が本体。
これを自分の作業ディレクトリにコピーする。
Javaのライブラリをシステムにインストールするどうのこうのという話は、僕にはわからない。
(Pythonのpip、Rubyのgemみたいなパッケージ管理ツールが欲しいんだけれども)
で、適当にソースコードを書く。ドキュメントは割と充実してるっぽいので適当に参照。
【参考】Apache Commons Math 3.3 API
import org.apache.commons.math3.complex object Main { def main(args: Array[String]) { val c = new complex.Complex(1,1) println(s"${c.sqrt().getReal}+${c.sqrt().getImaginary}i") } }
Mathはorg.apache.commons.math3以下に入ってるので、必要そうなモジュールをimport。
僕の場合は複素数計算がしたかったので、org.apache.commons.math3.complex.Complexを利用。
(正直な話、モダンな言語なんだからこれくらい標準ライブラリに入れろよという感じはある)
サンプルソースはを計算。
ところが。
実行方法がわからない。
コンパイル
$ fsc -cp commons-math3-3.3.jar Main.scala
どうやらcp(classpathの略)で必要なライブラリを指定してあげればコンパイルできるようだ。
ちなみに、fscはfast scala compilerなので、別に普通のscalacでもよい。
実行
$ scala Main java.lang.ClassNotFoundException: org.apache.commons.math3.complex.Complex at java.net.URLClassLoader$1.run(URLClassLoader.java:372) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:360) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at Main$.main(Main.scala:5) at Main.main(Main.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at scala.tools.nsc.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:71) at scala.tools.nsc.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31) at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:139) at scala.tools.nsc.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:71) at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:139) at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:28) at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:45) at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:35) at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:45) at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:74) at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96) at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:105) at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
Complexを使っているところでClassNotFoundExceptionを飛ばしているのだから、Commons Mathを動的リンクしているんだろう。
調べてみたところ、コンパイル時と同様classpathオプションで指定できるらしい。
もう一回実行
$ scala -cp commons-math3-3.3.jar Main
No such file or class on classpath: Main
???
今度はさっきコンパイルしたMainが読み込めない。どうしたものか。