CPSチェイン
追記:「東京Node学園#1「非同期プログラミングの改善」のエッセンス」というスライドで、似たようなテクニックが使われているのを見た(p.32-)。 そんなにスジは悪くないのかもしれない。
JavaScriptでは非同期的に関数を呼ぶことが多い。例えばimgタグのロードが終わったら次にAを処理して、それが終わったらBをして…など。
こういうときCPS形式でプログラムを書くはめになる。
func1(arg1, function(res1){ func2(arg2, function(arg3, res2){..})})
かようにJavaScriptでは関数リテラルがすこぶる扱いづらい -- 'function' とか 'return' とか {} のネストとか…あとカリー化するにも一苦労 -- JavaScriptプログラマはどう書くんだろう? こういう非同期呼び出しをうまく同期的に記述するためのsyntax sugarがほしい。 第一級継続があればうまいこと書けるのだろうけど。
さしあたり function(引数,継続) {} という形の関数を逐次的に呼び出す関数を書いてみた。
function chain() { function cpsbody(a) { if(a.length<2) { return a[0]; } return a[1](a[0],function(r){return cpsbody([r].concat(a.slice(2)));}) } var args = Array.prototype.slice.call(arguments); // making array from arguments return cpsbody(args); }
こんな風に使う。
function f1(arg,ifdone) { return ifdone(arg+" f1 "); } function f2(arg,ifdone) { return ifdone(arg+" f2 "); } alert(chain("start",f1,f2,f1,f2)); // "start f1 f2 f1 f2 " がダイアログボックスに出る