初めてのPerl  RSSを登録する

Perl言語初心者の筆者が「初めてのPerl第3版」をテキストにして学習していきます。そのときに、気になったことなどを適宜まとめて記事にします。アドバイス、コメント、挨拶など気軽にしていただければ、うれしいです。

現在休刊中です    
解除

規約に同意して

2008/10/24

4日目:サブルーチン

本記事では、サブルーチン(=ユーザー定義の関数)の取扱いについて
まとめます。前回、前々回は、実は手抜きな内容になっていましたので、
少し気合を入れ直していきます!

□ サブルーチンの定義
テキスト4章のしょっぱなに、非常に魅力的な例が載っていました(P.68)。

sub marine {
    $n += 1;
    print "Hello, sailor number $n!\n";
}

この例のように、サブルーチンはsubというキーワードの後に、サブルーチン
の名前(任意)とブレースで囲まれたサブルーチンの本体とからなります。
絶妙なネーミングセンスですね!

サブルーチンの中では、どんなグローバル変数でも参照することができます。
もちろん、アクセスできるからと言って無制限にアクセスすることが推奨されて
いるわけではないと思います。なぜなら、そのような関数は他との依存関係が
複雑になるので、プログラムの他の部分の修正によってこの関数の挙動が
変わったりするといった、ややこしい事態になりがちだからです。

□ C言語との比較
C言語と比べて、Perlの関数定義はかなり柔軟になっています。実際に比較して
みると、C言語では、

//関数プロトタイプ宣言
int max(int a, int b) ;

//関数定義
int max(int a, int b) {
  if( a <= b) 
	return b;
  else
	return a;
}

のようにファイルの先頭に関数プロトタイプ宣言を書きます。そして、ファイルの
任意の場所に関数定義を書きます。これらはC言語の仕様として決まっている
ので、この通りに書かないとコンパイルできません。しかし、Perlでは、プログラムで
使用する関数の仕様(関数名、戻り値の型、引数の個数や型など)を明示的に
宣言しません。

sub max {
  if($_[0] < $_[1]) {$_[1]} else {$_[0]}
}

(注)このサブルーチンmaxに渡される1番目の引数は$_[0]に、2番目の引数は
$_[1]に保持されている。ちなみに、$_[0]や$_[1]などは配列@_に引数が格納されて
いることを表しているので、デフォルト変数$_とは無関係です。

これをしてPerlは堅苦しくなくて良いと考えるか、バグに陥りやすいから危険と
考えるかは人によってマチマチだと思います。おそらく、前者の考え方を好む人は
Perl向きなのでしょう。

□ サブルーチンの戻り値
サブルーチンの戻り値は、最後に行われた計算の結果が、自動的に戻り値になります。
例えば、上のmaxの例では$_[0]あるいは$_[1]のいづれか大きい方が最後に評価される
ので、大きい方の値がmaxの戻り値になります。

このとき、私は2つの疑問点を持ちました。まず第1の疑問点は、「maxに誤って
3個以上の引数が与えられたらどうするのだろうか?」ということです。サブルーチンの
定義において、C言語のmaxのように引数は2個だけと指定しないので、誤って3個以上
の引数がmaxに与えられることが起こり得ます。実際の挙動は、3個目以降の引数が
無視されますが、それではプログラマの予期しない結果を計算してしまうことでしょう。

第2の疑問点は、「どこで戻り値が返されるのかを理解するのは、とても難しいのでは?」
ということです。return文などで明示的に戻り値を返すように書かれていれば助かるの
ですが、そうでない場合でも最後に評価された式の値が戻り値になるのです。コードの処理
を丹念に追いかけて、最後に評価される式を見つけるのは、とても骨の折れる作業だと
思います。。。

これらのことは欠点というよりは、プログラミングスタイルの違いと思います。いづれにせよ、
プログラミングの経験があまりない人がPerlを学ぶときには、こういうこともあることを
知っておいた方が良いと思います。

次のサブルーチンはmaxの改訂版です(P.78から引用しました)。1個以上の引数を
受け取ったときに、その中で最大の数を返す(0個のときはundefを返す)ものです。

sub max {
	my($max_so_far) =shift @_;
	foreach (@_) {
		if($_ > $max_so_far) {
			$max_so_far = $_;
		}
	}
	$max_so_far;
}

(注)my($max_so_far)によって、$max_so_farをサブルーチン内だけで有効なプライベート変数を
宣言しています。

このサブルーチンは、foreach文が一回も回らなかったとき(=引数が0個だったとき)に、
undefを返すように、ブロックの最後の行で$max_so_farを書いてあります。こういう気配りは、
うっかり見過ごしてしまいそうです。。。

□ use strictプラグマ
上のサブルーチンmaxの定義で$max_so_farと書くべきところを、途中で間違えて$maxsofarと
書いてしまうこともあると思います。 Perlは$max_so_farとは異なる別の変数$maxsofarとして
計算するので、これはバグになります!こういった間違いを未然に防ぐためには、プログラムの
先頭に

use strict;

と書きましょう。こうすることで、プライベート変数としてあらかじめ

my($maxsofar);

と宣言しないでプログラム中で変数$maxsofarを使おうとすると、プログラムのコンパイル時に
エラーになって警告してくれます。 

現在休刊中です
解除

規約に同意して

最近の記事

上へ戻る