長い手順を「名前の付いた部品」に変える

プログラムには、入力を調べる、合計を求める、結果を表示するといった多くの処理があります。これらを最初から最後まで一続きに書くと、どこが何を担当しているのか見つけにくくなります。そこで、ひとまとまりの処理を切り出して名前を付け、必要な場所から実行できるようにしたものが関数です。関数を作ることを「定義する」、定義済みの関数を使うことを「呼び出す」といいます。

例えば、税込み価格を求める処理を複数の場所で使う場合、同じ計算式を何度も書くよりも、価格を受け取って計算結果を返す関数にまとめた方が役割が明確です。計算方法を変更するときも、呼び出し側ではなく定義を直すことで対応できます。ただし、似ているようで条件が異なる処理まで無理に一つへまとめると、関数の中に分岐が増え、かえって読みにくくなることがあります。

関数は、処理の重複を減らすためだけの仕組みではありません。複雑なアルゴリズムを「入力を整える」「値を計算する」「結果を出力する」のような役割に分け、全体を理解しやすくするためにも使われます。適切な名前が付いた関数は、その行で何をしているかを短く伝える説明にもなります。

引数で受け取り、戻り値で呼び出し元へ返す

関数へ渡す値を引数、関数が処理結果として呼び出し元へ返す値を戻り値といいます。例えば area(5, 3) という呼び出しなら、53 を縦と横の長さとして受け取り、面積の 15 を返すように設計できます。呼び出し元は戻り値を表示したり、別の計算に使ったり、変数へ保存したりできます。

引数には「この関数が処理に必要とする情報」、戻り値には「呼び出し元が次に使う結果」を選びます。値を関数の外から受け取る形にすれば、特定の数値だけでなく、異なる入力に同じ処理を適用できます。関数を呼び出す側は、内部の細かな計算手順を毎回知る必要がなく、どのような値を渡せば何が返るかを理解すれば利用できます。

すべての関数に引数と戻り値の両方が必要なわけではありません。現在時刻を取得する関数のように引数を必要としないものや、画面へ文字を表示する関数のように、値を返すことよりも動作そのものを目的とするものもあります。必要な入出力は関数の役割によって決まります。

関数の内側だけで使う変数が混線を防ぐ

多くのプログラミング言語には、名前を利用できる範囲を決めるスコープという考え方があります。関数の中で作ったローカル変数は、通常、その関数の実行中に内部で使われ、外部から直接は扱えません。この区切りがあるため、別々の関数で同じ変数名を使っても、それぞれを別のものとして管理できます。

一方、関数の外側にある変数を関数から変更できる言語や書き方もあります。画面表示、ファイルへの保存、外部の変数の変更など、関数の外部の状態に影響を与える動作は副作用と呼ばれます。副作用そのものが誤りなのではなく、入出力を行うプログラムには必要です。ただし、どの関数が状態を変えたのか分かりにくいと、実行順序によって結果が変わる原因になります。値を引数で受け取り、結果を戻り値で返す設計にすると、データの流れを追いやすくなります。

一つの役割に絞ると確認と再利用がしやすい

関数の分け方に唯一の正解はありませんが、「関数名を見て役割を短く説明できるか」は有用な判断材料です。一つの関数が入力、計算、表示、保存をすべて担当すると、変更の影響範囲が広くなります。役割ごとに分ければ、計算部分だけに複数の入力を与えて結果を確かめるなど、小さな単位で動作を確認できます。

分割しすぎにも注意が必要です。数行を読むたびに別の関数へ移らなければ内容を理解できない構成では、処理の流れを追いにくくなります。まとまりのある仕事を一つの関数にし、関数名、引数、戻り値から目的が伝わる大きさを選ぶことが大切です。

作成した関数は、そのプログラムの中だけでなく、別のプログラムから利用できる形にまとめられる場合もあります。よく使う関数を集めたものがライブラリです。また、関数が自分自身を処理の途中で呼び出す書き方は再帰と呼ばれ、同じ構造を含む問題を表す方法の一つです。

数学の関数に似ていても、画面表示までできる

「関数」という名前は数学でも使われます。どちらも入力に応じて処理し、結果を得るという見方ができますが、プログラミングの関数は数学の関数と完全に同じではありません。数学の関数では、同じ入力に対して対応する出力が一つに定まります。プログラミングでは、同じ引数でも外部の状態や時刻によって戻り値が変わる関数や、画面表示のように戻り値以外の動作をする関数も作れます。

同じ入力に対して常に同じ結果を返し、副作用を持たない関数は純粋関数と呼ばれます。純粋関数は入力と出力の関係だけを見て動作を確かめやすいという特徴があります。一方で、利用者から入力を受け取ったり結果を保存したりするには外部とのやり取りが必要です。プログラムでは、計算を担当する部分と副作用を伴う部分を意識して分けることで、それぞれの役割を把握しやすくできます。