2006年05月21日 05:20 [Edit]
perl - use strict; # and be happy
どうやら私の本では、啓蒙が全然足りなかったらしい。
Perl/CGI辞典 - 土井 毅さん 著 - にて use strict が推奨されていない件について - iandeth.p.104strict プラグマは、Perlスクリプトでの記法を厳密にするためのプラグマです。 (中略) これにより、宣言の曖昧な変数への参照を発見できます。[参考] strict プラグマは厳密すぎるため、通常のプログラミングではあまり使用しません。... orz
この本が20世紀に出たというのであれば驚かないけど、今年に出たというのは、Perl5 Porterとしてもショックである。
しかし、確かにuse strict; # or dieという姿勢だけではなく、use strict; # and be happyという姿勢も必要なのだと思う。
Perl/CGI辞典 - 土井 毅さん 著 - にて use strict が推奨されていない件について - iandeth.Perl言語をこれから使おうとして、この本を手に取っている人達に対して strictプラグマ を「あまり使いません」と切って捨てちゃ駄目だと思う (悲)。
というわけで、改めてuse strictが何をするのかを、改めて解説します(ここからですます調)。
使い方
これだけです。
#!/usr/local/bin/perl use strict;
なにはなくとも#!の直下の行にuse strictと書くだけ。ついでなので、use strictされていないperl scriptを見つけるscriptを以下に。
#!/usr/bin/env perl
use strict;
use warnings;
use Getopt::Std;
use File::Find ();
my %opt;
getopts("v" => \%opt);
push @ARGV, '.' unless @ARGV;
sub check{
my $path = shift;
open my $fh, '<', $path or die "$path : $!";
my $text = do{ local $/; <$fh> };
close $fh;
my @ok = ('not strict', 'strict');
my $ok = $text =~ /^use\s+strict;/m ? 1 : 0;
print "$path\t: $ok[$ok]\n" if ($opt{v} or !$ok);
}
sub wanted {
my ($dev,$ino,$mode,$nlink,$uid,$gid);
(($dev,$ino,$mode,$nlink,$uid,$gid) = lstat($_)) or return;
-f _ or return;
/\w.*\.(?:pl|pm|t)\z/s or return;
check($File::Find::name);
}
File::Find::find({wanted => \&wanted}, @ARGV);
__END__
何をするか
ここで問題です。以下のプログラムは何をするでしょうか?
#!/usr/local/bin/perl my $hel1o = "hello, world!"; print $hello, "\n";
答え:ただの空行が出力されます。しかしこれはあなたが期待していた出力でしょうか?
ここで、use strictしてみましょう。
#!/usr/local/bin/perl
use strict;
my $hel1o = "hello, world!";
print $hello, "\n";
今度は、
Global symbol "$hello" requires explicit package name at ...
というメッセージを出して止まったはずです。実は$hel1oは$hel1oとなっていて、$helloはどこにも使われていなかったのです。
人の目で見つけるより、perlに見つけさせた方がよくありませんか?strictがそれをやってくれるのです。
必要なときにだけ、no strict 'refs';
どうしてもuse strictでプログラムが動かない場合も、該当箇所だけ選んでその効果を切る事ができます。以下では、ピンクの部分だけ選択的にstrictの影響を切っています。
sub make_instances {
my ( $pkg, $arg_ref ) = @_;
croak 'Usage: ' . $pkg . '->new({key => val, ...})'
unless ref $arg_ref eq 'HASH';
for my $arg ( keys %$arg_ref ) {
no strict 'refs';
*{ $pkg . '::get_' . $arg } = sub($) {
my $self = shift;
return $self->{$arg};
}
if $arg_ref->{$arg} =~ /r/;
*{ $pkg . '::set_' . $arg } = sub($$) {
my $self = shift;
return $self->{$arg} = shift;
}
if $arg_ref->{$arg} =~ /w/;
}
}
ここでno strict 'refs';となっている点に注目してください。ただのno strict;ではなく。実は、use strict;には、vars、refs、そしてsubsという3種類の効果がありますが、no strict;ではこの三種類の効果を全部殺してしまいます。だから、他を活かしたまま必要なところだけ切るという使い方をするわけです。
実際問題、必要となるのはこのno strict 'refs';だけでしょう。varsはすでにourがあるためほとんど不要ですし、subsは\&subnameという書き方があるため、これもまたほとんど不要です。そしてno strict 'refs';が本当に必要なのは、中級以上のscriptだけです。
まとめ
いかがでしょう?これでもstrictは不要ですか?
本当の友は、あなたのいい点だけではなく、あなたの問題点も指摘してくれるといいます。そういう人こそ友だというあなたは、use strictでよりperlをフレンドリーなものにしてください。
なお、Perl 6では、このstrict(とwarnings)が標準となります。例外は-eをつけて、コマンドラインから実行する場合だけです。
こんなとこかな。
Perl/CGI辞典 - 土井 毅さん 著 - にて use strict が推奨されていない件について - iandeth.いや、僕が一人で書くのではなくて、ここは Perl 好きなみんなの力を合わせて、共同で「Perl はこんなに便利だよ・楽しいよ」的な初級 - 中級レベルの本を執筆してみませんか?
実は本に関しては、新たな企画が進行中です。もうすぐ発表できると思います。乞うご期待!
Dan the Strict, Friendly Perl Monger
この記事へのトラックバックURL
たぶん、巷の「use strict」推奨本に足りないのは、「no strict」の紹介なんだと思います。だから受け入れられないのではないかと。
use strict原理主義だけをたたき込むと、堅苦しさを感じたり(スクリプト言語は気軽に組めるのも長所でなくてはいけません)、昔のperlスクリプトがうまく動作しなかったりして(互換性重要)、「strictだめじゃん」っていう印象を与えてしまう。
例のようにno strictをきちんと教えておけば、必要なときの対処のしかたと同時にスコープへの理解も深まるので一石二鳥。もちろんno strictが「必要なとき」というのは原理主義的には「ない!」かもしれませんが、過去のコーディングスタイルからの移行を考えるとやはり必要です。
パソコンの電源の入れ方と同時に切り方も教えるのと同じですね。型を教えつつ、その型の崩し方も教えるような。