7. 関数について
今日は、関数について詳しくご説明いたします。
■関数とは
毎回同じ処理を実行するのに、いちいち同じ記述を書いていたのでは、面倒ですし、
ファイルサイズも大きくなってしまいます。
そこで、処理が同じ場合は、関数という処理をまとめたものを呼び出すだけで
同じ処理を実行します。
呼び出し側は、関数名の 1 行で済むので、開発が非常に楽になります。
■宣言 & 呼び出し方宣言
関数の定義は次のように行います。
sub 関数名 {
処理
}
&関数名 # 呼び出し
上のように関数を宣言しただけでは関数の内容は実行されません。メインの処理が
関数を呼び出すことによって初めて実行されます。
基本的に、呼び出し側の関数名には"&" を付けますが、省略可能です。
また、関数に変数を渡すこともできます。これを引数と呼びます。
引数の受け取りについては、後述します。
【 関数の呼び出し 】
&関数名; # 引数を与えない呼び出し
&関数名 ( 引数リスト ); # 引数を与える呼び出し
do &関数名; # 引数を与えない呼び出し
do &関数名 ( 引数リスト ); # 引数を与える呼び出し
doで明示的に呼び出すことができますが、このdoも省略可能です。
また、引数がある場合でも、"()"を省略することが可能です。
"()"を省略した場合、関数名と第1引数の間は、半角スペースを入れます。
-----------------------------------------------------------------
sub syori_A { #
print "A"; # 関数の定義(この時点では実行されません)
}
sub syori_B { #
print "B"; # 関数の定義(この時点では実行されません)
}
&syori_A; # "&"は省略可能
&syori_B; # 〃
do &syori_B;
do &syori_A;
-----------------------------------------------------------------
《 出力 》
ABBA
■関数の終了、値の戻し
関数の実行後、処理の結果を受け取ることができます。
return
returnは、関数を終了して、戻り値として値を呼び出し側に返すことが
できます。
return 命令は実行された時点で呼び出し側に制御が戻ります。
つまり、関数の途中でも条件で"return"が呼び出されると、関数を
終了して、メインの処理に戻ります。
-----------------------------------------------------------------
print &sub_A;
sub sub_A {
return "Hello World\n";
}
-----------------------------------------------------------------
《 出力 》
Hello World
-----------------------------------------------------------------
&sub_A;
sub sub_A {
print "This is";
return;
print "Sample"; # returnで関数の処理が終了してしまったため、実行されない
}
-----------------------------------------------------------------
《 出力 》
This is
戻り値がなければ、returnを省略することができます。
■引数の受け取り
関数に引数を渡し、関数内でそれを使った処理ができます。
指定した引数は特殊変数 "@_" へ格納されます。
-----------------------------------------------------------------
&Sub_A ( "Hello" , "World" , "!!" );
sub Sub_A {
( $a , $b , $c ) = @_; # 引数の受け取り
}
-----------------------------------------------------------------
上のサンプルの場合、1 番目の引数に"Hello"、2 番目の引数に"World"、3 番目の
引数に"!!"を渡しています。
受け取り側では、@_で配列として受け取ることができます。サンプルのように
すれば、$aに"Hello"、$bに"World"、$cに"!!"が入ります。
上記の他に$_[0]で"Hello"、$_[1]で"World"、$[2]で"!!"が直接取得できます。
-----------------------------------------------------------------
$a = 1;
$b = 2;
&Sub_B ( $a, $b );
sub Sub_B {
$buf1 = $_[0]; # 1番目の引数の受け取り
$buf2 = $_[1]; # 2番目の引数の受け取り
}
-----------------------------------------------------------------
■関数内の変数
関数内で変数を用いる場合で、メイン処理の方で使用している変数名と同じものを
使用することができます。
この場合、myとlocalで挙動が異なります。
-----------------------------------------------------------------
$a = 100;
$b = 200;
&test1;
sub test1
{
my $a = 1; # 関数内のみ有効
local $b = 2; # この関数内と、この関数内で呼ばれた関数内で有効
&test2;
}
sub test2
{
print $a; # メインの$aが表示される (100)
print $b; # test1の$bが表示される (2)
}
-----------------------------------------------------------------
《 出力 》
1002
上の例の場合、$aは 100 が、$bには 2 が表示されます。
つまり、myで宣言した場合は、その関数内でのみ有効な変数であることを意味し、
localで宣言した場合は、その関数内で有効であり、その関数内で呼ばれた関数
の中でも有効になります。
★今日のまとめサンプルプログラム
-----------------------------------------------------------------
#! /usr/local/bin/perl
print "Content-type:text/html\n\n";
print << "END_OF_HTML";
<HTML>
<BODY>
END_OF_HTML
&sub_A;
$a = 100;
$b = 200;
$c = &sub_B($a, $b);
print $c . "<br>";
&sub_C;
print "main a = $a<br>"; # 関数内でセットした値は有効にならない (100)
print "main b = $b<br>"; # 関数内でセットした値は有効にならない (200)
print << "END_OF_HTML";
</BODY>
</HTML>
END_OF_HTML
sub sub_A {
print "This is a test program.<br>";
}
sub sub_B {
return $_[0] + $_[1]; # 1番目の引数と2番目の引数の和を返す
}
sub sub_C {
my $a = 5; # この関数内のみ有効
local $b = 6; # この関数内と、この関数内で呼ばれた関数内で有効
&sub_D;
}
sub sub_D {
print "sub_D a = $a<br>"; # メインの$aが表示される (100)
print "sub_D b = $b<br>"; # sub_Cの$bが表示される (6)
}
exit;
-----------------------------------------------------------------
■解説
ちょっと分かりにくいかもしれませんが、サンプルを実行して、なぜそういう結果が
表示されるのかを確認してみてください。
また、sub_C関数内のmyやlocal宣言を省略した場合は、メインの$aと$bが直接変更
されます。
他にもいろいろと変更して、どのような結果になるかを試してみてください。
★課題
1. 以下の条件を満たす関数を作成してください。
(1) 2つの引数を受け取り、積(掛け算)の結果を返す関数
(2) 3つの引数を受け取り、引数を全てをprintする関数
(3) 引数を1つ受け取り、値が100以上の場合に、"True"の文字列を返す関数
(4) 2つの引数(整数)を受け取り、2つの引数の値が同じ場合に、"True"の
文字列を返し、違う場合は"False"の文字列を返す関数
★前回の課題の解答
1. 以下のプログラムを、変数宣言が必要となるプログラムに変更してください。
→下のサンプルを参照してください。
-----------------------------------------------------------------
#! /usr/local/bin/perl
use strict;
my ($a, $b, $c, $d, $i, @week, %week);
print "Content-type:text/html\n\n";
print << "END_OF_HTML";
<HTML>
<BODY>
END_OF_HTML
$a = 10;
$b = '20';
$c = $a + $b;
$d = $a . $b;
print "\$c = $c<br>";
print "\$d = $d<br>";
@week = ('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat') ;
for ($i = 0; $i <= $#week; $i++) {
print $week[$i] . '<br>';
}
%week = ('sun', '始まり', 'wed', '中日', 'fri', '週末') ;
print $week{sun} . '<br>';
print $week{wed} . '<br>';
print $week{fri} . '<br>';
print << "END_OF_HTML";
</BODY>
</HTML>
END_OF_HTML
exit;
-----------------------------------------------------------------
■解説
配列やハッシュ配列は、@と%で宣言します。
また、$iなど、すべての変数を宣言しないとエラーになるので、注意してください。
|