amachangの例題の場合もそうだが、これには一つ問題がある。

Kazuho@Cybozu Labs: Re: for 文を setTimeout に変換する
for 文を setTimeout に変換する - IT戦記の件。おもしろい。自分だったらこう書くかなと思いました。

ネストした場合、順番がぐしゃぐしゃになるのである。それを以下に示す。

プログラム:
出力:
エラー:

もし期待どおりなら、[0,0],[0,1],[0,2],[1,0],[1,1],[1,2],[2,0],[2,1],[2,2]とならねばならないが、見てのとおりそうならない。

これを回避するには、あらかじめ「ネスト」を解いたデータを用意しておき、それを一つずつ処理すればよい。

ここで、timeout_for()をこう書き換える。機能的にはtimeout_for()と互換だが、semanticsを変えてもう少し「forっぽく」してみた。Timeoutの間隔も変更可能だ。

function forTimeout(ms){
  return function(fi, fc, fn){
    var v =     (typeof fi == 'function') ? fi() : fi;
    var fcond = (typeof fc == 'function') ? fc
              : (typeof fc == 'number')   ? function(a){return a < fc}
              :                             function(a){ return true }
    var fnext = (typeof fn == 'function') ? fn
              : (typeof fn == 'number')   ? function(a){return a + fn}
              :                             null;
    return function(fblock){
      var iter = function(){
        if ( fcond(v) ) setTimeout(function(){
          fblock(v);
          if (fnext) v = fnext(v);
          iter()
        }, ms);
      };
      iter();
    };
  };
}

まず、使い方の実例。

プログラム:
出力:
エラー:

次にネストの例。

プログラム:
出力:
エラー:

こちらの方がわかりやすいかも知れない。3番目の引数が省略されている点に注意。for()でもfor(;;)のように中身を省略する記法に対応している。

プログラム:
出力:
エラー:

Enjoy!

Dan the JavaScripter