第6章「繰り返し」つづき

foreach, while, forという3種類の繰り返しの構文について見てきた。これ以外にも繰り返しの構文(じゃないものも含む)があるらしい。

do until文、do while文(p163)

他の言語にもdo while文は見たことがあるね。条件判断をループの最後で行うパターン。
untilだと、与えられた条件を満たさない間繰り返す。

my $line;
do
{
  $line = <STDIN>;
  print $line;
} until ($line eq "end\n");

whileだと、与えられた条件を満たす間繰り返す。

my $line;
do
{
  $line = <STDIN>;
  print $line;
} while ($line ne "end\n");

演算子xによる文字列の繰り返し(p164)

演算子xは二項演算子で、左辺に文字列を、右辺に数値を要求して、戻り値として左辺の文字列を右辺で指定された回数だけ繰り返したた文字列を返す。http://ideone.com/HkChl

my @text = (
  "There's more than one way to do it.",
  "Write once, run anywhere.",
  "Programming Lesson");
foreach (@text)
{
  print '+', '-' x length($_), "+\n";
  print '|', $_, "|\n";
  print '+', '-' x length($_), "+\n";
}

xを演算子にしちゃうとxって変数名をつけられないじゃないか!って思った僕はまだまだPerl初心者ですね。

関数grepによる繰り返し(p165)

関数grepは、第1引数で与えた条件に合う要素を、第2引数で与えられたリストから探し、それらを新しいリストにして返す関数。
次のスクリプトでは、Sで始まる要素を探している。http://ideone.com/teTiH

my @word = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
my @found = grep(/^S/, @word);
print "@found\n";

正規表現に関してはまた後日。

関数mapによる繰り返し(p166)

以下のスクリプトは、

my @square = map { $_ ** 2 } (0 .. 9);

以下のスクリプトと同じ結果になる。

my @square = ();
foreach (0 .. 9)
{
  push(@square, $_ ** 2);
}

http://ideone.com/KvKg6 http://ideone.com/UEYRj
この手の関数は、よく高階関数として提供される。前者の

{ $_ ** 2 }

がλ抽象に見えてしかたがないのでやってみた。

# scheme で ((lambda (a) (+ a 1)) 1) みたいなの?
my $foo = { $a + 1 } 1;
print "\$foo = ", $foo, "\n";

実行時のエラーではなくコンパイルエラー。うーん...このコードの断片はいったいなんなんだろう?

パターンマッチの /g 修飾子による繰り返し(p167-p168)

grep関数と似てるけど、 「パターンマッチの /g 修飾子」なるものを使うと、一つの文字列から、条件にマッチする部分を抽出して、新しいリストにして返してくれるらしい。http://ideone.com/7sSN5

my $line = '168cm, 58kg, 37years old';
my @match = ($line =~ /[0-9]+/g);

ってやると、数値の部分である「168」「58」「37」が見つけられる。んで、それをリストにして@matchに代入している。これも正規表現。また後日。