前提知識
ForのStepは普通、
Dim i as Long
For i = 1 to 10 Step 1
' なんやかんやあって桶屋が儲かる
Next i
こんな感じで使う。
Stepを省略するとデフォルトで「1」になる。
大体は省略していると思う。
たまに、データを削除するときとかは逆順で処理するので、以下のように使うことがある。
Dim i as Long
For i = 10 to 1 Step -1
' なんか消す
Next i
なん...だと...
今日やろうとしたのは、
非再帰のマージソートを実装しようとした以下のコード。
' 単位を倍々にしていってマージする。1, 2, 4, 8, ...
Dim i as Long
For i = 1 to map.Count Step i
' マージソートする
Next i
こんな感じで書いたら、ループが一回まわるたびにiの値も増えるから、うまく動くはず!と思っていたわけですよ。
ただし、実際は無限ループになってしまいフリーズしたんですね。
ステップ実行して処理を追ってみると、このときiは1のままで増えることはありませんでした。
つまり、Stepは0になってました。
どういうことだってばよ
わたしがしていた勘違いをCとかの構文で書くと
for (int i = 1; i <= map.length; i += i) {
// なんか処理
}
こうだと思っていたんです。
でも実際は
for (int step = 0, i = 1; i <= map.length; i += step) {
// なんか処理
}
こんな感じみたいです。
まとめ
つまるところ、以下の2点が理解できていませんでした。
- Stepの値はループごとに再評価されない
- ループ用のカウンタの初期化より先に、Stepの設定がされる
なるほどなー。
つーか前から思っていたけどVBのForってなんでわざわざ劣化させた仕様にしているんだろう。。。
使いにくくてしょうがないな。。。
ちなみに確認したのはExcelVBAです。
他のVB系でも同じっぽいけど動作確認はしていないのであしからず。