短気
コンピューターが怠慢な時に感じる怒り。この怒りの持ち主は、今ある問題に対応するプログラムにとどまらず、今後起こりうる問題を想定したプログラムを書く。少なくともそうしようとする。よって、プログラマーの第二の美徳である。
-- Larry Wall (翻訳:小飼弾)

プログラマーの怠慢ぶりを一通り見たしたところで、今度は短気(impatience)ぶりをまとめることにしましょう。

「名前を付けて保存」再び

前回の最後では、九九を表示するプログラムを書きました。

for (var x = 1; x < 10; x++){
  for (var y = 1; y < 10; y++){
    p(x + ' × ' + y + ' = ' + x * y);
  }
}

これを別の機会に使いたいときには、またこのプログラムをコピーしてペーストすれば良さそうです。が、ちょっと待ってください。まだこのプログラムは5行しかありませんが、何千行も何万行もあるプログラムを、ただ単に同じことをするためにコピー&ペーストを繰り返すのはまだ怠慢が足りなさそうですし、そもそも以前書いたプログラムをすぐに利用できないことに耐えられるほどプログラマーの気は長くありません。

ここでレシピを思い出してみましょう。「カレールウを作る」ということを、わざわざ「種芋を畑に植え、肉牛を肥育し、ジャガイモと牛肉を手に入れ....」などと書く人がいるでしょうか。一言で「カレールウを作る」と言いたいはずです。具体的にどうやってカレールウを作るかは、一度だけレシピに書いておけば、あとはレシピは見るものであって書くものではないはずです。

それを可能にするのが、functionです。

書き方は至ってシンプル。

function function_name(){ // プログラムに、function_nameという名前を付ける
  // プログラムをここに書く
} // おしまい

これを使うときには、こうします。

function_name();

では、実際に動くかどうかを確かめてみましょう。

プログラム:
出力:
エラー:

たしかにうまく行ったようです。これで、九九を表示したいときには、一言print_kuku()と言えばいいわけです。ちなみに、名前に英単語しか使えないのは変数と同じです。

functionって何?

それにしても、ひとかたまりのプログラムをまとめることを、なんでfunctionと呼ぶのでしょうか?そして何でお尻に()を付けなければならないのでしょうか。

それを知るために、今度は上のプログラムの機能を少し変えてみましょう。まず、「一の段だけ表示するプログラム」を作ってみましょう。

function print_1_no_dan(){
  var x = 1; // 1 の段
  for (var y = 1; y < 10; y++){
    p(x + ' × ' + y + ' = ' + x * y);
  }
}

こんな感じでしょうか。それでは、二の段のプログラムを書いてください。三の段のプログラムを書いてください....九の段に行く前に、あなたはもううんざりしてませんか?それで正しいのです。

いっそ「xの段を表示するプログラム」を一つ書いて、それをxだけ変えて何回も使えるようにしたくはありませんか?

functionには、当然その機能もあります。習うより慣れろ。実物を見てみましょう。

プログラム:
出力:
エラー:

先ほどとの違いは、()の中にxが入っていることです。このxのことを、引数(argument)と呼びます。引「数」?そうです。なぜ「プログラムにまとめて名前をつけること」を英語ではfunctionと呼びますが、これは数学の世界では「関数」のことです。以後、本書でも関数と呼ぶことにします。括弧がついているのも、これで納得がいくところだと思います。

そして、関数を「使う」--プログラマーは「呼ぶ」といいます--ときには、xに具体的な値を入れるわけです。しかし、なんだか「引数に1を入れてprint_n_no_danを呼び出す関数」のもややこしい言い方ですね。これは、「1でprint_n_no_danする」と呼んでしまっていいのです。「関数」と呼ぶと数学臭いのですが、functionの本来の意味は「機能」。自然言語であれば「動詞」に過ぎないのです。ちなみに、「引数」は「述語」または「目的語」です。

ここで、簡単な読み方を覚えておきましょう。

function do_this(a, b, c){ // 「a,b,cを使ってなにかする」ことに、do_thisと名付ける
  // a, b, c を使って何をどうするのかを書く
}
do_this(1,2,3); // 1, 2, 3を使ってdo_thisする

やった結果をまた使う

単に何かをやるだけであれば、わざわざ「関数」などというもったいぶった名前を付ける必要もないはずで、実際他の言語では他の呼び方をしています。例えば私がもっとも得意とするPerlというプログラミング言語では、functionとは呼ばずsubと呼びます。これはサブルーチン(subroutine)の略です。確かにプログラムの羅列はルーチンなので、それをひとまとめにすることをサブルーチンと呼ぶのは適切に思えます。Perlではさらにそれを省略してsubと呼んでいるわけです。なんだかアニキが喜びそうな名前ですね。

しかし、実際の場面では「何かをやった」ら、その結果をさらに利用したくもなることの方が多かったりします。例えば「aとbを足した結果を表示する」のであれば、「aとbを足した結果を表示する」という「機能」を一つ作るのではなく、「aとbを足す」機能と、「xを表示する」という機能に分けた方が使いやすいでしょう。これならば、「aとbを足した結果をダイアログボックスに出す」プログラムも、プログラム全体を書き直さなくても「xをダイアログボックスに出す」プログラムだけ定義すればいいのですから。

以下、「nの階乗を計算する」プログラムを作り、結果を二通りのやりかたで表示する例です。階乗というのは、たとえば5ならば1x2x3x4x5と、一からそこまでの数字を全て掛け合わせることです。数学ではn!なんて書きます。英語ではfactorialと呼びます。

プログラム:
出力:
エラー:

ポイントはreturn result;で、これは「resultを返す」という意味です。こうなると、もう「単なる」サブルーチンではなく、「関数」という感じが確かにするでしょう。resultという値を戻しているので、resultのことは「戻り値」といいます。

関数の中で関数を使う

すでにお気づきだとは思いますが、関数の中で別の関数を使うことも当然OKです。さもなければ「カレールウを作る」の中で「材料を刻む」ことすら出来ません。見てのとおり、今までの例ではp()だとかalert()だとかといった関数を何の断りもなく使ってきましたが、それはすでに使えるように私が手配しておいたからです。

そう。必要な関数を全て自分で書く必要はないのです。その関数の名前と、その関数が何をするのかさえ知っていれば、他人が書いた関数を利用してかまわないのです。ご飯だけ炊いてレトルトのルウをかけてもそれが立派なカレーであるのと同じことです。

一つ面白いのは、ある関数はその関数自体を使うことが出来るということです。これは全ての言語でそうだというわけではありませんが、JavaScriptを含め、多くの言語ではそういうことが出来ます。

なんだか急に難しいことを言い出したように思われるかも知れませんが、実例を見てみればそれがどういうことかおわかりいただけると思います。先ほどの階乗を、今度は「自分自身を使う」というやり方で書き直してみましょう。

プログラム:
出力:
エラー:

不思議なことに、これもうまく行きます。しかし、順を追っていけば、これも簡単にわかります。factorial(10)は10 * factorial(9)、factorial(9)は9 * factorial(8)...これを1になるまで繰り返せば、最終結果は10*9*8*7*6*5*4*3*2*1となるのがおわかりいただけるでしょう。

プログラムには繰り返す部分が何度もあるというのは前に言いましたが、「自分自身を呼ぶ関数」があれば、繰り返すための構文も実は不要なのです。自分自身を呼ぶ関数のことを、再帰関数(recursive function)と呼びます。

まだわからない?いや、心配いりません。ここでは「関数は自分自身も含め、別の関数を呼ぶことができる」ことを覚えておいてください。この「自分自身を呼ぶ関数」は、後で再び登場するので、その時に改めて理解すればOKです。「再帰関数」という名前も、とりあえず忘れて構いません。

現代プログラマーの日常生活=関数の作成と利用

現代におけるプログラミングというのは、この関数を作ったり、作っておいた関数を使ったりというのが全てだと言い切っても過言ではありません。そしてプログラミングにおいては、関数を作るより使うことの方が遥かに多いのです。自然言語でも、すでに定義された語彙を使う機会の方が、新しい言葉を作る機会よりずっと多いでしょ?それと同じです。

実は、これはアマグラマーに限らず、プロのプログラマーでも同じで、実のところプロほど自分で関数を書く前に、すでに目的にあった関数があるかどうかをきちんと調べて、できればそちらを使うという傾向があります。初心者が「これどうやってやるの?」と質問すると、よくプロプログラマーが「ググレ、カス」というつれない答えをする光景がネットではよく見られますが、その理由がこれです。

ちなみに、すでにある関数を自分で書いてしまうことを、「車輪の再発明」と言います。すでに優れた車輪が売られているのに、わざわざ自分で作ることの無駄を戒める言葉です。

しかし、よく考えてみてください。車輪にしろネットにしろプログラミング言語にしろ、誰かが発明しておいてくれたからこそ使えるのです。アマグラマーは車輪の再発明を恐れないで下さい。誰でも最初は初心者で、そして誰もが何度も車輪を再発明しているのです。はじめのうちはプログラムを書くことに対して短気でいて、経験を積むにしたがってプログラムを使うことに短気になるというのが、上手に短気になる秘訣です。

まとめ

  • 関数(function)とは、ひとかたまりのプログラムにまとめて名前をつけたもの
  • 引数(argument)とは関数の目的語
  • 関数の実行結果を、返り値(return value)と呼ぶ
  • f(a,b)は、「aとbを使ってfする」と読む
  • 関数の中から関数を使うことが出来る。関数は自分自身を使うことも出来る。
  • プログラマーの日常生活は、関数を書いたり使ったりすることで成り立っている

Dan the Programmer