最近は、さすがに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を入れるようにします。