2007年12月27日木曜日

JRuby idioms

* Java を使う

- require 'java'
- include_class 'java.lang.String' to short name access
- java.lang.String.new("abc")

* File I/O

- read

f = open(filename)
while line = f.readline
:
end
f.close


begin
line = readline
rescue EOFError
break
end

2007年12月26日水曜日

Google Chart API

Google Chart API の整理

もっとも、Eastwood のためだが...

- user 1日 50000 リクエストまで。

http://chart.apis.google.com/chart?
chs=200x125
&chd=s:helloWorld
&cht=lc
&chxt=x,y
&chxl=0:|Mar|Apr|May|June|July|1:||50+Kb

- chs=wwwxhhh は pixel 単位のサイズ
- chd=.... はデータ
- cht=... はチャートの種類
- chxt=x,y は x, y 両方のラベルが必要ということを指定
- chxl=... は x, y 軸のラベル

- HTML に embed するときは & ではなく & をつかう。

- char data には3種類のエンコーディングがある。
-- Simple 62 までの値 chd=s:...
A=0,B=1,Z=25,a=26,z=51,0=52,9=61,_=missing value
data set separator=","
-- Text 1000 までの値 chd=t:...
0.0=0,1.0=1,100.0=100, -1=missing value
data set separator="|"
-- Extended 4096 までの値 chd=e:
use char pair, A-Za-z0-9-._
AA = 0, AZ = 25, Aa = 26, Az = 51, A0 = 52, A9 = 61, A- = 62, A. = 63
BA = 64, BZ = 89, Ba = 90, Bz = 115, B0 = 116, B9 = 125, B- = 126, B. = 127
.A = 4032, .Z = 4057, .a = 4058, .z = 4083, .0 = 4084, .9 = 4093, .- = 4094, .. = 4095.
'_' = missing value
data set separator=","

(書きかけ...)

NetBeans 6 / ruby gems OutOfMemoryError

Java heap size はどうもハードコーディングされているらしい。

http://deadlock.netbeans.org/fisheye/rdiff/netbeans?csid=MAIN:mkrauskopf:20071216155725&u&N

Index: ruby/platform/src/org/netbeans/modules/ruby/platform/RubyExecution.java
===================================================================
RCS file: /cvsup/nb_all/ruby/platform/src/org/netbeans/modules/ruby/platform/RubyExecution.java,v
diff -u -N -r1.2 -r1.3
--- ruby/platform/src/org/netbeans/modules/ruby/platform/RubyExecution.java 16 Dec 2007 15:48:05 -0000 1.2
+++ ruby/platform/src/org/netbeans/modules/ruby/platform/RubyExecution.java 16 Dec 2007 15:57:25 -0000 1.3
@@ -170,7 +170,7 @@

String extraArgs = System.getenv("JRUBY_EXTRA_VM_ARGS"); // NOI18N

- String javaMemory = "-Xmx256m"; // NOI18N
+ String javaMemory = "-Xmx512m"; // NOI18N
String javaStack = "-Xss1024k"; // NOI18N

if (extraArgs != null) {

JRUBY_EXTRA_VM_ARGS に -Xmx512m を指定することでこれは解決。

rake がなかなか動いてくれない。以下のキーワードで探してみるが、
これといったのが見つからない...

"adding Java library jruby-complete-1.0.2" "rake aborted!" "execution expired"

何とか war ファイルはできたものの、アクセスするとディレクトリリストが
見えてしまう。アプリケーションとしては動かない。rake task で run すると
jetty が起動されるが、JSP サポートがないと出る。
ただ、war をデプロイしたのは Tomcat 5.5.1 だ。なぜだ???

2007年12月21日金曜日

Scala

Java Posse の Martin Odersky の interview から、Scala の作者である
だけではなく 1.3 以降の javac の開発もやってきた人だと関心。Scala
自身は初見だったが、よく pod cast にでてきたのは覚えている。言語に
うるさい人には気になるようだ。

Scala のコンパイラ、実行環境はオープンソースでダウンロードできて、
1.4 あたりからの java があれば実行できる。

* Hello World

package hello;
object HelloWorld {
def main(args: Array[String]) {
println("Hello World!")
}
}

- package は java と同様
- object Name { ... } は Name というシングルトンを作る
- メソッドの定義は def ではじめる。引数は "名前: 型" で宣言する
- println は組み込み
- import も同様に使えるが、機能が拡張されている。最後の要素で
{class1, class2} のようにまとめて指定でき、import a.b.C._ で
C がクラス名とすると、これは C に関する static import として
働く。

- ソースの拡張子は .scala, scalac でコンパイル。ファイル名とクラス名の
 一致の必要はないようだ。

* クラス定義

class Complex(real: double, imaginary: double) {
def re = real
def im = imaginary
override def toString() =
"" + re + (if (im < 0) "" else "+") + im + "i"
}

クラス名のあとに引数のリストが来る。これは primary constructor の
シグネチャで、class の body がパースされる。ボディがパースされるのは
ruby に似ている。

def re = real

は初期値の設定と re という getter/setter の宣言でもある。プロパティを
作っているといってもいいかも知れないが、うるさい人は色々と意見がある
だろう。本当のプロパティはコンポーネントモデルにおけるプロパティであり、
参照、設定のほかにもイベント機能なども備えないとなど云々...

Ruby のように自明なものは関数のあとに () を書かなくても呼べる。
またオブジェクトのオペレーションを呼ぶときに "." すら省略できるケースが
ある。

インスタンス化は java とほぼ同じ。

val c = new Complex(1.2, 3.4)

これは厳密に書けば

val c: Complex = new Complex(1.2, 3.4)

* Generics / Genericity

Generics/Template 相当の機能を備えている。Genericity と呼んでいる。
下の例では a は任意の型。

class Reference[a] {
private var contents: a = _
def set(value: a) { contents = value }
def get: a = contents
}

* Mixin 機能。

Ruby のものと似ている。AOP の手法の一つともいえる。実態つき、拡張可能な
インターフェイスのようなものと言ってもいい。

* call-by-value/call-by-name

関数呼び出しは call-by-value と call-by-name があり、引数の評価の
仕方が異なる。デフォルトは call-by-valude であるが、reduction が
完了しない事がある。その場合にはパラメータの型の前に => を入れると
call-by-name になる。

def constOne(x: Int, y: => Int) = 1

* if-else は conditional expression の様にも使える。

def abs(x: Double) = if (x >= 0) x else x

* Unit は java の void とほぼ同様。()

* Nested function

inner class の様に関数の中に関数を定義できる。一番外側の関数の変数は
nested function からも参照できる。

* Tail Recursion

一見、再起呼び出しに見えても、スタックを余計に消費しないように実行できる
場合はそうしてくれる。

* First-Class Functions

関数は first-class value と呼ばれ、他の関数に渡すことができる。そのような
関数を受け取ったり、返したりする関数は higher-order functions と呼ばれる。

関数のパラメータの型は "Int => Int" (Int をとり Int を返す) という形で
指定できる。その例として下のものは a から b の間の値に f 適用してその
合計をとる関数となる。

def sum(f: Int => Int, a: Int, b: Int): Int =
if (a > b) 0 else f(a) + sum(f, a + 1, b)

def sumInts(a: Int, b: Int): Int = sum(id, a, b)
def sumSquares(a: Int, b: Int): Int = sum(square, a, b)
def sumPowersOfTwo(a: Int, b: Int): Int = sum(powerOfTwo, a, b)

def id(x: Int): Int = x
def square(x: Int): Int = x * x
def powerOfTwo(x: Int): Int = if (x == 0) 1 else 2 * powerOfTwo(x 1)

2007年12月20日木曜日

J2EE 1.4

J2EE 1.4 で iBATIS を使った Bean Managed Entity Bean のサンプルを作ることに
なった。一つ一つ手で行うのは無謀なので NetBeans6 を使ってみる。

J2EE 1.4 なので以下の URL を参考にする。
http://www.netbeans.org/kb/41/
http://www.netbeans.org/kb/41/j2ee-tut/index.html

SavingsAccount のサンプルで Bean Managed Bean を作ってみる。Bean Module を
作り、Entity Bean を追加する。Entity Bean 内で Enterprise Resource ->
Use Database でデータベースを選択することになるが、サンプルは NetBeans4.1
ベースで当時のバンドルデータベースは pointbase で細かなところが違って
くる。

Use Database のダイアログでまず最初に指定するのは Reference Name だが、
これは app server ごとに異なる sun-ejb-jar.xml の中で JNDI で参照する
サーバのデータベースリソース (jdbc/mysqlTest01 等) につける名前だ。
この設定は NetBeans が勝手にやってくれる。選択対象は Sun Java System
Application Server Admin Console の Resources/JDBC/JDBC Resources の
エントリから選択することになる。このページには jdbc/* がリストされている。
これらのエントリは個々に enable/disable ができて Resources/JDBC/Connection Pools
のエントリを参照している。Connection Pools のエントリはいわゆるデータ
ソースで URL, user, JDBC driver 等の属性を持っている。PointBase を
復習するのも面倒なので MySQL を使ってみる。ウィザードを使えば設定は
比較的簡単だが、最初 XA driver を選んでしまい、トランザクション関連の
エラーになったので、ただのデータソースにした。コネクションプールに
対応した JDBC Resource も定義して、Entity Bean からは適当に名前を
つけたリソースを参照させる。

実際の DB ソーサのコードはベタな JDBC なのでサンプルからコピー。
ビジネスメッソッドもコンテキストメニューを使ったり、リファクタリングの
フィールドのエンカプセレイト機能を使って作っていく。ビジネスメソッドは
対応するものが *Remote.java のインターフェイスに定義されていなければ
ならないが、IDE が 'throws RemoteException;' を自動的につけてくれて
いないメソッドについては実行時にエラーが出たので、手でつけた。

Home メソッドも追加していくことになるが、コンテキストメニューで追加すると
Bean には ejbFindByLastName のようなメソッドができるが、戻り値を複数に
指定しておくとどうやら Home インターフェイス側には cByLastName のような
メソッドができる。コレクションで返すのでこういうネーミングになっているのかも
と勝手に納得していたが、そういうことではないらしい。名前はあっていないと
いけない。インターフェイスにあわせて ejbCByLastName とやってもだめ、
ejbcByLastName とやってもだめだった。Collection を返すことが名前から
わかることは悪いことではないと思い、Home 側を findcByLastName として
Bean 側を ejbFindcByLastName とすると動いた。この辺は Java Beans の
細かなところを調べればわかるのかも知れないが、その気力はない。
経験則としてキャメルケース・パスカルケースに1文字のワードというか、節を
持たせるのは良くないということを覚えておこう。

これくらいをクリアしたところで動くようになった。サンプルのクライアントで
一箇所だけ動かなかったのは remove の呼び出し。そのままでは文法エラーに
なるし、home 経由で呼ぼうとしてもエラーが消えない。今回はスキップ。


次に Roster のサンプルで CMP も確認しておく。このケースではもともと
関連のあるテープルを定義しておいて、それから New -> CMP Entity Beans from
Database... で作っている。若干強引に MySQL 上にテーブルを作ってこの処理を
すると関連のテーブルだけプライマリキーがないということで Bean が
作成されない。alter table _table_name_ add constraint primary key (field, field1,...)
で強引にやると作成されたが、ejb-jar.xml に CMP Relationships がまったく
現れない。

結局 Derby でテーブル作成の SQL が通ったので、それをもとにやってみると
動いたみたい。1:N や M:N の参照をわかりやすい名前に ejb-jar.xml で変更する
とそれがソースに反映されるとあったが、どうやらこれは動いていない。

次のステップとしていくつかの Bean に finder メソッドを EJB QL で追加して
行くところだが、このあたりは NB 4.1 と 6.0 の違いが大きいようで、このあたりで
今日は断念。

やっぱり、昔の EJB は面倒くさい...

2007年12月9日日曜日

Xcode

自作の C++ アプリケーションのリファクタリングの為に NetBeans6 に取り込んでみる。
その過程でコンパイラを聞かれるがデフォルトではLeopard にはコンパイラはないらしい。
(cc, c++ は not found になる。)Google を見て回ったところ Xcode というパッケージに
含まれているようだ。ユーザー登録をすれば ADC からダウンロードできるとのこと。
ユーザー登録の際に Apple ID とリンクできるようなことが書いてあったので、登録して
みると確認等の画面で日本語が文字化けしている。まあいいだろうということでXcode 3.0
をダウンロード。ディスクイメージをマウントしてみて出てきた PDF をみてみると
Leopard のメディアにも入っているらしいということが判明...

展開したものから XcodeTools.mpkg を入れてみる。特に問題なくインストール完了。


Macintosh:wtp$ cc
i686-apple-darwin9-gcc-4.0.1: no input files
Macintosh:wtp$ c++
i686-apple-darwin9-g++-4.0.1: no input files