Rubyの標準ライブラリをPureJavaで書いてみる (1)
これは11/27に書いたものの続きです。
Rubyの記述力の高さをJavaでも実現してみたいので、RubyのつもりでJavaのコードが書けるようなライブラリを作ってみます。既にどこかで同じかそれ以上のものが作られていたりするかもしれません*1が、JavaSE5.0から導入された新しいJava言語機能を使わないと実現が難しいため、副産物としてこれらの新機能についてちょっと勉強になったりしています。
動的言語っぽさを出すためには総称型とオートボクシング/アンボクシングは不可欠ですし、組み込み関数っぽさを出すにはstatic-import機能が手放せません。foreachや可変長引数も捨てがたいですね。無理やり注釈も使ってたりするので、残りはEnumだけです。今のところ使い道が思いつきませんが、たぶん使うことになるでしょう。
成果物については、ある程度形になったら公開するかもしれません。
これはJavaとしてはおそらく邪道な方法です。ネタとしてご覧ください。
現在の状況
- Enumerable,Arrayが80%程度完成。blockの実現方法はもうちょっと検討したい。
- Kernel,Range,Str(String),Regexpを作り始める。
- I/O関連は見送り。やるとしても後回し。
- 他は今のところJava標準のものを使う。
サンプル
本体は未だ整理できていないので、使い方だけ。
Ruby
array = Array[1, 2, 3] a = [1, 2, 3] range = Range.new(1, 3) r = (1..3) p array, a, range, r [3, 4, 5].reverse_each do |item| print item end puts (1..4).to_a.shift def collect() Proc.new do |item| item * 2 end end print a.collect(&collect) puts
Java+"lib.ruby"
import static lib.ruby.Kernel.*; import lib.ruby.*; import lib.ruby.Enumerable.*; public final class Main { public static void main(String[] args) { Array<Integer> array = array(1, 2, 3); Array<Integer> a = a(1, 2, 3); Range<Integer> range = range(1, 3); Range<Integer> r = r(1, 3); puts(array, a, range, r); a(3, 4, 5).reverseEach(new Callable<Integer>() { public void call(Integer element) { print(element); } }); puts(range(1, 4).toA().shift()); Collectable<Integer> collectable = new Collectable<Integer>() { public Integer collect(Integer element) { return element * 2; } }; puts(a.each(collectable)); } }
$ # ruby/java両方 [1, 2, 3] [1, 2, 3] 1..3 1..3 5431 246 $
*1:潜在的にそれを覚えていて、無意識に作り直しているんじゃないかと疑っています。