相互再帰関数でポモドーロタイマー作ってみました

こんにちは

 

仕事上、Excelを使うことが多く、今回はポモドーロタイマーをExcel VBAで作ってみました!

 

ポモドーロタイマーとは

 

ググればすぐ出てくるので詳細は省きますが※1

要はX分作業、Y分休憩をZセット、みたいなタイマーですな。

 

VBAでやるには?

 

取っ掛かりもなにもないときは、まず検索ですね。「VBA タイマー」で検索すると、ストップウォッチの作り方が書いてあり、OnTimeメソッドを再帰させれば、設定時間おきにサブルーチン実施する云々。他の言語でよくあるThread的なことはできなそうなので、この機能使ってやってみるか!

 

で、最初作ったコードがこちら。

f:id:Shoriencohol:20191226211814j:plain

。。。あまりのif文の多さと再帰記述の多さにピントがぶれております。。。美しくない。。。裏でこんなに頑張られるとポモドーロやってても頭に「あー今4回めの再帰文呼び出してるんだな。さっきのポモドーロはあのifで殺されてて。あれ、一体今何セット目?」とか考えて集中できなそう。。。

 

と、悩んでいたところ、SNSより神の手が。

相互再帰させるのはどうですか?(マストドン、とりぽかさんより) 

 

 

おお!再帰を学んだばかりだし手を出すのをためらっていた相互再帰関数!確かに、作業と休憩の2モードがあるから、2関数を別のサブルーチンにすればうまくいきそう!!

実は、コードのヒントはもらいましたが、見ないで「相互再帰」という言葉だけでなんとか正解に行きつけるようにコーディングしよう!そして家に帰って(会社でコードいじってた)、いざVBAを開くと。。。

f:id:Shoriencohol:20191226212903j:plain

あー盛大に文字化けしてますね。。。自宅PCのOSが中国語ベースなので、全角文字が盛大に文字化け。でも、「中国語か文字化けかわからない」という突っ込みもあり。た、たしかに。。。まあ、諦めて英語にするか。。。

 

相互再帰できました!

 

といことで、最終的にできたコードがこちら。

f:id:Shoriencohol:20191226213130j:plain

スッキリした。。。if文の化け物みたいなコードが、各関数1ルーチンのifとたった2回の再帰関数の呼び出しで実現できるなんて。。。場合によるとは思いますが、再帰の凄さを認識しました。。。

 

とはいえ。。。

 

OnTime関数はサブルーチン自体の実行が終わっても裏で動作しているし、それを動的に止める方法はExcel強制終了以外にない、ということもあり、コードミスが有ったときや複雑なコードになった場合のデバッグは厳しそう、というなんとなーくの思いを持っていたら、

複数プロセス(or スレッド or プロシージャ)でくるくる回すと、
バグったときに追いかけるのが大変なので、僕だったらこんな感じで書くかもです。

(1):TrainningTime回数トレーニング繰り返す
(2):そのあと、RestTime回数休憩を繰り返す
(3):SetTime回数(1)(2)を繰り返す

繰り返しは
for rm.text = t.text -1 to 0 step -1
...
next rm.text
みたいにかけないかなぁ(やってないのでわからない。できなければループ変数をiでとって適宜rm.textに表示のため書き戻す感じで)
そうするとApplication.OntimeでなくてApplication.Waitとかでいけたりしないかなと。(sleepが使えたら一番なんだろうけどVBAには標準ではないっぽい。) 

マストドン、ぷらいずあうと さんより

そうですよね。自分も、再帰を学んだばかりだから使ってみたさでやったけど、自分で考えつくのはloop分だし、まあ、個人で使うならまだしも、品質保証必要になったら再帰ってなかなか書きにくいかもなーとか思いつつ、そういういろんなこと考えながらコードって書かなきゃならないんだな、とか思いつつ。

 

日々、勉強ですね。

 

ではではー

 

※1 私が書きたいように書いているので、しょっちゅう大事なところでも省きます。