IT用語、プログラミング言語、スクリプトにおける宣言/declarationとは
変数(場合によっては定数) 共通ファイル 関数(言語による) |
等を予めファイルの先頭、関数の先頭、任意の場所または別ファイルで使用する旨を各言語の規約に沿って記述する事です。
Perlの宣言には変数宣言とPerlモジュールやクラスであることを宣言するpackage、読み込むファイルを宣言するuse、requireがあります。
Perl5においてuseは、package宣言されたファイルを取り込み、requireは、それ以外のファイルを読み込む為に使用します。
use モジュール名;
require "ファイル+拡張子";
このようにPerl5以降のバージョンでは、モジュールの読み込みは『use』、ファイルの読み込みは『require』と使い分けができますが、Perl4までは、『use』という宣言はなく、『use』用途も『require』されていた経緯があります。
また、Perl5以降のバージョンでは、strictやwarnings、その他、命名規則上、全て小文字として予約されているプラグマ(pragma、拡張子は、やはり.pm)というPerlに組み込まれたモジュールがありますが、これらは、やはり『use』で読み込みます。
更にクラス宣言で使用するpackageについては従来からあるモジュール宣言と同様であり、Perl5以降では、そのpackageとリファレンスを組み合わせてクラスとして利用できるように作られています。
$scalar;
@array;
%hash;
Perlの変数は、その種類によって(その変数を利用するより前に)宣言することもできますし、省略することもできます。
Perlは、いずれの変数においても値を代入する際に型を自動認識してくれるのでC/C++/Javaなどのように変数を宣言する際に型を指定する必要がありません(サブルーチンにおいては型指定がないので指定しませんし、それもあって仮引数も記述しません)。
また、Perlにはmy、our、localというスコープに影響する宣言時の指定があり、ここに示したような各種変数にセミコロンを付加しただけの変数宣言は、スコープと合わせて後述のように注意が必要です。
Perlの変数のスコープ(有効範囲・可視範囲)は、若干話が込み入りますが、
1.宣言する位置
2.宣言は変数のみか、my/our/localを付加するか
3.strictプラグマモジュールまたは、Strictモジュールを取り込むか否か
の3つの条件によります。
文法規則の緩やかなPerlにおいて厳密な文法で記述することを宣言する3のstrictプラグマモジュールまたはStrictモジュールについては、後述しますが、いずれかを取り込むと変数の宣言は必須、更に変数のみの宣言はエラーとなり、my、ourまたはlocalを付加しないと宣言できなくなります(warningsプラグマモジュールまたはWarningsモジュールでは警告出力されます)。
独立した位置での宣言か、{ }でくくられたサブルーチンや条件分岐、ループといった制御構造などの影響を受ける位置での宣言かでmy、our、localのスコープは変わります(が、スコープ上、変数のみの宣言は常にグローバルとなってしまいます)。
例えば、スクリプトファイル冒頭など{ }でくくられたサブルーチンなどの影響を受けずに独立して宣言する場合、つまり、下記のように記述された場合には、[変数のみ]、[my]、[our]、[local]のどの方法による宣言でもグローバル変数になってしまいます。
#!/usr/bin/perl
#!/usr/bin/perl
#!/usr/bin/perl
一方、下記のように{ }でくくられたサブルーチン内やループ内など、他の影響を受ける位置に宣言する場合には、スコープに関する影響が異なってきます。
#!/usr/bin/perl
sub foo {
...
#!/usr/bin/perl
sub foo {
...
#!/usr/bin/perl
sub foo {
...
[変数のみ宣言]した場合はそれでもグローバル変数、[local]による変数宣言では{ }内と更にサブルーチンやループがネストしている場合はそれを含めた範囲で有効なローカル変数、[my]による変数宣言では、宣言したまさにその{ }内でのみ有効な局所変数になります。
[our]については、[use strict 'vars';]とした時に[namespace::]の付加を省略できる以外は[my]とほぼ同様です。
但し、前述の通りPerlのバージョンアップの過程で厳密な文法チェックを行うstrictプラグマモジュールとStrictモジュールが生まれましたが、これらいずれかのモジュールを取り込む場合、my、our、localをつけない宣言はエラーとなります。
例えば、
#!/usr/bin/perl
# スクリプト名:test.pl
use strict;
$scalar; # ←この行が5行めだとすると...
として実行しようとすると
$ ./test.pl
Global symbol "$scalar" requires explicit package name at ./test.pl line 5.
のようなエラーが出力されますが、これは、直訳すると「グローバルシンボル$scalarは明示的なパッケージ名を要求している」、これを意訳すると「何らかのパッケージ(モジュールやクラス)で宣言されている場合を除き、グローバル宣言できない」、要は「それやっちゃダメだよ」と言われているようなものです。
モジュールやクラスファイルを作成しているわけではないし、変数宣言しなきゃいいって話でもありませんから、そう言われても困りますが、my、ourやlocalを使って宣言すれば、このエラーを回避することができます。
グローバル変数は、期せずして同名の変数があった場合バグの原因にもなりやすく、仮に承知の上であってもミスを生む可能性を高めることになるので極力限定するのが一般的で常にスコープを意識してmy、our、localによって妥当なスコープ内でのみ利用するようにした方が無難であり、ほとんどの場合それが賢明です。
strict以外にPerlではバージョン5からwarningsというプラグマモジュールを利用できますが、こうしたことからも、開発中は、常にuseしておくのがベターです。
それにより変数のみでの宣言ができなくなるので、その上でスコープを意識してmy、our、localを有効に使い分けることができれば、バグを生む可能性が激減すると思われます。
例えばグローバルとネスト範囲まで有効な変数宣言はlocal、場合によりreturnで返却する場合も含め、その場だけで使う変数はmyとするなどとするとよいかもしれません。