Perlのwhile/until/for/foreachといった反復・ループ、if...elsif...else/unlessといった条件分岐などの制御構文においては、本来のループ規則や条件規則とは別にループ条件や分岐条件の中で別途コントロール可能なnext/last/redo/die/continue/goto文があり、これらは省略可能なラベル位置またはラベルが省略された場合は、それぞれ所定の位置に処理を移すことが可能です。
Perlでは、条件分岐やループ処理と共に用いるlast、next、continue、redoがありますが、C言語経験者でPerlを始めたばかりという場合、若干戸惑うこともあるかもしれませんが、比較してみると下記のようになります。
Perl | C言語 | 意味 |
---|---|---|
last | break | ループ処理を抜ける |
next | continue | 続けてループ条件を評価する(ループの先頭に戻る) |
redo | - | 無条件でループ処理を抜ける |
continue | - | 省略可、基本的にあってもなくても同じことができる |
ただし、Perlのlast、next、redoには、省略可能なlabel(任意の名称の末尾にコロン[:]を付加)があり、いずれもlabelが省略された場合には、最も内側のループに対して有効になります。
これらのラベルは、基本的に1つのループで完結する場合には、処理やロジック上は、あってもなくても同じ(省略可)で、2重以上の条件分岐やループのより内側から外側のループ位置に対してラベルを利用する場合に意味が出てきます。
また、後述のgoto文と同様にラベルの使い方によってはロジックとは無縁の強制的な操作になってしまう可能性があるので、これらを利用する場合でも極力ラベルなしで使う方が安全だと思います。
また、Perlには、ファイルI/O(入出力)などの予測できない、または制御できないエラーが発生した場合に利用できるdie文があります。
Perl | C言語 | 意味 |
---|---|---|
die | - | ファイルI/O(入出力)などで失敗した場合の処理を記述 |
尚、その際、$!(ドル+エクスクラメーションマーク)を利用するとPerl独自のエラーメッセージを出力することができます。
open IN,"<foo.txt" or die $!
もちろんオリジナルメッセージと併用することもできます。
open IN,"<foo.txt" or die "original message : $!"
また、Perlには、使われることは、ほぼないはずですがgoto文もあります。
Perl | C言語 | 意味 |
---|---|---|
goto | 無条件にラベル位置までジャンプする |
省略されることが多いものの前述のlast、next、redoにもラベルがあり、歴史的にも他の言語でも比較的見かけるとすればgoto文ではないでしょうか。
このgotoとlabelの組み合わせはプログラムを上から順次処理していく(次に来る処理以外は呼ばない)COBOLやFORTRANのようなプログラミング言語で例外処理を行う場合に使われている経緯があり、往々にしてその利用を制限されがちではありますがC言語にもgoto文があります。
なぜ制限されがちかといえば、goto文は、gotoで示されたlabel位置まで「無条件で」戻るので(現代に至ってもただでさえ100%バグをなくすことが困難であるにも関わらず)論理的であるはずの(論理的になるように作ろうと思っている)プログラムの論理性が失われる(なんでもアリになっちゃう)懸念が多分にあり、修正、メンテをしようにも、その制御がそれで良いのかどうかすら判定が難しいどころか、書いた人など仕様を知っている極々限られた人にしかその真意がわからないことも想定されるほどソース自体が読み(追い)にくく、バグの原因にもなり得るといったデメリットがあるからです。
尤もPerlの場合には、敬遠する以前にC言語とも事情が異なり、lastやdieを利用すれば済むはずなのでPerlでgoto文を使わなければならないケースはないと思います。