僕はプログラミングに魅せられて,それからプログラムを作る構成要素に強い興味を持ってきました.たとえば,日本語だったらまず「ひらがな」があります.ひらがなと分かち書き(単語と単語の間に空白を入れる)でだいたいの日本語が表現できます.話し言葉と一緒ですね.そのひらがなに「漢字」や「カタカナ」「アルファベット」などを追加して表現力を増してきました.たとえば面白いのは「本気」と書いて「マジ」と読むみたいなやつで.この面白さはひらがなだけでは表現できないですよね.あとローマ字というのもありますね.
同じように,プログラムを形作る構成要素もいろんな理由で発明されてきました.人間に作りやすいとか,いままで作ったことのない難しいプログラムを簡単にするとかです.
なぜ,このシリーズを書こと思ったかというと,構成要素はたくさんあってちゃんと進化しているんだよ,ということを広く知ってもらいたいからです.
ところが,プログラミング教育のブームの影響で「順次」「反復」「条件分岐」という言葉を目にするようになりました.これらもプログラムの構成要素ですが,確かに大事だけど,全体像の中でどういう位置付けななんでしょう.「これがプログラミングの基本だからしっかり覚えておいて欲しい」というのは僕はちょっと簡単には言えないんですよ.
で,最初に説明したいのはGOTO文です.基本要素と言われている「反復」と「条件分岐」ですが,GOTOはそれをさらに分解したものです.
GOTOが出てくるのは,機械語からです.機械語はコンピュータが直接わかる言葉ですね.機械語っていうから,難しいのかと思われがちですが,その逆でとても簡単でわかりやすいです.
その前に機械語をちょっと説明しますね.コンピュータの動きの速さの説明でクロックというのがあります.この原稿を書いている僕のマックはプロセッサが2.5GHzとなってますが,これがクロックの速さです.Gは10億,Hzは1秒間の回数,なので1秒で25億回という驚きの速さです.で,機械語は命令を1列に並べたものですが,この1つの命令が動くのがこのクロックの速さになります.厳密には1つの命令に数クロックかかったり,逆に1クロックで複数の命令を実行したりということもありますが,25億が10億になるくらいの違いです.脱線しますがコアが複数あるプロセッサは,同時に命令をコア分だけ実行できると言うことです.
で,1クロックで実行できるものを機械語の1命令としましたが,これは一言でいうと,回路で表現できるもの,ということになります.例えば足し算をする回路とかかけ算をする回路というのが作れます.そういうのが機械語の命令になります.3つの数を足したいときは,2つの足し算に分解できますから足し算命令を2つ使います.
機械語はメモリー上に1列にならんで入っています.その先頭の番地から実行させて,1つの命令の実行が終わったら,次の命令を実行するという風に動いてゆきます.
メモリーの番地は数字で表されていて,いまどこの命令が動いているのか,ということを指し示す「プログラムカウンタ」というレジスタがあります.命令は順に並んでいるので,次の命令を実行するためには,その数字が1つずつ増えるので「カウンタ」という名前になっているんでしょうね.
で,やっとでてきたGOTOですが.このプログラムカウンタに好きな数字をセットできる,というものです.
1000 2をたす
1001 3をかける
1002 GOTO 1000
最初,プログラムカウンタには1000が入っていて,「2をたす」という命令を実行してプログラムカウンタは1001になります.次の命令は「3をかける」でこれを実行してプログラムカウンタは1002になります.つぎの命令が「GOTO 1000」なので,プログラムカウンタを1000にします.すると,また最初にもどって「2をたす」ことから繰り返します.このプログラムは延々と「2をたして」「3をかける」を繰り返しますね.
これだけだと足りなくて,もう1つ「条件付きGOTO」というのがあります.「GOTO」はいつも飛ぶのに対して「条件付きGOTO」はある条件のときだけ飛びます.たとえば,
1000 10にする
1001 3をひく
1002 ゼロより大きければ GOTO 1001
1003 3をたす
10から3を3回引いたら1ですが,もう一度引くと-2になって条件「ゼロより大きければ」が成立しないので次1003に進みます.1003では引きすぎた3をたしているので,これは10を3で割った余りを計算してます.
もっと詳しくコンピュータの中身のことを知りたい人は,ぜひ僕の新刊「さわるようにしくみがわかるコンピュータのひみつ」をお読みください.
「反復」は「条件付きGOTO」で作れるのがわかったと思いますが,「条件分岐」はどうでしょうか.こんなかんじでやります.
1000 条件の計算
条件付きGOTO 2000
条件が成立しないときにやること
...
GOTO 3000
2000 条件が成立したときにやること
...
3000 両方の処理が合流する部分
ここで2000とか3000という具体的な数になってますが,もちろんここは間に入る命令の数によってこの番地が変わってきます.番地がずれるととんでもないことになるので,機械語でどこに飛ぶのかという計算は面倒でした.
番地を数字で表すからこんな風に間違えやすくなるわけで.数字の代わりにラベル(文字)で表すやりかたが発明されます.上で2000とあるところにL1, 3000のとこはL2としておきます.実際に間にはいる命令が決まるとL1は何番地,L2は何番地と決まります.つまり,全体を2回たどる必要があるってことですね.
GOTOがその後嫌われたのは,プログラムがぐちゃぐちゃになるからです.ここまで行って次にどこに飛ぶのかがわかりにくい.それでも数字のときは,上に戻るのか下に進むのかがだいたいわかったのですが,ラベルになっちゃうとそれもわからない.そもそも,人間はなにかモノに名前をつけるのは慣れてますけど,こういう,時間軸上の状態に名前をつけるのは慣れてませんから,ラベルにわかりやすい名前もつけにくい.
そこでGOTOをつかった典型的なパターンに名前をつけて,そういう苦労を隠そうということで発明されたのが「反復」と「条件分岐」と言われるものになります.つまり裸のコンピュータに1つ皮を被せています.
さて「GOTOをつかった典型的なパターン」と言いましたが,これも実はそんなに簡単じゃありません.GOTOはとても柔軟でいろんな使い方ができましたから,それらの使い方を全部カバーするのはなかなか大変です.まず「反復」に関して3つあります.
ポイントは,繰り返しの中で実行する部分と,繰り返しをやめる判断をいつするかということです.
1つ目は,最初に繰り返しをやめるかどうか判断する場合です.たとえば,
メールを1通ずつ読むときは,メールが届いているか調べて,あれば「メールを読む」を繰り返します.この場合,最初にメールが1通も届いていなければ1回も繰り返しません.
2つ目は,最後に繰り返しをやめるかどうか判断する場合です.たとえば野菜をフライパンで炒める場合です.野菜をかき混ぜる,野菜が炒めたりなければ繰り返す.このときは,最初に1回は野菜をかき混ぜることをやります.これあんまり使わないですが,時々出てくるんで無しってわけには行かない.
3つ目は,これが意外とわすれられるのですが,繰り返しの途中でやめる判断をする場合です.基本は1つ目と同じと考えて良いんですが,条件判断を簡単な計算でできない場合です.
繰り返し開始
条件判断のための複雑な計算
条件判断(条件が成立したら繰り返しを抜ける)
繰り返す内容
繰り返し終わり
こんな感じですが,これは1の方法だけでやろうとすると
条件判断のための複雑な計算
条件が成立する間繰り返す
繰り返す内容
条件判断のための複雑な計算
繰り返し終わり
ここで,繰り返しの条件が逆になっています.上は,成立したら抜けるのに対して,下は成立したら繰り返すのです.そういう条件がどっちだったか間違うのはよくやります.それから「条件判断のための複雑な計算」が2回出てきているのも気持ち悪いですね.
それから,よくあるのが決まった回数だけ繰り返すという構文です.これをGOTOでやるためには,繰り返しの回数を数える方法を自前で用意しなければなりません.
条件分岐に関してもいろいろとありますがちょっと長くなったので,次回にします.あと,機械語は一番簡単なのになぜ難しいのか,という話も必要ですね.
さて.この調子で説明していくと,全部で何回くらいまで続くのか.でも,こういう説明ならいくらでも書けるので,ちょっと続けてみましょうかね.