Perl プログラミングにおいて、and/or を使って条件分岐処理を行う場合の留意点。
Perl は if 文の他、and/or という論理演算子を使って条件分岐処理ができる。
例えば、以下の2つの処理結果は同じになる。
my $same = ‘abcde’;
if ($str eq $same){
print “IF: true.\n”; #こちらが print される
} else {
print “IF: false.\n”;
}
$str eq $same
and print “AND/OR: true.\n” #こちらが print される
or print “AND/OR: false.\n”;
Perl のガイドラインでは and/or の方が処理が速い、という事になっていて、実際に何百回も呼ばれるルーチンを修正すると、それだけで処理が速くなる。
という事でこの構文は非常に便利なのだが、場合によっては期待どおり動作しない場合がある。
例えば、「ハッシュ変数の個々の値をチェックして、値が空白だったらそのエントリを削除したい」とする。フォームの必須入力チェックなどで必要になる処理だ。
単純化するために処理を半角だけに限っているが、値が空白文字だけかどうかを確認する処理は以下のようになる。
$ws =~ m/^\s*$/
and print “AND/OR regexp: true.\n” #こちらが print される
or print “AND/OR regexp: false.\n”;
これを、ハッシュの値に変えても処理は同じ。
$myhash{ws} =~ m/^\s*$/
and print “AND/OR regexp: true.\n” #こちらが print される
or print “AND/OR regexp: false.\n”;
ハッシュのキーを削除する場合は and をつなげて書く事ができる。
$myhash{ws} =~ m/^\s*$/
and print “AND/OR regexp delete: true.\n” #こちらが print される
and delete $myhash{ws}
or print “AND/OR regexp delete: false.\n”;
しかしここに落とし穴がある。
もしエントリが空文字だったらどうだろう?以下のコードは期待どおり動作しない。
$myhash{null} =~ m/^\s*$/
and print “AND/OR regexp delete null: true.\n” # print される
and delete $myhash{null}
or print “AND/OR regexp delete null: false.\n”; # ここも print される!
delete $hash{key} は削除した要素の値を返すが、これが空文字だった場合、「false」と認識され、次の 「or ….」が実行されてしまう。
このため、false を返す可能性のある処理を挟む場合は if 文を使わなければならない。
print “IF regexp delete null: true.\n”; # print される
delete $myhash{null};
} else {
print “IF regexp delete null: false.\n”; # print されない
}
以下のような代入の場合も同じ。
and print “AND/OR set value 1: true.\n” #こちらが print される
and $val = 1
or print “AND/OR set value 1: false.\n”;
$str eq $same
and print “AND/OR set value 2: true.\n” # print される
and $val = 0
or print “AND/OR set value 2: false.\n”; # ここも print される!
ちなみに
この点が重要になるのは、and を複数連結する場合や、or の後の処理をきちんと分岐させたい場合(例えば die するなど)。
and の処理のみで終了してよい場合、一連の and で連結された処理の最後であれば false を返しても良い。