プログラムを作っていくと、何度も同じことをしなくてはならないことがあります。
プログラムのはじめのほうで出てきた一連のやりとりが、プログラムの中盤にも終盤にも出てきたりして、そのたびに同じコードをコピーした結果、あちこちに同じ一連のコードがあるという状況はけっして良くありません。もし、その部分を変更しなくてはいけなくなったときに、何か所も直さなくてはいけなくなりますから、のちのち不便になります。
そこで、サブルーチンの出番です。
これは、一連のコードをまとめておくプログラムの固まりです。
「起きる」
「シャワーを浴びる」
「朝ごはんを食べる」
「仕事する」
「昼ごはんを食べる」
「仕事する」
「夕ごはんを食べる」
「シャワーを浴びる」
「寝る」
(一日の終わり)
こんなプログラムがあったとき、「シャワーを浴びる」と「仕事をする」が2か所ずつあります。おなじものは一緒にしてしまおうというのがサブルーチンです。
「起きる」
→サブルーチンAへ
「朝ごはんを食べる」
→サブルーチンBへ
「昼ごはんを食べる」
→サブルーチンBへ
「夕ごはんを食べる」
→サブルーチンAへ
「寝る」
(一日の終わり)
サブルーチンA「シャワーを浴びる」
サブルーチンB「仕事する」
メインの流れとは別に、離れたところにまとめて置いておいて、メインのほうにはサブルーチンを見るようにと指示するわけです。
実際には次のようになります。
$x = 1;
$y = 2;
&tashizan;
$x = 3;
$y = 4;
&tashizan;
exit;sub tashizan {
print $x + $y;
}
まず、$x に 1、$y に 2 を入れます。
次にサブルーチン tashizan を実行します。
サブルーチン tashizan は $x と $y を足したものを表示します。
サブルーチンが終わったら前のところに戻ります。
今度は、$x に 3、$y に 4 を入れます。
そして、もう一度、サブルーチン tashizan を実行して、
exit でプログラムを終了させます。
サブルーチンは sub tashizan { } の部分です。
sub につづけて、お好みのサブルーチンの名前をつけます。
サブルーチン使うときには、&とサブルーチンの名前という形になります。
サブルーチンに何らかの値を渡したい場合があります。
たとえば、先程の例でいえば…
「起きる」
→サブルーチンAへ
→サブルーチンC(朝)へ
→サブルーチンBへ
→サブルーチンC(昼)へ
→サブルーチンBへ
→サブルーチンC(夕)へ
→サブルーチンAへ
「寝る」
(一日の終わり)サブルーチンA「シャワーを浴びる」
サブルーチンB「仕事する」
サブルーチンC「ごはんを食べる」(時間帯)
このように「ごはんを食べる」でひとつにまとめて、メインのほうでは朝昼夕の時間帯だけを指定すると楽なわけです。
このような感じをプログラムにしてみると次のようになります。
$x = 2;
$y = 3;
$z = &kakezan($x, $y);
$z = &kakezan($z, $y);
print $z;
exit;sub kakezan {
my ($a, $b) = @_;
my $c = $a * $b;
return $c;
}
サブルーチン kakezan では、受け取った2つの数字をかけた答えを返します。
$x に 2、$y に 3 を入れ、kakezan に渡します。
戻ってきた答えが $z に入ります。
次に、$z と $y をもう一度 kakezan に渡し、その答えを $z に入れます。
結果は、2 * 3 * 3 ですから、18 になります。
&kakezan( ) と書き、( ) の中にサブルーチンに渡したいデータを、(複数ある場合は)カンマ区切りで入れます。
サブルーチンのほうでは、my ($a, $b) = @_; という書き方でデータを受け取って、return で返しています。
@_ という特殊な配列に、受け渡されたデータが入っています。
配列ですから、配列の1番目は $_[0] ですし、2番目は $_[1] と表現できます。
つまり、次のような書き方もできます。
my ($a, $b) = @_;
my $a = $_[0];
my $b = $_[1];my $a = shift @_;
my $b = shift @_;my $a = shift;
my $b = shift;
上の4種類はどれも同じです。
shift は、配列の先頭からデータを1つ取り出す命令です。
この時、特殊な配列 @_ は省略できるというルールがPerlにはあるので、単に shift で受け取れるわけです。
筆者もはじめて こういう使い方をする shift を見たときには「ナンデ?」って思いました。
$a、$b の前についている my は、この変数はこのサブルーチンの中でしか使いません、ということを主張しています。もし、このサブルーチン以外で $a や $b を使っていた場合、それは別の変数として扱うことになります。
したがって、わかりやすいように $a や $b としましたが、$a が $y で $b が $x であってもなにも問題は起こりません。my さえついていれば、サブルーチンの外と中とで同じ変数名が使え、別のものとして扱ってくれるわけです。
ちなみに、サブルーチンへ受け渡すデータ、サブルーチンで受け取るデータのことを、プログラム業界では、「引数(ひきすう)」と言います。
サブルーチンから返ってくるデータを「戻り値(もどりち)」と言います。
また、サブルーチンのことを、「ユーザー定義関数」と言ったり、単に「関数」と言う人もいます。