関数
関数も基本的な仕様の一つです。
デフォルト変数を先ほど使用しましたが、引数渡しには $_ の場合以外に @_ も使用が可能です。
上記の2例では return で明示的に戻り値を指定していますが、 perl ではreturn を使用しなくてもperlが返してくれる場合があります。 ただ、最初の頃はしっかりと return を使用して明示的に表す事をお勧めします。 ミスも少なくなるし、なによりコードの可読性が上がります。
では関数のなかで他の部分に気兼ねせず任意に変数の名前を定義する事は出来ないのでしょうか? 当然出来ます。 この時には my というキーワードを使用します。 これを使用して変数を定義すると、有効範囲はそれが定義されたブロック内に限定されます。
補足ですが、上記の my の有効範囲は関数内に限定されるわけではありません。 { } で囲まれたブロック内で有効なのです。 よって、関数ではなくループなどの中や if(){~} の中でも有効です。 大いに活用しましょう!
#!Perl
sub valadd{
$re = $_[0] + $_[1];
return $re;
}
$str = &valadd(5,8);
print $str;
として実行すると
13と表示されます。 ここではまず作る必要は無い、数値2つを足して返す関数を作成してみました。 この例でわかるように、Perl では sub とそれに続く任意の名前が関数の宣言に当たります。 その後に ( ) を付け、{ } の間に関数の処理内容を書き込みます。 問題は引数(関数に渡す値の事)なのですが、Perl の場合、よくここで躓く事が多いようです。 ここで使用しているのはデフォルト変数です。 関数を呼び出している部分で(5,8)と二つの値を渡していますが、 受け取り側で[0]に5、[1]に8 を受け取っています。 なを、呼び出しには定義した関数名の前に & を付けてください。
デフォルト変数を先ほど使用しましたが、引数渡しには $_ の場合以外に @_ も使用が可能です。
#!Perl
sub valadd{
($aa,$bb) = @_;
$re = $aa + $bb;
return $re;
}
$str = &valadd(5,8);
print $str;
として実行すると
13別に難しいこっちゃないのですが、変数で一々引数を取得するのか、それとも配列で一気に取得するのかぐらいの違いです。 受け取った引数群をそのままループ等に渡す場合は、配列の形で取得した方が有用な場合が多いです。
上記の2例では return で明示的に戻り値を指定していますが、 perl ではreturn を使用しなくてもperlが返してくれる場合があります。 ただ、最初の頃はしっかりと return を使用して明示的に表す事をお勧めします。 ミスも少なくなるし、なによりコードの可読性が上がります。
関数とスコープについて
スコープは変数の使用範囲です。 perl では特に指定しなかった場合は変数は自動的にグローバルとして扱われます。 これは気を付けなければいけない点で、不用意に変数名を付けると想定しない場所で内容が書き換えられる場合があるという事です。 例えば、
#!Perl
sub valadd{
$re = $re + $_[0] + $_[1];
return $re;
}
$re = 9;
$str = &valadd(5,8);
print $str;
として実行すると
22なぜこの結果が出るかわかりますよね。 関数自体の宣言はコードの頭にされていますが、 関数内で使用されている $re が関数を呼び出す直前の列で既に定義されているからです。
では関数のなかで他の部分に気兼ねせず任意に変数の名前を定義する事は出来ないのでしょうか? 当然出来ます。 この時には my というキーワードを使用します。 これを使用して変数を定義すると、有効範囲はそれが定義されたブロック内に限定されます。
#!Perl
sub valadd{
my($a,$b) = @_;
my($re);
$re = $re + $a $b;
return $re;
}
$re = 9;
$str = &valadd(5,8);
print $str;
として実行すると
13ここでは関数内でのみ有効な $re を作成して使用しているので、 関数呼び出し前の $re = 9; という処理は関数内の変数には影響がありません。 何もしなければグローバル変数というperlの決まり事は、時には変数有効範囲の混乱を招きます。 関数内の変数にはmyを適用しておく癖を付けておけばそういったミスも軽減されるでしょう。
補足ですが、上記の my の有効範囲は関数内に限定されるわけではありません。 { } で囲まれたブロック内で有効なのです。 よって、関数ではなくループなどの中や if(){~} の中でも有効です。 大いに活用しましょう!
2008年 11月 2日ドキュメント作成
2008年 11月 2日ドキュメント更新