4.12.2 練習問題

前の問題で作成したサブルーチンを使用して、1から1000までの合計を求めるプログラムを書いてください。

何を求めているのかよくわからない問題だなぁ。
と思いつつ、前のプログラムをちょっと削って足す。

#!/usr/bin/perl -w
use strict;

my @fred = 1..1000;
my $fred_total = &total(@fred);
print "The total of \@fred is $fred_total.\n";


sub total {
  my $sum = 0;
  foreach (@_) {
    $sum += $_;
  }
  $sum;
}

動いてる。
で、解答を見る。
...1行で書けますよ、という問題だったのかな?

4.12.1 練習問題

配列の合計を出すサブルーチンを作る問題。

#!/usr/bin/perl -w
use strict;

my @fred = qw{ 1 3 5 7 9 };
my $fred_total = &total(@fred);
print "The total of \@fred is $fred_total.\n";
print "Enter some numbers on separate lines: ";
my $user_total = &total();
print "The total of those numbers is $user_total.\n";


sub total {
  my $sum = 0;
  foreach (@_) {
    $sum += $_;
  }
  $sum;
}

変数名まで解答と一緒。:-)

4.11.1 アンパーサンドを省略する

これまたid:TransFreeBSDさんに教わった
サブルーチン呼び出し時のアンパーサンド(&)*1の省略が
出てきました。


注意する点は以下。

  • サブルーチンの起動より後ろでサブルーチンを起動すると、Perlが起動されるdivisionの正体をわからないので、省略できない場合もある。
  • もしサブルーチン名がPerlの組み込み関数と同じ名前だったら、それを呼び出すには必ずアンパーサンドを付けなければならない。

後者は、とくに初心者の内は気をつけないと。
Perlがバージョンアップして、過去のソースを新しいバージョンで
コンパイルしなくてはならない場合に、
もし新しくPerlの組み込み関数になったサブルーチン名の
アンパーサンドを省略して使ってたり、なんてことは
ありそうなんですが、実際にはどうなんでしょうね。


それはさておき、省略できるところは省略するってのが
Perlっぽいというのを再認識。

*1:ついでに普段使っている割に語源を知らなかった「アンパーサンド(&)」について調べてみたら、極東ブログに詳細に書いてありました。以下引用。「アンパサンド(ampersand)の語源"and per se and"は、「andといってもつまりandそれ自体」ということ。含みとしては、AとNとDの略語とかじゃないということ。「"&"はだからぁANDなんだよぉ」ということでもある。」

4.11 return演算子

id:Baysideさん、id:TransFreeBSDさんに教わった
return演算子が早速出てきました。


return演算子の最も多い使い方として

  • サブルーチンの残りを実行せずに、即座に値を返す。

とあります。
C言語のreturnと同じ感じですかね。


戻り値には必ずreturnを明記するかどうかは
プログラマの流儀次第とあります。
私としてはその方がメンテナンスしやすそうですが、
『初めてのPerl』には、

多くのPerlプログラマは、わざわざreturnとタイプするのは、無駄な労力だと認識しています。

とあります。
省略できるところは省略するのがPerlっぽいので、
私もreturnが書いてないことに慣れる必要がありますね。


郷に入りては郷に従え、と。

4.9 レキシカル変数(my変数)についての注意事項

foreach (1..10) {
  my($square) = $_ * $_;
  print "$_ squared is $square.\n";
}

こういう場合、$squareはこのforeach文内のみ有効だそうです。
『初めてのPerl』にも書いてある通り、
メンテナンス上素敵な仕様です。
CやJavaではこの場合どうだったのか覚えてませんが、(ぉぃ
確かprivateであっても関数全体に有効な変数に
なったような気がします。(適当...)

4.8 可変長のパラメータリスト

実世界のPerlコードでは、任意の長さのパラメータリストをサブルーチンに渡すということがよくあります。

ってことは、引数の数を限定しないサブルーチンを
作ることができる。
そしてそれがよくある、ということですね。
そういう関数を他の言語で書いた経験はないのですが、
よく考えるとそれは私の書いてきたプログラムのジャンルが
偏っていたから、ということに尽きるような気がします。
だってこうしなきゃ実現できない処理、
または実現が面倒になる処理って
たくさんありそうだから。


それはさておき、以下の引数の大きい方の値を求める関数max*1
引数を何個でも受け取れるように改良した例文が載っていたので
動くように変更して練習。
(予定外の値を入力された場合の処理なし)

  • 引数2個の場合。

#!/usr/bin/perl -w
use strict;

print "2行にわけて数字を2つ入力して下さい。:\n";
int &max();

sub max {
  my($a, $b) = @_;
  if($a > $b) { $a } else { $b }
}


  • 引数を何個でも受け取れる場合。

#!/usr/bin/perl -w
use strict;

print "改行して数字を複数入力して下さい。:\n";

print &max();

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

後者は最高水位線というそう。
Perlではこう書けるんだな、という好例。


また、空のパラメータリストが与えられた場合についても
4.8.2で説明してあります。
そういうことよくありそうですもんね。
上記の&maxの場合は、戻り値がundefになる、と。

*1:等しい場合の処理が中途半端だけど、原文そのままで。