kilim で Java でもジェネレーター
Twitter と Erlang をきっかけに注目を集めるようになった軽量プロセス(とかマイクロスレッドとか)を Java で実現するためのライブラリに kilim があります。
夜中に突然 Java が書きたくなって、まだ、Examples を動かしてみた程度ですが、とりあえず Python のジェネレーターっぽいことができるのは分かったので記事にしておきます。暇と知識が増えたら、もうすこし突っ込んだ記事もあげる予定です(自信がないので今回、ですます調)。
ジェネレーターの例
では、本当につまらない例です。フィボナッチ数を求めるプログラムをどうぞ。
import kilim.Generator;
import kilim.pausable;
public class Fib extends Generator<Integer> {
public @pausable void execute() { // (1)
int fib1 = 0;
int fib2 = 1;
while (true) {
yield(fib1); // (2)
fib2 = fib1 + fib2;
fib1 = fib2 - fib1;
}
}
public static void main(String[] args) {
final Fib fib = new Fib();
for (int i = 0; i <= 10; i++) {
System.out.printf("Fib(%d) = %d\n", i, fib.next()); // (3)
}
}
}
面白い箇所の行にコメントで番号を振りました。
- 協調動作させたいメソッドは、このように
@pausable
アノテーションで指示します - 呼び出し側に制御を戻すときは
yield
メソッドを使います。Python 的 kilim.Generator
はjava.util.Iterator
とjava.lang.Iterable
インターフェースを実装しているので、こんなふうに使います。ますます Python
ビルドと実行方法
上記のソースコードを実行するまでの手順をまとめておきます。
まずは公式サイトからソースコードをダウンロードして展開、ビルドします。
% tar xvzf kilim-0.5.tgz.tar
% cd kilim-0.5
% ant
.jar
も作っておきましょう(2008/6/27追記:cd classes
が抜けていたので追記しました)。
% cd classes/
% jar cvf kilim-0.5.jar kilim
適当なディレクトリを作成して、さきほど作成した kilim-0.5.jar
とソースコードに含まれている asm-all-2.2.3.jar
をコピーします。また、上記のサンプルプログラムを Fib.java
という名前で、同じディレクトリに保存してください。
早速、Fib.java
をコンパイルします。
% javac -cp ./kilim-0.5.jar ./Fib.java
% ls
Fib.class Fib.java asm-all-2.2.3.jar kilim-0.5.jar
Fib.class
が作成されているのでコンパイルは成功しています。実行してみましょう。
% java -cp .:./kilim-0.5.jar Fib
############################################################
Task class Fib has either not been woven or the classpath is incorrect
############################################################
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1176)
at kilim.Task.errNotWoven(Task.java:188)
at kilim.Task.execute(Task.java:252)
at kilim.Task._runExecute(Task.java:291)
at kilim.Generator.next(Generator.java:47)
at Fib.main(Fib.java:22)
あらら … 不可解なエラーが出てしまいました。
種を明かすと kilim はバイトコード改変を利用しています。そのため、実行する前に、対象の .class
ファイルを kilim.tools.Weaver
で変換してやらないといけません(ソースコードのコメントを読むと、継続渡し形式(CPS)変換をしているらしい)。
% java -cp .:./kilim-0.5.jar:./asm-all-2.2.3.jar kilim.tools.Weaver -d . Fib
Wrote: ./kilim/S_I2.class
Wrote: ./Fib.class
なんだか .class
が増えちゃったけど、いまのところ気にしない…
% java -cp .:./kilim-0.5.jar Fib
Fib(0) = 0
Fib(1) = 1
Fib(2) = 1
Fib(3) = 2
Fib(4) = 3
Fib(5) = 5
Fib(6) = 8
Fib(7) = 13
Fib(8) = 21
Fib(9) = 34
Fib(10) = 55
今度は実行できました。フィボナッチ数が順番に出力されているのが分かると思います。