2008年06月19日 21:45 [Edit]

perl - use warnings; # -w でなくて

camel

最近は、さすがに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()は引数を二つ要求するのに、一つしか入れなくても動いてしまう。これは$bundefとなり、数値コンテキストでは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はあくまでも実行時のスイッチなので、スクリプト、すなわち実行ファイルで指定しないと有効にならない。

Distance.pm
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;

としていただきたい。ちなみにh2xsModule::Starterを使ってモジュールを初期生成した場合、この二行は必ず入っている。あと、Mooseにはこの二行と同等の効果も含まれている。

use warnings; # and be safe!

Dan the Perl Monger

See also:

この記事へのトラックバックURL

この記事へのトラックバック
perl -w と use warningsの違いがずっとわからなかったのですが、dankogaiさんの超わかりやすい解説を見てやっと理解できました。...
[Perl] -w とuse warnigs;の違いについて【DQNEO起業日記】at 2011年08月01日 03:14
色々なところでperlのプログラムはuse strictを使うようにという記事を見かける。 □Perlで必須の記述 use strict と use warnings - Sakura scope □404 Blog Not Found:perl - use strict; # and be happy そこで、いつも使っている送信フォーム用のcgiプログラムにuse ...
「use strict」に対応させる簡単な改造方法【perl】【地方の中規模印刷会社で苦悩するWebデザイナー改めWebディレクターの日記】at 2009年02月09日 17:19
これに対する真面目な解答とちょっと不真面目な解決策を。 strict プラグマについて - perl-mongers.org 「use strict; って何でデフォルトでオンになってないの?」 言われてみれば確かに。何でなんでしょうか?
perl - use strict なしでstrictに【404 Blog Not Found】at 2008年07月10日 22:39
以下のエラー処理の方法にちょっと口を挟みたくなったので。 エラー処理を行う。 - サンプルコードによる Perl 入門
perl - use Carp; # warn() と die() だけじゃなくて【404 Blog Not Found】at 2008年06月30日 04:06
404 Blog Not Found:perl - use warnings; # -w でなくて # 2008年06月20日 mzp mzp *プログラム参考, Perl use warningsで再帰を書くと、毎回警告されるのがうざい。 http://b.hatena.ne.jp/mzp/20080620#bookmark-9012282 id:mzpさんのブクマ米にちょっくら反応。 再帰で
[Perl]no warnings ’whatever’【Unknown::Programming】at 2008年06月20日 17:17
著者より献本御礼。 すぐわかるオブジェクト指向Perl 深沢千尋 「すぐわかる」のタイトルに反して、「すぐにわからない人が、すぐではなくあくまで自分のペースでゆっくり学ぶ」のに向いた良書。ウサギタイプではなく、カメタイプの人が Perl を学ぶのであれば、....
$this->get if $you->learn(slow) - 書評 - すぐわかるオブジェクト指向Perl【404 Blog Not Found】at 2008年06月20日 01:04
perl -w と use warningsの違いがずっとわからなかったのですが...
[Perl] -w とuse warnigs;の違いについて【DQN起業日記】at 2008年06月20日 00:49
この記事へのコメント
そんな違いがあったのですか。
手元のリャマ本には
"#!/usr/local/bin/perl -w"
を記述しろと書いてありましたが、
今度から代わりにuse warningsを入れるようにします。
Posted by 通りすがり at 2008年06月20日 16:57
某全角を半角に変換するときとかに
文字コードのマッピングは歴史的経緯で正しいマッピングがされてない文字が何文字か有り UTF-8 to EUC to UTF-8で もとの文字コードに戻れない文字が存在するために、文字化けする。

という文字コード当たりのWarningが表示されるオプションも欲しいです。MS932を作った人が、まぁあれはしょうがないんだよ〜とかさぁ、しょうがないじゃん?いいじゃん、適当でと、僕の目の前でそのバグを報告したときにおっしゃっていましたが、そんなこといわれても、文字化けする物はするんだよと。全角を半角変換テーブルを自作した僕が通ります。

文字コード周りは文字コードの仕様事態にバグがある文字があるので・・・だれかワーニング作ってよとか思います。本当に、泣きました。
Posted by 心は萌え at 2008年06月20日 14:44