2006年05月21日 05:20 [Edit]

perl - use strict; # and be happy

camel

どうやら私の本では、啓蒙が全然足りなかったらしい。

Perl/CGI辞典 - 土井 毅さん 著 - にて use strict が推奨されていない件について - iandeth.
p.104
strict プラグマは、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;には、varsrefs、そして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; というものを知りました。 なんでも、Perlで、変数宣言を厳密にして、グローバル変数を禁止するためのおまじないだそうです。 このモジュール、あちこちのスクリプトでよく見かけるので調べてみたら、超有名かつ基本的なモジュールだそうです。(汗...
[Perl] use strictを導入してみた【DQNEO起業日記】at 2013年07月24日 00:45
 Macを中心にPerlを使ってスパイダの勉強をしているのですが、前回からまた色々と購入しました。 追加分です。 ・プログラミングPerl 第3版 VOL...
Perl本続々購入 "use strict"について【araiBlog】at 2009年12月29日 00:25
色々なところで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
最近は、さすがにuse strict;されていない実践コードを目にすることもほとんどなくなってきたのだけど、まだ残っているのがuse warnings;利用。以下と併せて読んでいただけると幸いだ。 404 Blog Not Found:perl - use strict; # and be happy
perl - use warnings; # -w でなくて【404 Blog Not Found】at 2008年06月19日 21:54
use strict; というものを知りました。 なんでも、Perlで、変数宣言...
[Perl] use strictを導入してみた【DQN起業日記】at 2008年02月27日 03:34
C とかもちろん知らないし、Java もさわりません。 PHPにすら手を出してませんし、JavaScriptも手探りで組んでます。 正直、use strict; って足かせなイメージでしかないです。 ...
[Perl] use strict; わかりません【お気楽極楽ブログ】at 2006年05月22日 09:00
http://blog.livedoor.jp/dankogai/archives/50502585.html なにやら use strict を推奨しない本が最近でたらしい。 use strict しなくても許されるのはワンライナーぐらいじゃないかな。 find . -type f -exec perl -i -pe 's!/usr/bin/perl!/usr/local/bin/perl!g&amp...
Perlの use strict【spiritlooseのはてなダイアリー】at 2006年05月21日 13:18
テレビでは想像つかないDanさんのuse strict;の解説。 ちょー大事だと思う。 Danさんの本でも重要だと書いていたと思うけど、僕は初めてのPerlとかのオライリー本派でした。 結局、use strict;と-Tは付けるべきと僕は思ってます(僕のサイトとかで付けてねーじゃん、ってい...
use strict;【心に優しさを】at 2006年05月21日 12:24
テレビからは想像つかない素晴らしいDanさんの本を読んで、strictは絶対必要だと思った自分。 オライリーの本など、数多くの本でも付けるべき、としているのですが、(自分のモノも含めて)実際にWebサイトで見かけるサンプルなどは付けてないなー、と。 あと、-Tも付ける...
やっぱりstrictは必須【心に優しさを】at 2006年05月21日 12:16
この記事へのコメント
有用性はよくわかるのですが、毎回毎回書かなきゃならないなら、デフォルトでstrict にしておけばよいと思うのはシロウト考えでしょうか。
Posted by へぼへぼプログラマ at 2006年05月21日 23:39
うん。そうですね。

たぶん、巷の「use strict」推奨本に足りないのは、「no strict」の紹介なんだと思います。だから受け入れられないのではないかと。

use strict原理主義だけをたたき込むと、堅苦しさを感じたり(スクリプト言語は気軽に組めるのも長所でなくてはいけません)、昔のperlスクリプトがうまく動作しなかったりして(互換性重要)、「strictだめじゃん」っていう印象を与えてしまう。

例のようにno strictをきちんと教えておけば、必要なときの対処のしかたと同時にスコープへの理解も深まるので一石二鳥。もちろんno strictが「必要なとき」というのは原理主義的には「ない!」かもしれませんが、過去のコーディングスタイルからの移行を考えるとやはり必要です。

パソコンの電源の入れ方と同時に切り方も教えるのと同じですね。型を教えつつ、その型の崩し方も教えるような。
Posted by Bar at 2006年05月21日 12:24