戻り値(返り値)とは、
呼び出された関数内で生成、算出(または結合、比較)した結果や、その結果に基づくフラグなどを呼び出し元に返す場合のその値 |
の事です。
$ret=&abc; |
Perlでは、例えば、呼び出し元でサブルーチンabcを呼び出す際に、この「戻り値」を入れる箱(変数)を予め用意して代入するとサブルーチンabcの返り値がスカラー値である場合はその値そのものを取得することができます。
sub abc {
~
return x;
}
sub abc {
~
return $z;
}
多くの場合、呼び出されたサブルーチン側からはreturn文を使ってそのルーチンの結果となる何らかの値を返し、その時、返り値がスカラー値である場合は呼び出し元の[$ret]にはサブルーチンで返されるスカラー値[x]やスカラー変数[$z]に格納された値が入る(戻ってくる)ということになります。
$ret = $foo;
@ret = @bar;
%ret = %hoge;
返り値が数値キー型配列、文字列キー型配列の実体である場合は、当然それぞれの型でも取得できるわけですが、データ量としての値が大きい場合、値をそのまま渡すのは効率的とは言えません。
この時、Perlでは、Cのポインタのように値そのものではなく値を格納したアドレスを返すことができ、そのアドレスに格納されている中身の値の参照(リファレンス)ができるようになっています。
$ret = \$foo;
$ret = \@bar;
$ret = \%hoge;
Perlにおける変数への参照(リファレンス)は先頭に\バックスラッシュ(Windowsではyenマーク)を付加します。
参照先アドレスにある変数がスカラー、数値キー型配列、文字列キー型配列の何れであってもアドレス値を格納する変数は、Perlの変数においてはスカラー変数で十分なのでリファレンスを受け取る際にはこれを利用します。
$ret =&foo;
sub foo { return \$foo; }
$ret = &bar;
sub bar { return \@bar; }
$ret = &hoge;
sub hoge { return \%hoge; }
これは、ルーチン/サブルーチン/メソッドの戻り値においても同様です。
この時、リファレンスを格納するスカラー変数$retはリファレンス変数と呼ばれることがあります。
ちなみに返り値である数値キー型配列の実体をスカラー変数で取得したり、同じ関数内で数値キー型配列をスカラー変数に代入すると数値キー型配列の要素数を取得することになります。
@foo="123, xxx, 57dd";
$bar = @foo;
つまり、この場合には、$bの値は@fooの要素数である3ということです。
文字列キー型配列の実体[ %xyz ]をスカラー変数[ $ret ]に代入しても意味のある値にはなりませんが、文字列キー型配列の実体[ %xyz ]の要素[ $xyz{'要素'} ]であればスカラー変数[ $ret ]に[ $xyz{'要素'} ]に格納されたその値が代入されます。(リファレンス変数も併せて参照)。
#!/usr/bin/perl
use strict;
my $i;
my $k;
my $ret=&abc;
print "$ret\n";
exit;
sub abc {
$k=$k+1;
$i=$i+5;
}
(サブルーチンのページに同じ内容を書いていますが、)Perlではreturn文を使うことができますが、Perlのサブルーチンは、明示的にreturnで値を返却しない場合には、呼び出したそのサブルーチン内で最後に処理された結果が戻り値(返り値)になります。
呼び出し元で受け取らなければ済むかもしれませんが、それを意図しない場合には、発見しにくいバグを埋め込むことにならないようにする為にも、仮に返却する値がなくともreturn;と記述するか、0、1などで成功、失敗を示す値をセットしておくとよいでしょう。
例えば、return文をつけずに呼び出し元で戻り値を受け取り(スクリプトファイル名をtest.plとして実行権限をセットして)実行すると
$ ./test.pl
5
その場合、値が1となるはずの$kの値は戻りませんが、$iの値である5が戻り値となることが確認できます。
sub abc {
$k=$k+1;
$i=$i+5;
return;
}
ここで戻り値を省略してreturn;と記述して実行すると
$ ./test.pl
print "$ret\n";に改行[\n]があるので改行はされますが、実行結果に値は戻しません。
もちろんreturnに$iや$kを戻り値として渡すこともできますが、この例に関しては、$i、$kに注目すれば共に実質グローバル変数なのでサブルーチンabcにおけるreturnの有無に関わらず、式の結果は$i、$kに格納されます。
ちなみに、例えばここにサブルーチンの成功失敗を表す値を付加してreturn 0;、return 1;などとすれば、呼び出し元の$retには0や1が返ります。
Perlの真偽値は、0または""(カラ)は「偽」、0以外の数値またはカラでない何らかの文字は「真」です。
尚、0で始まる数字の並びにおいても数値か文字列かを判定するまでもなく「数値」または「カラではない何らかの文字列」に該当するので「真」となります。
また、Perlには「未定義」という判定基準がありますが、真偽値としては「未定義」は「偽」です。
「未定義」・「未定義値」は、式の中でundef(undefinedの省略形)で表現され、undef()関数で引数を未定義に設定することができ、引数を省略し単にundefとすると(undef関数を呼び出した結果はundefとなるので)結果的に未定義である値を表現することができますが、「未定義か否か」を調べるには、「定義済みか否か」の判定を行うdefined()関数を使用し、その結果が偽の場合、undefということになります。
例えばundef値が存在するケースとしては、外部入力から任意の値を受け取るケースで且つ未入力項目をカラ文字列として設定するなどの処理をしない場合や内部ロジックにおいて意図的にundefを判定に利用する場合、または意図せずundef値が存在し得て、例外エラーのケースとしてもundefを想定したロジック、コーディングとなっていない不十分なコードなどが考えられます。
これらのことから、Perlでコードを書く場合、特にサブルーチンでreturn文自体やreturn文の引数を省略するか否かを考える場合には、return省略時の式の結果を含め、結果として戻り値が「未定義」(undef)と成り得るケースがあるか否かを念頭に置く必要があると言えるでしょうし、仮に意図してundefを許容し、評価する場合でもundefを他の値に変換するなどサブルーチン化したり、使用個所を極力局所化するのが賢明でしょう。
尚、useで取り込んでいるstrict(.pm)は、厳密な文法チェックをしてくれるPerlに標準で組み込まれるプラグマであり、先頭のSが大文字のStrict(.pm)とは本来の目的は同じですが違うモジュールです。
例えば、strictを取り込まなければmy $i,$k;などまとめて宣言できますが、strictを取り込む場合は個々に宣言する必要があります。