MIS.W 公式ブログ

早稲田大学公認、情報系創作サークル「早稲田大学経営情報学会」(MIS.W)の公式ブログです!

プログラミングパラダイム【アドベントカレンダー16日目】

新歓アドベントカレンダー16日目を担当します、48代プロ研会長のtomiokaです。今回は新入生向けということで、「プログラミングパラダイム」というモノを紹介します。この記事がこれからプログラミングの世界を探検する人の案内板になればいいなあと思います。

ただし、平易な説明を心がけているため、ここで用いられている名称や説明が学術的に正しいかどうかは保証できません。気になったら自分で調べてみよう!(丸投げ)

プログラミングって?

この記事の読者にはプログラミング初心者を想定しているので、まずはここから説明しなければならないでしょう。といっても、本題ではないのでなるべくサクッと済ませましょう。

「コンピュータ」とは、その名の通り計算を行う機械です。コンピュータは計算を行う能力を持っていますが、それを自ら行使することはありません(少なくとも今は)。その能力をうまく使ってやるのがプログラマの仕事です。

しかし、コンピュータは頑固で融通の利かないシャイなあんちくしょうなので、その計算能力の使い道を教えてあげるのにもちょっとしたコツが要ります。その伝達手段こそがプログラミングです。より具体的に言えば、ソースコードと呼ばれる計算手順を記した書物を書くことがプログラマの仕事になります。

さて、皆さんは人に何かを伝えたいときどのように説明しますか? より具体的に一つ一つの事柄を詳説しますか? 例え話を使いますか? それとも、数学的モデルを導入して厳密に証明するのでしょうか。このように、「説明する」こと自体も何らかの枠組み(パラダイム)に基づいて行われます。プログラミングにおけるその枠組みをプログラミングパラダイムと呼びます。やっと出てきましたね。

プログラミングパラダイムについてざっくり理解しておくと、知識を整理するのにとても役に立ちます。現在では大小様々なプログラミングパラダイムが存在しますが、ここでは主なものをいくつか紹介します。これらが全て理解できたのなら、プログラミングで苦労することはもうほとんどないでしょう。

命令型プログラミング

計算手順を表現するとき、一番単純で直感的なのは必要な操作を順番に書き連ねていくことです。コンピュータに対してああしろこうしろという命令を記述していくやり方は、命令型プログラミングと呼ばれます。命令型プログラミングで書かれたプログラムの例を見てみましょう。

100: LET X = 0
110: LET I = 0
120: I = I + 1
130: X = X + I
140: IF I < 10 THEN GOTO 120
150: GOTO 160
160: PRINT X

このプログラムを実行すると1から10までの和が出力されます。命令型プログラミングで書かれたプログラムは通常上の行から下の行に向かって一行ずつ実行されます。大体一行に一つ「命令」が記述されています。例えば、120行は「Iに1足したものを新しくIの値としろ」という命令であり、140行は「Iが10より小さいなら120行から実行しろ」という命令になります。

構造化プログラミング

命令型プログラミングはコンピュータにとってはわかりやすいのですが、人間にとってはプログラムがどのような順番で実行されるのか非常にわかりにくいものになってしまいます。そこで、プログラムを条件分岐や繰り返し等によって記述し、その構造をわかりやすくするのが構造化プログラミングです。

var x = 0
for i in 1...10 {
  x += i
}
println(x)

このプログラムを実行すると1から10までの和が出力されます。これでわかりやすくなったのか? と思う人もいるかもしれませんが、より複雑な制御構造(サブルーチンとか)を用いたコードでは実行順序があちこちに行ってしまうので、見通しが良くなるということは想像以上に威力を発揮します。

オブジェクト指向プログラミング

さて、命令型プログラミング(と構造化プログラミング)は手続きを記述するという方向から考えるものです。しかし、私たちは普段「動作」ではなく「モノ」を主体に考えています。例えば「打つ」という動作を考えてみましょう。何をイメージしたでしょうか? バットでボールを打つとか、そういったものでしょう。とにかく、私たちは「バット」といった「モノ」なしに「打つ」という動作を考えることは難しいということです。こういった「モノ」をオブジェクトといい、オブジェクトを中心としたプログラミングパラダイムオブジェクト指向プログラミングと言います。

では、例を見てみましょう。

class Ball {
  int weight;
  int radius;
}
class Bat {
  int weight;
  int length;
  void hit(Ball ball);
}

Bat mybat = new Bat();
Ball ironball = new Ball();
mybat.hit(ironball);

せっかくなのでバットとボールの例にしました。今までとかなり毛色が違うので、面食らったかもしれません。ここで詳しく解説すると締め切りに間に合わなくなってしまうので、気になった人は各自調べてみましょう。ただし、新入生のみなさんわからなくても全く問題ありません! これからゆっくり学んでいきましょう。オブジェクト指向プログラミングの利点としては自然にアイデアをプログラムに落とし込めることとかコードの再利用がしやすいこととか色々あります。ただし、何でもかんでもオブジェクト指向にすればいいというものでもありませんが。

関数プログラミング

最後に、関数プログラミングについて紹介しましょう。プログラムは小さなプログラムを組み合わせて作られます。ほとんどのプログラムでは、この小さなプログラムの単位を「関数」と呼びます。厳密には数学でいう関数とは異なりますが、もともと数学の概念を参考にしていることなどからそう呼ばれます。

関数とは入力に対応する出力を与えるものですが、この入力として関数を与えるとどうなるでしょうか? このような関数を高階関数と呼び、この高階関数をもとにした様々な技法を総称して関数プログラミングと呼びます。

それでは、それっぽいコード例でイメージを掴んでみましょう。

var list = [1, 2, 3, 4]
list.map { x => x + 10 }  // [11, 12, 13, 14]
list.map { x => x * x }   // [1, 4, 9, 16]

mapはリストのそれぞれの要素に引数として与えた関数を適用するものです。同じリストでも、与える関数によって結果が変化しています。関数がデータとして扱えるようになると、参照透明性やデータ型などが問題になってきます。そのあたりを厳密にしたものは純粋関数プログラミングと呼ばれたりします。関数プログラミングから発展した概念はたくさんあり、メジャーな言語は相当数それを取り入れていますので、勉強しておいて損はないでしょう。


ここまで主なプログラミングパラダイムを紹介してきました。もちろんここにあげたものが全てではありませんが、プログラマとして技術をつけたい! と思っている人は最低限知っているだろうというところを選びました。

また、それぞれ分けて紹介しましたが、だからといってそれぞれのパラダイムが完全に独立したものであるというわけではありません。どのパラダイムにも得手不得手がありますし、それぞれを共存させることもできます。私も適材適所で使いこなせるようになれたらいいなあと常日頃思っております。

この記事を読んでちょれーなーと思った人、道は長く険しいと思った人、ちょっと面白そうかも? と思った人、プログラミング研究会にてお待ちしております。機会があれば気軽に話しかけてください。