陳腐な答えは、構文エラーであるlocal
ため、使用する必要があるということです。my *FH
「正しい」(しかしあまり啓発的ではない)答えは、あなたが間違っているということです。代わりにレキシカル ファイルハンドルと 3 引数形式を使用する必要がありますopen
。
sub newopen {
my $path = shift;
my $fh;
open($fh, '<', $path) or do {
warn "Can't read file '$path' [$!]\n";
return;
}
return $fh;
}
理由を本当に答えるには、レキシカル変数とグローバル変数の違い、および変数のスコープとその期間の違いを説明する必要があります。
変数のスコープは、その名前が有効なプログラムの部分です。スコープは静的プロパティです。一方、変数の期間は動的プロパティです。期間は、変数が存在し、値を保持するプログラムの実行中の時間です。
my
レキシカル変数を宣言します。レキシカル変数の有効範囲は、宣言の時点から囲んでいるブロック (またはファイル) の終わりまでです。競合することなく、異なるスコープで同じ名前の他の変数を持つことができます。(重複するスコープで名前を再利用することもできますが、そうしないでください。) レキシカル変数の期間は、参照カウントによって管理されます。変数への参照が少なくとも 1 つある限り、その名前が特定のスコープ内で有効でなくても、値は存在します! my
ランタイム効果もあります。指定された名前で新しい変数を割り当てます。
local
は少し異なります。グローバル変数で動作します。グローバル変数には、グローバル スコープ (名前はどこでも有効) と、プログラムの存続期間全体があります。グローバル変数の値をlocal
一時的に変更します。これは、「動的スコープ」と呼ばれることもあります。変更は宣言の時点から始まり、囲んでいるブロックの終わりまで持続し、その後古い値が復元されます。新しい値はブロックに限定されないことに注意することが重要です。これはどこでも表示されます (呼び出されたサブルーチンを含む)。参照カウント規則は引き続き適用されるため、変更の有効期限が切れた後も、ローカライズされた値への参照を取得して保持できます。local
例に戻る:*FH
はグローバル変数です。より正確には、これは「typeglob」であり、一連のグローバル変数のコンテナーです。型グロブには、基本的な変数の型 (スカラー、配列、ハッシュ) のそれぞれに対応するスロットと、その他いくつかのものがあります。歴史的に、Perl はファイルハンドルを格納するために型グロブを使用し、local
それらを -izing することで、それらが互いに破壊しないようにしました。レキシカル変数には型グロブがないため、言ってmy *FH
いるのは構文エラーです。
最近のバージョンの Perl レキシカル変数では、代わりにファイルハンドルとして使用できますし、使用する必要があります。そして、それは「正しい」答えに戻ります。