そのほかに注意するポイント
(3)
undefの扱い方に注意する
変数を未定義にしたいときにはシステム関数であるundef
を使いますが、@y= undef
のように単にundef
を代入すると、
use Data::Dumper;
my @a = undef;
print Dumper \@a; # $VAR1 = [
# undef
# ];
my @b = ();
print Dumper \@b; # $VAR1 = [];
変数@a
にundef
の戻り値を代入しようとしたときだけ、$a[0]
にundef
が入った配列ができてしまいます。
同様に、undef
を配列に返すのも注意が必要です。
sub something1 {
return undef;
}
my @array1 = something1();
print Dumper \@array1; # $VAR1 = [
# undef
# ];
しかし、return;
のままだと警告が出て、
my %hash = (
keyA => 12345,
keyB => something2(),
keyC => undef,
);
print Dumper \%hash;
# Odd number of elements in hash assignment at..
# Use of uninitialized value in list assignment at..
# $VAR1 = {
# 'keyA' => 12345,
# 'keyB' => 'keyC',
# '' => undef
# };
そこでPerl 5.//
のあとに値を書きます。左辺が定義されている場合はそのまま、
keyB => something2() // undef,
# $VAR1 = {
# 'keyA' => 12345,
# 'keyB' => undef,
# 'keyC' => undef
# };
出力のバッファリング
Perlは出力のたびにシステムコールしないようバッファリングを行っており、$| = 1
をループの前に書きます。特殊変数$|
は、
$| = 1;
foreach ( 0..10 ){ sleep 1; print"+"; }
ファイルへ出力する場合、autoflush(1)
を呼び出すことでバッファリングが無効になります。
open my $out, '>', 'output.txt' or die $!;
$out->autoflush(1);
||とorの違い
Perlでは演算子||
の同義語としてor
がありますが、
たとえばin.
が存在しない状態で、
open my $file1, "<", "in.txt" or die $!;
open my $file2, "<", "in.txt" || die $!;
こういったコードの断片を試すにはワンライナーが一番手軽です。-e
オプションを付けてコードをシングルクォーテーションで囲い、
$ perl -e 'open $file1, "<", "in.txt" or die $!;'
No such file or directory at -e line 1.
or
を使うとNo such file or directory
とエラーが表示され異常終了します。
$ perl -e 'open $file1, "<", "in.txt" || die $!;'
$
||
を使うとdie
もされず正常終了しています$?
で確認できます)。
重要なのが演算子の優先度です。or
の優先度は一番低いため、open
が成功しているかどうかの部分が見られます。||
を使った場合は,よりも優先度が高いため、"input.
を先に見て、"input.
は文字列であり、die
しないままopen
が実行されてしまいます。こういった演算子の情報を得るには、perldoc perlop
で参照できます。
notと!の違い
否定を表すnot
と!
についても優先度があり、
次の2つのif文ではどうでしょうか。
if (not $x && $y)
if (! $x && $y)
not ! &&
の3つの演算子の優先度はperldoc perlop
によるとnot < && < !
となっています。これを当てはめると1番目はif(not($x && $y))
となり、$x
は真かつ$y
も真でなければの意味で、unless($x && $y)
と同義となります。2番目はif((!$x) && $y)
で、$x
は偽かつ$y
は真であればとなります。
今回はこれをB::Deparse
というモジュールを使って確認してみます。このモジュールはPerl側でのソースコードの解釈を出力してくれます。B::Deparse
はPerlのワンライナーでオプションとして-MO=Deparse
を付けて実行するのが手軽です。先ほどのif文とunless($x&& $y)
の3つをそれぞれ次のように実行してみます。
$ perl -MO=Deparse,-p -e 'print 1 if (not $x && $y)'
(($x and $y) or print(1));
$ perl -MO=Deparse,-p -e 'print 1 if (! $x && $y)'
((not($x) and $y) and print(1));
$ perl -MO=Deparse,-p -e 'print 1 unless ($x && $y)'
(($x and $y) or print(1));
このように処理される順番に括弧がついて出力されます。括弧を外したい場合は-p
なしで実行します。
Perlの勉強会
最後にPerlの情報収集や勉強会について紹介します。
YAPCとはYet Another Perl Conferenceの略で、
ほかにも地方pm
また、
まとめ
Perlの歴史は長く、
さて、