サブルーチンの基本的な使い方
プログラム内で何回も同じ処理をするようなときは、その処理の部分を切り離してサブルーチンにしてしまうのがスマートなやり方です。そうすれば、何回も同じソースを書く必要がなくなるので、時間の節約にもなります。
サブルーチンの宣言
サブルーチンは sub で宣言します。
sub func; # サブルーチンの宣言
サブルーチンを宣言し、なおかつ定義するには次のようにします。サブルーチンの宣言と定義を同時に行うのが一般的です。
# サブルーチンの宣言と定義
sub func{
....
}
サブルーチンを呼び出すには、アンパサンド( & ) をサブルーチン名の前につけて、以下のようにします。
&func();
サブルーチンはファイルのどの場所で宣言してもかまいませんし、呼び出し元と同じファイル内でなくても問題ありません。別ファイルにあるサブルーチンは、do、 require 、 use で取り込むことができます。
サブルーチンは引数を呼び出し元から受け取ることができます。サブルーチンが受け取った引数は特殊変数の @_に格納されているので、$_[0] から順に $_[1]、$_[2] と参照することができます。
sub func{
print "引数は " . $_[0] . " ". $_[1] ."\n";
}
&func(1, "YES!");
> 引数は 1 YES!
特殊変数 @_ は渡された値のリファレンスになっています。ですから、 @_の値を変更すると、引数として指定された変数の値も変更されることになります。
sub func{
$_[0] = 100;
}
my $x = 1;
print $x;
> 1
&func( $x ); # この時点で $x の値は 100 に変更されます
print $x;
> 100
呼び出し元の値を変えるようなサブルーチンに &func(1, "YES!")と、定数値を渡すとエラーになります。呼び出し元の値を変更したくないような場合は、サブルーチンの最初で特殊変数@_ の値を変数にコピーします。
sub func{
my ($val1, $val2) = @_;
print "引数は" . $val1 . $val2 . "\n";
}
サブルーチンの引数にはスカラだけではなく、配列やハッシュを渡すこともできます。
&func(1, "YES!"); my @list = (1, "YES!"); &func(@list);
サブルーチンから値を返すには、return を使います。returnを省略すると、最後に評価された結果が戻り値となります。
sub func{
my ($val) = @_;
return "引数は" . $val . "\n";
}
print &func("YES!");
> 引数はYES!
プロトタイプ付きサブルーチン
サブルーチンは、宣言時にプロトタイプを利用することにより、受け取る引数の型や数を指定することができます。この宣言によって、引数の数や型に制約を加えることができます。
プロトタイプの概要
プロトタイプ付きのサブルーチンを宣言するには、次のように宣言文にプロトタイプ用に用意されたシンボルを指定します。
# プロトタイプ付きサブルーチンの宣言と定義
sub func( $$@ ){
.....
}
# プロトタイプ付きサブルーチンの呼び出し
&func($a, $b, @list);
上記の例文では、スカラ2つとリスト1つをプロトタイプで指定しています。
プロトタイプ用のシンボル
サブルーチンを宣言するときに、サブルーチン名の後にカッコで変数のタイプを表すダラー( $ )、アットマーク( @ )、パーセント( % )を指定しておきます。たとえば、ダラーが2つ続いて指定されていれば、引数としてスカラ変数が2つ、アットマーク( @ )が1つであれば配列が1つ必要となります。
プロトタイプ用のシンボル一覧
| 記号 | 意味 |
|---|---|
| $ | スカラ |
| @ | リスト |
| % | ハッシュ |
| & | 無名サブルーチン |
| * | 型グロブ |
引数の変数型をチェック
バックスラッシュ( \ )付きの型は、引数が絶対にその変数型でなければいけないことを示します。
sub func( \% );
上記のサブルーチン宣言は、1つのハッシュ変数を受け取ります。逆に、バックスラッシュなしの @ と % は、残りすべての引数を飲み込んで、リストコンテキストを強制します。
たとえば、次のようなプロトタイプ付きサブルーチンを宣言した場合、2つの配列を引数として渡しても、1つの配列にまとめて渡されてしまいます。
sub func(@@){
my (@a, @b) = @_;
print @a, ":", @b, "\n";
}
my @array1 = (1,2,3);
my @array2 = (A,B,C);
&func( @array1, @array2 );
> 123ABC:
このようなときに、バックスラッシュ( / )をプロトタイプシンボルの前につけて、複数の配列やハッシュを受け取らないように指定しましょう。
sub func(\@){
my ($a, $b) = @_;
print @$a, ":", @$b, "\n";
}
my @array1 = (1,2,3);
my @array2 = (A,B,C);
# 複数の配列だとエラーになるので、配列のリファレンスを渡している
&func( \@array1, \@array2 );
> 123:ABC
必須の引数と省略可能な引数の区切り
セミコロン( ; )は、必須の引数と省略可能な引数の区切りです。たとえば、次のように指定すると、最初のスカラ値のみが必須となります。
sub func($;$);
2番目のスカラ値は省略可能です。リストは空でもかまわないので、@ や % の前にはセミコロン( ; )は必要ありません。
プロトタイプの利用ガイドライン
プロトタイプ付きサブルーチンは、引数のコンテキストを強制的に合わようとします。これは、コンパイル時に行われますが、必ずしも引数の型と数をチェックするとは限りません。その代わり、組み込み関数と同じように呼び出し時にカッコを省略するような書式のサブルーチンを作成することができます。
プロトタイプで注意する点は、サブルーチンリファレンス \&func や間接サブルーチン &{&sub}
などには影響しないということです。また、メソッド呼び出しも同様です。
カッコを省略する
@array = func 1, 2;
プロトタイプ宣言がない場合は、次のように呼び出します。
@array = func(1,2);
組み込み関数をエミュレートする
push や shiftといった組み込み関数の、引数を配列にまとめずに渡すという動作をエミュレートすることができます。たとえば、push( @array, 1, 2 ) では、push 関数は実際の配列ではなく @arrayへのリファレンスを受け取ります。これは、@ に \ を付けたプロトタイプで実現できます。
sub mypush( \@@ ){
my $array_ref = shift;
my @remainder = @_;
....
}
プロトタイプ宣言の中の \@ は、「最初の引数は @ で始まり、リファレンス渡しとする」という意味です。2つ目の @ は、残りの引数はリストという意味です。
プロトタイプ利用例
以下に、プロトタイプの利用例を一覧で記載しておきます。参考にしてください。
| 宣言 | 呼び出し例 |
|---|---|
| sub mylink($$) | mylink $old, $new |
| sub myindex($$;$) | myindex &getstring, "substr" |
| myreverse(@) | myreverse $a,$b,$c |
| myjoin($@) | myjoin ":", array; |
| mypop(\@) | mypop @array |
| mykeys(\%) | mykeys %{$hashref} |
| myopen(*;$) | myopen HANDLE, $name |
| mypipe(**) | mypipe READH, WRITEH |
テクニック集
引数にリファレンスを指定する
サブルーチンに複数の配列やハッシュを指定しても、予想通りには動作してくれません。受け取り側が配列 @_ なので、すべてこの配列に格納されることになります。ですから、以下のように配列の後にハッシュを引数として渡しても、すべて配列にまとめられてしまいます。
my @list = (1..3);
my %hash = (a=>1, b=>2, c=>3);
&func(@list, %hash);
sub func{
my(@list, %hash) = @_;
foreach my $key( @list ){
print "$key ";
}
print "\n";
foreach my $key( keys %hash ){
print "$key: $hash{$key} ";
}
}
> 1 2 3 a 1 b 2 c 3
上記のサブルーチンは配列とハッシュを受け取ろうとしていますが、結果はすべて1番目の引数である @a に格納されてしまっています。
複数の配列やハッシュを別々に扱いたい場合は、リファレンスを使います。
&func( \@list, \%hash );
sub func{
my ($list, $hash) = @_;
print "-------list--------", "\n";
foreach my $key( @{ $list } ){
print "$key", "\n";
}
print "-------hash--------", "\n";
foreach my $key( keys % { $hash } ){
print "$key: $hash->{$key}", "\n";
}
}
戻り値を配列やハッシュにする
サブルーチンの引数として配列やハッシュを渡す場合と同様に、戻り値もリファレンスを使うことによって簡単に実現できます。
# 配列を返す
sub return_array{
....
return \@array;
}
# ハッシュを返す
sub return_hash{
....
return \%hash;
}
サブルーチンの呼び出し元のコンテキストを調べる
wantarrayサブルーチンを使って、サブルーチンを呼び出したコンテキスト(スカラ/リスト)を調べることができます。これにより、ひとつのサブルーチンでスカラを返したり、リストを返したりすることができるようになります。
sub func{
return wantarray ? (1..3) : 1;
}
my @list = func(); # 値が「1」から「3」の配列が返される
my $scaler = func(); # 値が「1」のスカラが返される
コンテキストとは
コンテキストとは、どのような値を求めているかという状況です。たとえば、数値が求められている場合は数値コンテキスト、複数の値が求められているときはリストコンテキストという使い方をします。
名前つき引数を渡す
引数に名前を付けてサブルーチンに渡すことができます。
func( ALPHA => "ABC", NUMBER => 100, COUNT => 0 );
サブルーチン内では、デフォルト値や引数名とその値をハッシュに代入します。
sub func{
my %args = (
ALPHA => "ABC",
NUMBER => 100,
COUNT => 0,
@_, # 呼び出し時に指定された引数名とその値の組
);
}
特殊変数の @_ を最後に付け足すのを忘れないようにしましょう。これによって、引数値があれば、その値でデフォルト値を上書きします。
引数に名前をつける利点は、どの引数も省略することができるようになり、また、引数の順番を気にする必要がなくなります。
# 引数の順番を変えられないし、省略もできない func( "1番目の引数", "2番目の引数", "3番目の引数" ); # 引数を省略した上に、順番も気にしない(でも引数名は気にしてね) func( three=>"3番目の引数", one=>"1番目の引数" );
サブルーチンを再帰的に呼び出す
サブルーチンを再帰的に呼び出すこともできます。なんらかの条件で再帰的な呼び出しが終了するようにしておかないと、永遠に処理が続けられるので、注意する必要があります。
sub func{
.... # 必要な処理
&func(); # 再帰的に呼び出す
}