redo

ループ内の処理をもう一度開始する

構文

解説

redo コマンドは、条件を再評価せずにループブロックを再び開始します。 もし continue ブロックがあれば、それは実行されません。 LABEL が省略されると、このコマンドは最も内側のループを参照します。

my $count = 0;
LINE: while (<STDIN>) {
    $count++;
    if ( $count % 2 ) {
        redo LINE;
    }
    print $count, "\n";
}

redo EXPR という書き方は Perl 5.18.0 から使えるようになりましたが、 これによって実行時にラベル名を算出することができるようになりました。 それ以外は redo LABEL と同等です。

my $labelname = 'LINE';
my $count     = 0;
LINE: while (<STDIN>) {
    $count++;
    if ( $count % 2 ) {
        redo $labelname;
    }
    print $count, "\n";
}

redo は、eval {}, sub {}, do {} などのように、一般的に値を返すようなブロックから値を返すことはできません。 redo はフロー制御の振る舞いを実行し、一切の戻り値を除外します。 そのため、grepmap の処理を抜け出すために redo を使ってはいけません。

なお、ブロックは意味的には一度だけ実行されるループと同義と捉えることも可能です。 そのため、そのようなブロックの中にある redo は効率的にそのブロックをループ構成に変えます。 前述の通り、値を返さないブロックであれば、ループでなくても redo は使えます。

次の例はランダムに 0 から 99 までの整数を生成します。 そしてその値が 10 の倍数でなければ、ブロックの先頭に戻ります。 10 の倍数なら、それを出力してブロックを抜けます。

{
    my $num = int( rand(100) );    # 0 から 99 までの整数
    redo if $num % 10;             # $num が 10 の倍数でなければブロックの先頭に戻る
    print "${num}\n";
}