最近は、さすがにuse strict;されていない実践コードを目にすることもほとんどなくなってきたのだけど、まだ残っているのがuse warnings;利用。以下と併せて読んでいただけると幸いだ。
-w って何? warnings って何?
まず、以下のプログラムを見てみよう。
#!/usr/local/bin/perl
use strict;
sub distance {
my ( $a, $b ) = @_;
return sqrt( $a**2 + $b**2 );
}
print distance(@ARGV), "\n";
% perl scratch.pl 3 4 5
use strict;しているし、そして期待どおりに動いている。
しかし、以下の場合は期待どおりだろうか。
% perl scratch.pl 3 3
distance()は引数を二つ要求するのに、一つしか入れなくても動いてしまう。これは$bがundefとなり、数値コンテキストでは0として解釈されるため当然なのだけど、あなたは本当は$bを初期化しておきかったとする。どうすればよいか。
こういう時に活躍するのが、-wスイッチであり、use warnings;である。
まずは-wを見てみよう。
% perl -w d0.pl 3 Use of uninitialized value $b in exponentiation (**) at warnings.pl line 6. 3
確かに"Use of uninitialized value $b"という警告が出た。
次にuse warnings;を見てみよう。
% cat scratch.pl
#!/usr/local/bin/perl
use strict;
use warnings;
sub distance {
my ( $a, $b ) = @_;
return sqrt( $a**2 + $b**2 );
}
print distance(@ARGV), "\n";
% perl scratch.pl 3 Use of uninitialized value $b in exponentiation (**) at warnings.pl line 7. 3
こちらもきちんと警告を出している。
-w だと何がいけないの?
それでは、なぜuse warnings;を使うべきで、-wでないのか。-wの方がuse warnings;より短いではないか。
理由は二つある。
-wは.plには有効でも.pmには有効ではない
これが一番の理由である。-wはあくまでも実行時のスイッチなので、スクリプト、すなわち実行ファイルで指定しないと有効にならない。
package Distance;
use strict;
use base 'Exporter';
our @EXPORT = qw/distance/;
sub distance {
my ( $a, $b ) = @_;
return sqrt( $a**2 + $b**2 );
}
1;
scratch.pl
#!/usr/local/bin/perl use strict; use Distance; print distance(@ARGV), "\n";
と別れている場合、-wだと.plの方で指定しないと有効にならないのだ。ところが、use warnings;であれば.pmの方で指定してもきちんと警告してくれるのだ。
no warnings 'whatever';できない
use warnings;ということは、no warnings;も存在するということである。実際これは存在し、かつレキシカルなので、以下のように局所的に警告を止めることも出来る。
sub distance {
no warnings 'uninitialized';
my ( $a, $b ) = @_;
return sqrt( $a**2 + $b**2 );
}
-wでもこれに相当することは不可能ではないが、
sub distance {
local $^W = undef;
my ( $a, $b ) = @_;
return sqrt( $a**2 + $b**2 );
}
という極めて醜いものである。
まとめ
というわけで、今後スクリプトを書く時には、
use strict; use warnings;
をお忘れなきよう。
モジュールを書くのであれば、
package MyModule; use strict; use warnings;
としていただきたい。ちなみにh2xsやModule::Starterを使ってモジュールを初期生成した場合、この二行は必ず入っている。あと、Mooseにはこの二行と同等の効果も含まれている。
use warnings; # and be safe!
Dan the Perl Monger
See also:- perldoc perllexwarn
- perldoc perlrun
- perldoc perlvar
手元のリャマ本には
"#!/usr/local/bin/perl -w"
を記述しろと書いてありましたが、
今度から代わりにuse warningsを入れるようにします。