厳格な警告を使用する理由


104

Perlタグの質問の多くは、人々が使用することで解決できるように思えます。

use strict;
use warnings;

一部の人々は、これらをトレーニングホイールまたは不必要な複雑化に似ていると考えていると思います。これは、非常に熟練したPerlプログラマーでも使用するため、明らかにそうではありません。

Perlに習熟しているほとんどの人は常にこれらの2つのプラグマを使用しますが、それらを使用することから最も恩恵を受ける人はめったに使用しないようです。だから、私は人々を奨励するときに、リンクに疑問を持つように良いアイデアだと思ったuse strictwarnings

それでは、なぜPerlの開発すべきuse strictwarnings


14
私はいつも彼らはちょうどそれをデフォルトにし、DEVは実際に積極的に緩めるもの、に持っていない理由は、このようなもののためだろうuse loose;
ポールTyng

12
多くのクールで便利なものと同様に、Perlはハックとして、それを発明した人のためのツールとして始まりました。後でそれはより人気があり、ますます多くの非熟練者がそれを使い始めました。これは、あなたが何かuse strict良いことを考え始めたときですが、後方互換性はすでにあなたにとって本当の問題になっています:-(
DanielBöhmer11年

14
@JB Nizet、@ Paul T.、実際にuse strict;は、Perl 5.12(またはそれ以上)の言語を要求すると、デフォルトでオンになります。お試しくださいperl -e"use v5.012; $x=123;"no strict;実際にはオフにします。
池上

1
結局のところあなたの主張は本当ですが、私たちがそれを言う回数が増えるほど、おそらくより多くの人々が聞くでしょう。最近、より多くの/より良い/最新のPerlチュートリアルを利用できるようにする試みについていくつかの不満があり、確かに厳密/警告がこれらのそれぞれの上にあります。私の場合、すべてのスニペットの先頭にs / wを配置して、すべての初心者が毎回それを見るようにする予定です
Joel Berger

5
@JoelBergerいいえ、実際にはそのようなものは何もありません。私が言ったように、それはタイトルに同様の単語しかありません。下位互換性のためです。受け入れられた回答の最初の文は、私の質問にどのように適用されますか?
TLP

回答:


83

初心者にとってはuse strict;(そして、程度は低いですがuse warnings;)、変数名のタイプミスを見つけるのに役立ちます。経験豊富なプログラマでさえ、そのようなエラーを引き起こします。一般的なケースは、コードのクリーンアップまたはリファクタリング時に変数のインスタンスの名前を変更し忘れていることです。

を使用すると、use strict; use warnings;多くのエラーが他のエラーよりも早く検出されるため、エラーの根本的な原因を簡単に見つけることができます。根本的な原因は、エラーまたは検証チェックの必要性である可能性があり、それはプログラマーのスキルに関係なく発生する可能性があります。

Perlの警告の良い点は、それらがめったに偽らないことです。そのため、それらを使用するコストはほとんどありません。


関連資料:なぜ使用するのmyですか?


2
@TLP、私はそれがどれだけ役立つかを定量化する研究をするつもりはありません。彼らは無条件に助けになると言えば十分でしょう。
池上

1
なぜそれほど多くの利点があるのに、なぜそれがオプションになるのですか?デフォルトで有効にしませんか(上記のコメントのように)?互換性の理由ですか?
Jean

4
@Jean、後方互換性。use strict;バージョン5.12以降の言語(use 5.012;)を使用している場合、デフォルトでが有効になることに注意してください。
池上2013

@Jean単純なスクリプトを記述している場合、ファイルハンドラー名に関する警告や、変数を使用する前に変数を宣言しないことで警告を受けたくない場合:-)
user2676847

28

どうやらuse strictperlを強制的に適切にコーディングしたいときは、(強制的に)宣言を強制したり、文字列やサブワード、つまり裸語を明示したり、refを注意深く使用したりする必要があるときに使用する必要があります。注:エラーがある場合、strictを使用すると、使用すると実行が中止されます。

一方でuse warnings;、あなたはセミコロンを逃したように、あなたは「ELSIF」「のelseif」を使用していないプログラムに入力ミスを見つけましょう、あなたはどのようなことのように、非推奨の構文や関数を使用しています。注:警告を使用すると、警告のみが表示され、実行が継続されます。つまり、実行が中止されません。

とにかく、以下で詳しく説明しますが、詳細に進むとよいでしょう。

perl.com(私のお気に入り):

厳密な「vars」を使用してください。

つまり、変数を使用する前に、常に変数を宣言する必要があります。

宣言しない場合、おそらく宣言されていない変数のエラーメッセージが表示されます。

グローバルシンボル「$ variablename」には、scriptname.pl行3に明示的なパッケージ名が必要です

この警告は、変数のスコープが何であるかについてPerlが正確に明確ではないことを意味します。したがって、変数について明示する必要があります。つまりmy、現在のブロックに制限されるように変数を宣言するか、完全修飾名(例:$ MAIN :: variablename)で変数を参照します。

したがって、以下の基準の少なくとも1つを満たさない変数にアクセスしようとすると、コンパイル時エラーがトリガーされます。

  • @ ARGV、%ENVなどのPerl自体によって事前定義され、$などのすべてのグローバル句読点変数。または$ _。

  • 私たち(グローバルの場合)またはmy(語彙の場合)で宣言されています。

  • 別のパッケージからインポートされました。(use varsプラグマはインポートを偽装しますが、代わりに私たちを使用してください。)

  • パッケージ名とダブルコロンのパッケージ区切り文字を使用して完全修飾。

厳密な「サブ」を使用してください。

2つのプログラムを検討する

# prog 1
   $a = test_value;
   print "First program: ", $a, "\n";
   sub test_value { return "test passed"; }
 Output: First program's result: test_value

# prog 2
   sub test_value { return "test passed"; }
   $a = test_value;
   print "Second program: ", $a, "\n";
 Output: Second program's result: test passed

どちらの場合も、test_value()サブルーチンがあり、その結果を$ aに入れます。しかし、2つのプログラムを実行すると、2つの異なる結果が得られます。

最初のプログラムでは、に到達した時点で$a = test_value;、Perlはtest_value()サブルーチンを認識しておらず、test_valueは文字列 'test_value'として解釈されます。2番目のプログラムでは、test_value()の定義が$a = test_value;行の前にあります。Perlはtest_valueをサブ呼び出しと見なします。

潜水艦かもしれないし、コンテキストに応じた文字列であるかもしれないtest_valueのような孤立した単語のための専門用語は、方法によって、ある裸の単語。Perlのベアワードの処理は混乱を招く可能性があり、プログラムにバグを引き起こす可能性があります。

バグは最初のプログラムで発生したものですtest_value()。Perlはfindを楽しみにしないので、test_value()をまだ見ていないため、文字列が必要であると想定しています。したがって、の場合use strict subs;、このプログラムはエラーで終了します。

./a6-strictsubs.plの3行目で「strict subs」を使用している場合、単語「test_value」は許可されません。

このエラーの解決策は
1です。括弧を使用して、サブルーチンを呼び出していることを明確にします。Perlが$ a = test_value();を検出した場合、
2。最初に使用する前にサブルーチンを宣言します。

use strict;
sub test_value;  # Declares that there's a test_value() coming later ...
my $a = test_value;  # ...so Perl will know this line is okay.
.......
sub test_value { return "test_passed"; }

3.そして、それを文字列として使用するつもりなら、引用符で囲みます。

したがって、この制限により、Perlはすべての裸語を構文エラーとして扱います。* ベアワードは、コンテキストによって強制される他の解釈がないベアネームまたは識別子です。(コンテキストは多くの場合、近くのキーワードまたはトークン、または問題の単語の事前宣言によって強制されます。)*文字列として使用する場合は引用符で囲み、関数呼び出しとして使用する場合は事前宣言してくださいまたは括弧を使用します。

ベアワードは、この予測できない動作のために危険です。use strict; (or use strict 'subs';)将来奇妙な振る舞いを引き起こす可能性のある裸の言葉は、彼らが大混乱をもたらす前にあなたのプログラムを死にさせるので、それらを予測可能にします

厳密なサブをオンにしている場合でも、ベアワードを使用しても問題ない場所が1つあります。それは、ハッシュキーを割り当てるときです。

$hash{sample} = 6;   # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );

ハッシュキーのベアワードは常に文字列として解釈されるため、あいまいさはありません。

厳密な「参照」を使用します。

これにより、意図的に、またはその他の方法でシンボリック参照を使用すると、実行時エラーが発生します。ハード参照ではない値は、シンボリック参照として扱われます。つまり、参照はグローバル変数の名前を表す文字列として解釈されます。

use strict 'refs';

$ref = \$foo;       # Store "real" (hard) reference.
print $$ref;        # Dereferencing is ok.

$ref = "foo";       # Store name of global (package) variable.
print $$ref;        # WRONG, run-time error under strict refs.

警告を使用します。

このレキシカルスコープのプラグマにより、Perlの組み込み警告を柔軟に制御できます。コンパイラによって生成される警告と、ランタイムシステムから生成される警告の両方が可能です。

からperldiag

したがって、以下の分類からの警告メッセージの大部分、つまりW、D、Sは、warningsプラグマを使用して制御できます。

(W)警告(オプション)
(D)非推奨(デフォルトで有効)
(S)重大な警告(デフォルトで有効)

以下に頻繁に発生する警告メッセージのいくつかを分類別にリストしました。それらと他のメッセージの詳細についてはperldiagを参照してください

(W)警告(オプション):

%sの
引数がありません-%cの引数がありません
(代わりに&%s
を意味しましたか?)( "our"ではなく "local"
を意味しましたか?)(%ではなく$または@を意味しましたか?)
'%s 「コード基準ない
%Sに使用される)(長さ
数_見当違い

(D)非推奨(デフォルトで有効):

defined(@array)は非推奨です
defined(%hash)は非
推奨ですfalse条件でのmy()の非推奨の使用
$#はサポートされなくなりました

(S)重大な警告(デフォルトで有効)

ELSEIFはELSIFする必要があり
、オペレータが期待%sのFOUND
(%sの前に演算子がありませんが?)
(前の行にセミコロンがありません?)
%sの導入決して
%sの前に行方不明演算子またはセミコロン
の優先順位の問題:オープン%sが開いている必要があります(%sの)
プロトタイプの不一致:%sと%s
警告:括弧なしの "%s"の使用があいまい
です%sを開けません:%s


10

これら2つのプラグマは、コード内のバグを自動的に識別できます。

私はいつもこれを私のコードで使用しています:

use strict;
use warnings FATAL => 'all';

FATALと同じように、警告でコードを停止さstrictせます。

追加情報については、以下を参照してください。使用警告を使用して厳密にするFATAL => 'all';

また... 狭窄、スースによると


実際には、コンパイラーにFATAL => "all"割り当てる$SIG{__WARN__} = sub { croak "fatalized warning @_" };か、コンパイラーを台無しにして、何が必要かを伝えて、実行時まで遅延させる必要があります。
tchrist

6
@tchrist:これは常に現状のままで、文書化されているとおりに機能しています。ドキュメントどおりに機能しない場合は、を使用してドキュメントにパッチを適用してくださいperlbug
ツールの


3

ソース::さまざまなブログ

モジュールのimport()関数を呼び出して、関数と変数名をメインの名前空間にエクスポートします。

プラグマは、perlのコンパイル時または実行時の動作のいくつかの側面に影響を与えるモジュールです。プラグマは、コンパイラーにヒントを与えます。

警告を使用する-一度だけ使用された変数に関するperlの不満、文字列の数値への不適切な変換、開かれていないファイルに書き込もうとしています。コンパイル時に発生します。警告の制御に使用されます。

strictを使用-変数のスコープを宣言します。スクリプトである種の規律を設定するために使用されます。コードでベアワードが使用されている場合、それらは解釈されます。すべての変数には、my、ourまたはlocalのようなスコープを指定する必要があります。


1

「use strict」ディレクティブは、コードのコンパイル中に追加のチェックを行うようPerlに指示します。このディレクティブを使用すると、他の方法では見落とす可能性のある一般的なコーディングバグが検出されるため、Perlコードのデバッグにかかる​​時間が短縮されます。


0

厳格な警告は、変数がグローバルでないことを確認します。

ありとあらゆる変数名を追跡する必要があるのではなく、個々のメソッドに固有の変数を使用できるようにする方がずっと簡単です。

$ _、または特定の関数の変数がない場合も、よりコンパクトなコードをより速く書くのに役立ちます。

ただし、厳格な警告を使用しない場合、$ _はグローバルになります。


0
use strict;
use warnings;

厳格な警告は、perlプログラムのモードです。これにより、ユーザーはより自由にコードを入力できるようになり、そのPerlコードは正式に見え、そのコーディング標準が効果的になります。

警告は-w、perlシバン行と同じ意味であるため、perlプログラムによって生成された警告が表示され、ターミナルに表示されます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.