ループを制御する

Perlには、ループを制御するための演算子が三つある。

last  ループの実行を即座に終了
next  次の繰り返しに移動
redo  現在の繰り返しの先頭に戻る

ループ制御演算子が使えるのは、for、foreach、while、until、裸のブロックの五種類のループ。制御の対象となるのは、その制御演算子が置かれている最も内側のループ。

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

print "p:パス\ne:終了\n";
foreach (1..10) {
    my $a = int(rand(100)) + 1;    # 1〜100までの乱数を取得
    my $b = int(rand(100)) + 1;  
    print "Q$_:$a + $b = ";
    chomp(my $input = <STDIN>);
    next if $input =~ /p/i;        # pなら次へ
    last if $input =~ /e/i;        # eなら終了
    redo unless $input =~ /^\d+$/; # 数値以外ならやり直し
    if ($input == $a + $b) {
        print "○\n";
    } else {
        print "×\n";
    }
}
p:パス
e:終了
Q1:19 + 58 = z
Q1:61 + 30 = p
Q2:54 + 89 = 143
○
Q3:92 + 39 = 121
×
Q4:53 + 56 = e
if $input =~ /\D/;

これだと、エンターキーだけを押された場合にすり抜けてしまうので、

unless $input =~ /^\d$/;

に修正した。


nextは正確に言うと、whileループならcontinueブロックの先頭に、forループなら、3番目の部分($i++など)に飛ぶらしい。それ以外は、現在のループブロックの末尾に飛ぶのだろうか。とにかく、continueブロックを使えば、nextを使った場合でも、値を増減させることは可能。

my $n = 0;
while ($n < 5) {
    print "$n\n";
    next;
} continue { # この行をコメントアウトすると、無限ループに
    $n++;
}
0
1
2
3
4

ラベル付きブロック

一番内側のループ以外を制御するには、ラベルを使う。ループブロックの前に、ラベルとコロンを置き、制御演算子の後ろに制御したいループのラベルを置く。

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

LINE: while (1) {
    for my $n (1..10) {
        print "$nと入力してください:";
        chomp(my $input = <STDIN>);
        last LINE if $n == $input; # LINEループから抜ける
    }
}
1と入力してください:5
2と入力してください:7
3と入力してください:3

ラベル名には、組込み関数やサブールチンと区別できるように、大文字だけを使った方がいいらしい。