最近Hadoopを使うために5~6年ぶりにJavaをいじっています。
そんで、ちょっとばかり耐えがたいわけです。
例えばありがちな例題を挙げると、
["google", "検索エンジン","開発"]のようなタグ(文字列)のリスト(でも配列でもなんでもいい)を受け取って
[ {tag=>"google", enc=>"google"}, {tag=>"検索エンジン", enc=>"%E6%A4%9C%E7%B4%A2%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3"}, {tag=>"開発", enc=>"%E9%96%8B%E7%99%BA"} ]のようなハッシュテーブルのリストに変換しなさい。
ただしパーセントエンコーディングを行う関数(でもメソッドでもなんでもいい) uri_encodingは与えられているものとする。
こんなこと、Webアプリケーションではよくやるじゃないですか。
んで、実際Perlなんかでは結構簡単に書けて
my @tags;
#@tags : ("google", "検索エンジン","開発") はモデルとかから取得
my @ret = map{ { tag=>$_,enc=>uri_encoding($_) } } @tags;
まあこんな感じじゃないですか。
これをJavaで書くとこんなんなります。
List<String> tags;
//tags の中身はモデルとかから取得
List<Map<String,String>> result = new LinkedList<Map<String,String>>();
Iterator<String> i = tags.iterator();
while(i.hasNext()){
String tag = i.next();
Map<String,String> m = new HashMap<String,String>();
m.put("tag", tag);
m.put("enc", uri_encode(tag));
result.add(m);
}
こんなにも・・!!こんなにも苦しいのならば型などいらぬ!!
とか暗黒面に落ちそうになってしまいました。
これ以外にもWebアプリケーションなんかだとクエリーが全部文字列で来るけど、妥当性検証のためにintに変換してintと比較とかするのもJavaだとクソ面倒です。(例えば今表示している0件目ページの次の100件を表示するためにoffset=100とかをGETパラメタで受け取るとかそういう場合。こういうのはフレームワークが吸収してくれるんでしょうか?)
そんで、Javaのリハビリとしてバリアント型を作ってみました。
どうせWebアプリケーションのコントローラとかHadoopでやるようなテキスト処理だと、使う型はせいぜい文字列、整数、日付、リスト、ハッシュおよびそれらの組み合わせと相互変換なわけです。
こういう簡単なことは簡単に書けるように、これらを全部つっこめるvarクラスを作って、例えばさっきの問題ならこんな風に書けるようにするのがゴールです。(lambdaはファンクタのための抽象クラス、$はhashとかmapとかの関数的なクラスメソッドを入れておくためのクラス。)
var tags = $.list("Google", "検索エンジン", "開発");
lambda tag2hash = new lambda(){var f(var tag){
return $.hash( "tag", tag, "enc", uri_encode(tag) );
}};
var result = $.map(tag2hash, tags);
んで、書いたのがコレ(var.java)。
1ファイルにまとめるために無理やりpublicじゃない内部クラスを大量に使ってますが気にしないでください。
varクラス(クラス名が大文字で始まらないけど勘弁してねw)にmainついてますが、もうJavaソースには見えませんw
JavaでhackするというよりJavaをFxxkしてる気分になりました。
public class var {
public static void main(String[] args){
lambda square = new lambda(){var f(var v){
return new $(v.i() * v.i());
}};
lambda say = new lambda(){var f(var v){
System.out.println(v.display());
return var.NIL;
}};
//文字列
var name = new $("James");
say.apply(name);
//文字列と数値の混合リスト
var ls = $.list(1, "2", 3, 4, 5);
//リストの各要素を2乗したリストを返す(数値は自動変換)
say.apply($.map(square, ls));
//cdr(笑)
say.apply(ls.cdr());
//入れ子のハッシュテーブル
var hash = $.hash(
"John", $.hash("sex", "male", "age", 20),
"Eva", $.hash("sex", "female", "age", "unknown"),
"Abe", $.hash("sex", "unknown", "age", "25")
);
say.apply(hash.get("John").get("sex"));
say.apply(hash.get("Nobita").get("sex"));
say.apply(hash.keys());
say.apply(hash);
}
}
このmainを実行するとこんな感じ。
$ java variant/var
"James"
(1 4 9 16 25)
("2" 3 4 5)
"male"
nil
("John" "Abe" "Eva")
(("John" => (("age" => 20)("sex" => "male")))("Abe" => (("age" => "25")("sex" => "unknown")))("Eva" => (("age" => "unknown")("sex" => "female"))))
会社に来るついでにHxH25巻を買って読んだ。
もちろんジャンプ本誌でも読んでる、どころか各週3回は読み直したのになんでこんなに面白いのか。
あまりに面白いのでなんか電車の中で涙ぐんでしまった。はたからみたらキモかったと思う。別にオチはないけどおまえらもっとHxHを読むといいと思いました。
HUNTER×HUNTER NO.25 (25) (ジャンプコミックス)

価格 : ¥410 (税込)
メーカー : 集英社
→Amazonで詳細を見る
→ECナビリストで詳細を見る
おすすめ度 :

レビュー
ざーっと読んだけど、4,5章は演習問題をがっちりやらないと絶対理解できないと思って、そのうちやろうで放置してしまっていた。
なんとかするために社内で何人かに声をかけて社内でSICP読書会をすることにした。
第一回は1/16(水)
計算機プログラムの構造と解釈

価格 : ¥4830 (税込)
メーカー : ピアソンエデュケーション
→Amazonで詳細を見る
おすすめ度 :


