見出し画像

No. 7 C++で学ぶ最適化ソフトウェア開発: 古の呪文“GOTO”の恐怖

※忙しい人はタイトルと太字部分だけ読めばOK

 開発記として始めておきながら,なんかエッセイ風になってきましたね.まぁ気にせずいきましょう.今回はGOTOの話題をとり上げてみます.


GOTOとはワープツールである

 今回のプログラム作成において,かなり参考にしている本があるということはお伝えしたと思います.かなり充実した書籍で,内容だけ見れば絶版になっているのが不思議なくらいです.ただこの本,古いんすよね.書かれたのは1991年だし,解説やサンプルプログラムにおける使用言語もFORTRAN77というこれまた古い言語です.このサンプルコードの中で頻繁に登場する文言こそ,今回取り上げる“GOTO”になります.「後藤」ではなく「ゴー・トゥー」と読みます.読んで字の如く,「〜に行け」という意味です.要は,ソースコードの中で上下どこかしら指定した場所への自在なワープを可能とする命令な訳ですね.ただ,GOTOは現在使用が推奨されておらず,いわば禁止カードや禁止魔法みたいなものです.その理由は,「バグを生みやすく」「第3者から見て意味不明になり」「上級者しか使いこなせないから」あたりだと思います.

GOTOタイトル

↑みたいな感じで,コード中にいきなりGOTOを入れたとします.そうすると,途端にタイトルに戻って頭から読み返さないといけなくなるのです.たちまち無限ループの完成です.筆者にしてみれば,タイトルからGOTOまでに大事なことが書いてあるので頭がおかしくなるまで読み返して欲しい,みたいな意図があるのかも知れません.でも,第三者から見たら意味不明ですよね.しかもかなり自由度が高く一見便利なので,ついつい使っちゃうんです.でも,そのうちどこからどこに飛ばしたか,どこに影響が出るかみたいなことが整理しきれなくなり,気づいた時には開発者しか分からないコードができたり,最悪の場合完成する前にコードが破綻するなんてことも起こり得る危険なおまじないなのです.
ちなみに,上にあるGOTOは

if(ここまでを読んだ回数が3回未満){
 GOTOタイトル;
}else{
 続きを読む;
}

のようにすれば無限ループを回避できます.3回読んだらもういいよ,という意味ですね.でも,基本的には使用を避けたほうが無難です.一つで済めばもちろん良いのですが,2つ3つと使ってしまうともう開発者以外には意味不明という事態も容易に想像されます.

サンプルコードで多用されるGOTO

 参考書があるので,サンプルコードも示されているというのは上でも述べました.筆者もこれを横目にチラチラ見ながら自分のコードを組んでいるわけですが,一つ(ひとつじゃないけど!)問題があります.そう,GOTOの多用です.とにかく出てくるGOTOが,コードをどんどんワープさせます.下にワープさせるならまだ良いのですが,上に向かっても平気でワープさせてきます.つまり,もう終わったと思っていた処理をGOTOでワープしもう一回やらせたりするのです.すると,途端にやっていることの意味が分かりづらくなるのです.筆者が最適化ソフトウェアを組むのは実は2回目だということはすでに触れましたが,1回目の開発時はこのサンプルにあるGOTOを極力活かしたコーディング(コードを書くこと)を行いました.古代の力と無理に争わず,古の禁止された危険な呪文を使いまくったわけです.ただし,GOTOのワープ先はかなり制限させてもらいました.GOTOがワープできるのは,予め符号を打ってある部分だけです.転移魔法陣みたいなもんですね(?)で,この転移魔法陣がとにかくいろんなところに張り巡らされているので,ワープ先として使用しないものはとにかく潰しておきました.「使わんのに魔法陣を置いたらどれがどれだか分からんだろ!」みたいな感じですね.ただ,見返すとやっぱり分かりづらいのです.何せ,上から読んでいっても戻ってくるなんてGOTOが現れるまで分からないのですから.ということで,今回はこのGOTOを封じて書こうとしています.

GOTOは何で代用する?

 GOTOを使用しないとなると,全く同じ機能を別の何かで補う必要が出てきてしまいます.今回は,whileによる無限ループやif文による条件分岐で代用しています.whileは「while(条件){処理}」みたいな形で使い,設定した条件が満たされている間は{ }内の処理を繰り返す,という命令になります.ifについては知っている人も多いかもしれませんが,「if(条件){処理}」のように書いて条件が満たされれば処理を行うということですね.まず,下に送るGOTOはifで処理できます.

cout << "ちょっと飛ばすよ!";
if(a==b){
   goto 10;
}
cout << "a=bならここは表示されないよ!"; // ここは飛ばされる
10 cout << "ここまで飛んでくるよ!";

ちなみに,C++ではGOTOではなくgotoと書いています.大文字と小文字を区別するので,これは言語の都合です.上のコードは,goto 10の命令が来たら問答無用で「10 cout << …」のところにワープします.なので,aとbが同じ値なら(a==bのところ)間に書いてあることは全部すっ飛ばされるわけですね.もちろん,このコードはサンプルなのでそもそもgotoで処理する必要がないのですが,まぁその辺は甘く見てください.で,下のコードは上のgotoと同じ処理をします

cout << "ちょっと飛ばすよ!";
if(a==b){
 cout<< "ここまで飛んでくるよ!";
}else{
 cout << "a=bならここは表示されないよ!"; //
}

gotoのワープが下向きに飛んでいるので,if(…){処理1}という「もしも…なら処理1をせよ」を実行する命令で代替可能なわけですね.こんな感じで無事に処理できました.ただ,GOTOの怖い所は上にもワープできるということなのです.例を見てみましょう:

100 a=a+1;
if(a<100){
 goto 100;
}

このプログラムはaに1ずつ足していくだけの単純なものなのですが,aが100に足りない間は「上に戻れ!」を繰り返すループをgotoで実現しています.上にワープするgotoの例ですね.これをgotoなしで実現するにはどうするか?ということですが,例えばこんなのが考えられます:

while(a<100){
 a = a+1;
}

最初からこう書けよwhile(条件){処理}は「条件が満たされる間は処理を繰り返せ」という命令なので「aが100より小さい場合はひたすらaに1を足し続けなさい」という仕組みが完成しています.aが100以上になると(条件)が満たされなくなるので自動でループを抜けるため,最初のgotoワープでやっていることと全く同じ結果が得られるような置き換えになっているわけですね.

GOTOは適切に置き換えるとわかりやすくなる

 簡単な例ばかりですが,古の呪文GOTOを置き換える例をやってみました.GOTOを用いると指定した番号を打った行にワープできて便利なものの,開発者はその番号をプログラム中から探索するところから始めなければいけません.一方それらを置き換えてあげると,基本的に番号の探索は不要になりコードの仕組みをより簡単に把握することができるようになるでしょう.

開発中の最適化ソフトウェアではどうなっている?

 さて,本連載はC++で学ぶ最適化ソフトウェア開発なので,記事の話題はその開発過程から切り出してお送りしています.繰り返しになりますが,元ネタは1991年発売のFORTRAN77による最適化プログラミングで,そこに掲載されているサンプルコードをもとに筆者が2012年ごろにリメイクしたものをさらにリメイクしています.2012年はGOTOを甘んじて受け入れたと書きましたが,今回の開発では徹底的にGOTOの使用を封じ,最後まで計算が回るようになった現在でもGOTO使用回数は0となっています.ちらっとお見せしましょう:

開発中コードにおけるGOTO回避のコーディング

先ほども出てきたwhileを使用した回避例ですね.開発メモにある「GOTO 11」というのがサンプルコード中の指示で,それと同じ動作をするようにC++上のアルゴリズムを組んでいます.whileのあとの(true)というのは「本当」という意味で,これを打つとwhileはたちまち無限ループになります.で,無限ループを抜ける条件をifで書いておき,適切にループの外に飛び出すことでGOTOと同じ動作にしているわけです…これ,伝わるのかしらww

このような置き換えをコードの全てで行っております.

今回のまとめ

 今回はGOTOの置き換えについて書いてみました.おそらくですが,最近は最適化ソフトウェアを自分で組む人は減っているんじゃないかと予想しています.というのも,PhythonやOctave,MATLAB(有料)などですでに整備された最適化ツールが手軽に使用できちゃうんですよね.自分で組まなくても簡単に使えちゃうという.ただ,これらを考えなしに使用するのはお手軽な反面,中身がブラックボックスなので詳細がわからないという欠点があったりします.その反面,全てのソースコードを自分で書いた経験があれば,コードを見ながら理論的にはどんなトラブルでも遡って原因の特定ができるはずです.もちろんこれを読んでいる人に最適化ソフトウェアのコーディングに挑戦して欲しいなどとは全く思っていませんが,筆者の取り組みをきっかけに,人の作ったものを使うということの意味や自分でコーディングすることの強みを心に留めてくださればいいなと思います.

K. HISAKAWA


いいなと思ったら応援しよう!