blog20100901

2013/08/20 - プログラミング言語 Perl にまつわる etc. - Perl monger
参考 : perldoc, perldoc.jp, search.cpan.org, perldoc.perl.org ...
「 初めての Perl 第 6 版 」(オライリー・ジャパン発行 ISBN978-4-87311-567-2) 」
「 続・初めての Perl 改訂版 」(オライリー・ジャパン発行 ISBN4-87311-305-9) 」
「 Effective Perl 第 2 版 」(翔泳社発行 ISBN978-4-7981-3981-4) 」 ... etc,.

Perl Perl_7 mod_perl 翻訳

Perl mp2 翻訳 Perl リファレンス (d207)

目次 - Perl Index


Theme



Perl について、復習を兼ねて断片的な情報を掲載して行く連載その d207 回。

今回は、「 Documentation / General Documentation / Part I: Perl / Perl Reference 」を翻訳して確認します。

正確な内容は 原文 を確認してください。誤解や誤訳がある場合はご指摘ください。




Description



This document was born because some users are reluctant to learn Perl, prior to jumping into mod_perl. I will try to cover some of the most frequent pure Perl questions being asked at the list.

このドキュメントは mod_perl に飛びつくまえに, 一部のユーザが Perl を学ぶことに消極的なために生まれました。私はリスト (# メーリングリスト) で尋ねられるよくあるピュア Perl の質問の一部をカバーすることにトライします。
Before you decide to skip this chapter make sure you know all the information provided here. The rest of the Guide assumes that you have read this chapter and understood it.

あなたがこのチャプタをスキップする前にここで提供されている情報をすべてあなたが知っているかを確認してください。残りのガイドはあなたがこのチャプタを読んでそれを理解していることを想定しています。


perldoc のあまり知られていないがとても便利なオプション : perldoc's Rarely Known But Very Useful Options



First of all, I want to stress that you cannot become a Perl hacker without knowing how to read Perl documentation and search through it. Books are good, but an easily accessible and searchable Perl reference at your fingertips is a great time saver. It always has the up-to-date information for the version of perl you're using.

まず最初に, どのように Perl ドキュメントを読みそれを通じて検索するかを知ることなくしてあなたが Perl ハッカーにはなれないことを私は強調したいです。本は良いですが, あなたの指先で簡単にアクセスできて検索できる Perl リファレンスはグレートな時間の節約です。それは常にあなたが使っている perl のバージョンの最新の情報をもっています。
Of course you can use online Perl documentation at the Web. The two major sites are http://perldoc.perl.org and http://theoryx5.uwinnipeg.ca/CPAN/perl/.

もちろんあなたはウェブ上でオンラインの Perl ドキュメントを使うことができます。2 つのメジャーなサイトは http://perldoc.perl.org と http://theoryx5.uwinnipeg.ca/CPAN/perl/ です。
The perldoc utility provides you with access to the documentation installed on your system. To find out what Perl manpages are available execute:

perldoc ユーティリティはあなたのシステムにインストールされたドキュメントへのアクセスをあなたに提供します。Perl man ページを見つけだすにはこの実行が利用できます:

% perldoc perl

To find what functions perl has, execute:

perl がもっているファンクションを見つけるには, これを実行します:

% perldoc perlfunc

To learn the syntax and to find examples of a specific function, you would execute (e.g. for open()):

特定のファンクションのシンタックスと例を見つけるには, あなたはこれを実行できます (e.g. open() のために):

% perldoc -f open

Note: In perl5.005_03 and earlier, there is a bug in this and the -q options of perldoc. It won't call pod2man, but will display the section in POD format instead. Despite this bug it's still readable and very useful.

ノート: perl5.005_03 以前では, perldoc のこれと -q オプションでバグがあります。それは pod2man をコールしませんが, かわりに POD フォーマットでセクションを表示します。このバグにも関わらずそれは依然として読みやすくとても便利です。
The Perl FAQ (perlfaq manpage) is in several sections. To search through the sections for open you would execute:

Perl FAQ (perlfaq man ページ) はいくつかのセクションです。そのセクションを通じて open を検索するためにあなたはこれを実行できます:

% perldoc -q open

This will show you all the matching Question and Answer sections, still in POD format.

これはPOD フォーマットのままで, マッチするクエスチョンと回答セクションの全てをあなたに示します。
To read the perldoc manpage you would execute:

perldoc man ページを読むためにあなたはこれを実行できます:

% perldoc perldoc



Warnings リポートの追跡 : Tracing Warnings Reports



Sometimes it's very hard to understand what a warning is complaining about. You see the source code, but you cannot understand why some specific snippet produces that warning. The mystery often results from the fact that the code can be called from different places if it's located inside a subroutine.

ときどき warning が文句をいっているものを理解するのがとても難しいことがあります。あなたはソースコードを見ますが, なぜ特定のスニペットがその warning を生成するのかをあなたは理解できません。このミステリはそれがサブルーチンの内部に配置されいた場合に異なる場所からコードがコールされうるということの結果であることがよくあります。
Here is an example:

こちらが例です:

#warnings.pl
#-----------
#!/usr/bin/perl -w

use strict;

correct();
incorrect();

sub correct{
print_value("Perl");
}

sub incorrect{
print_value();
}

sub print_value{
my $var = shift;
print "My value is $var\n";
}

In the code above, print_value() prints the passed value. Subroutine correct() passes the value to print, but in subroutine incorrect() we forgot to pass it. When we run the script:

上記コードで, print_value() は渡された値を出力します。サブルーチン correct() は print に値を渡しますが, incorrect() サブルーチンでは私たちはそれを渡すことを忘れました。私たちがこのスクリプトを実行すると:

% ./warnings.pl

we get the warning:

私たちはこの warning をゲットします:

Use of uninitialized value at ./warnings.pl line 16.

Perl complains about an undefined variable $var at the line that attempts to print its value:

Perl は未定義の変数 $var の値の出力を試みている行について文句をいっています:

print "My value is $var\n";

But how do we know why it is undefined? The reason here obviously is that the calling function didn't pass the argument. But how do we know who was the caller? In our example there are two possible callers, in the general case there can be many of them, perhaps located in other files.

しかしなぜそれが未定義なのかを私たちはどのように知ることができるのでしょうか ? ここでの明確な理由はコールしているファンクションが引数を渡していないことです。しかし私たちは誰がコーラー (# 呼び出し元) なのかをどうやって知るのでしょうか ? 私たちの例では考えられる 2 つのコーラーがありますが, 一般的なケースでは多くのそれがあり, 他のファイルに位置していることだってあります。
We can use the caller() function, which tells who has called us, but even that might not be enough: it's possible to have a longer sequence of called subroutines, and not just two. For example, here it is sub third() which is at fault, and putting sub caller() in sub second() would not help us very much:

私たちは私たちに誰がコールしたかを伝えてくれる, caller() ファンクションを使うことができますが, それだけでは十分でないかもしれません: コールされたサブルーチンのシーケンスをより長くすることもできます, 2 つだけでなく。例えば, ここで失敗しているのは sub third() で, sub second() に sub caller() を置いても私たちにはあまりヘルプになりません:

sub third{
second();
}
sub second{
my $var = shift;
first($var);
}
sub first{
my $var = shift;
print "Var = $var\n";
}

The solution is quite simple. What we need is a full calls stack trace to the call that triggered the warning.

解決策はかなりシンプルです。私たちに必要なのは warning をトリガしたそのコールへの完全なコールのスタックトレースです。
The Carp module comes to our aid with its cluck() function. Let's modify the script by adding a couple of lines. The rest of the script is unchanged.

Carp モジュールはその cluck() ファンクションで私たちの補助になります。2 つの行を追加することでスクリプトを修正しましょう。スクリプトの残りは未変更です。

#warnings2.pl
#-----------
#!/usr/bin/perl -w

use strict;
use Carp ();
local $SIG{__WARN__} = \&Carp::cluck;

correct();
incorrect();

sub correct{
print_value("Perl");
}

sub incorrect{
print_value();
}

sub print_value{
my $var = shift;
print "My value is $var\n";
}

Now when we execute it, we see:

これで私たちがこれを実行すると, 私たちはこれをみることになります:

Use of uninitialized value at ./warnings2.pl line 19.
main::print_value() called at ./warnings2.pl line 14
main::incorrect() called at ./warnings2.pl line 7

Take a moment to understand the calls stack trace. The deepest calls are printed first. So the second line tells us that the warning was triggered in print_value(); the third, that print_value() was called by subroutine, incorrect().

コールのスタックトレースを理解するために少し時間をとってください。もっとも深いコールが最初に出力されます。ですから 2 番目の行は print_value() で warning がトリガされたことを私たちに伝えます; 3 番目は, サブルーチン incorrect() によって, print_value() がコールされています。

script => incorrect() => print_value()

We go into incorrect() and indeed see that we forgot to pass the variable. Of course when you write a subroutine like print_value it would be a good idea to check the passed arguments before starting execution. We omitted that step to contrive an easily debugged example.

私たちは incorrect() の中に行き私たちが変数を渡すことを忘れていることを確かに見ます。もちろんあなたが print_value のようなサブルーチンを書くとき実行を開始する前に渡される引数をチェックすることはグッドアイデアです。私たちは簡単にデバッグできる例を考案するためにそのステップを省略しました。
Sure, you say, I could find that problem by simple inspection of the code!

確かに, あなたはいいます, 私はコードのシンプルな調査でその問題を見つけることができたはずです !
Well, you're right. But I promise you that your task would be quite complicated and time consuming if your code has some thousands of lines. In addition, under mod_perl, certain uses of the eval operator and "here documents" are known to throw off Perl's line numbering, so the messages reporting warnings and errors can have incorrect line numbers. (See Finding the Line Which Triggered the Error or Warning for more information).

ええ, あなたは正しいです。しかしあなたのコードが数千行ある場合ではあなたのタスクがとても複雑になって時間がかかるようになることを私はあなたに約束しましょう。加えて, mod_perl のもとでは, 特定の eval オペレータの使用法と "here documents" が Perl の行番号を投げ捨てることが知られているので, warnings と エラーをリポートするメッセージは正しくない行番号をもっていることがあります。(詳細のために Finding the Line Which Triggerd the Error or Warning を参照してください)。

via: Finding the Line Which Triggerd the Error or Warning (https://perl.apache.org/docs/1.0/guide/debug.html#Finding_the_Line_Which_Triggered_the_Error_or_Warning)


Finding the Line Which Triggered the Error or Warning



Perl has no problem with the line numbers and file names for modules that are read from disk in the normal way, but modules that are compiled via eval() such as Apache::Registry and Apache::PerlRun sometimes with some versions of Perl get confused.

Perl は普通の方法でディスクから読まれるモジュールの行番号とファイル名では問題をもっていませんが, Apache::Registry や Apache::PerlRun のような eval() を介してコンパイルされるモジュールは Perl のバージョンによってはときどき混乱することになります。
There is the Perl <<HEREDOC inside eval "" problem that confuses the Perl current linenumber counter, newer Perls fix this. For older Perls compiling with the experimental PERL_MARK_WHERE=1 should solve this.

Perl <<HEREDOC の内側の eval "" には Perl の現在の行番号カウンタを混乱させる問題があり, 新しい Perl はこれを fix します。古い Perl では実験的な PERL_MARK_WHERE=1 でコンパイルしてこれを解決できるはずです。
Also if you happen to use line continuation \ your script, the line numbering will be off as well, since eval eats those \'s and combines the lines together. The solution: do not use \'s to mark lines as continued in Perl. Unlike shell languages, Perl doesn't require you to do that.

またあなたがあなたのスクリプトでたまたま行の継続の \ を使っている場合, eval はそれらの \ を食べて行を一緒に結合するので, その行番号もオフになります。その解決策: Perl での行を継続するためのマークに \ を使わない。shell 言語と異なり, Perl はあなたがそれを行うことを必要としません。
There are compiler directives to reset its counter to some value that you decide. You can always pepper your code with these to help you locate the problem. At the beginning of the line you could write something of the form:

あなたが決めた何らかの値にそのカウンタをリセットするためのコンパイラディレクティブがあります。あなたはあなたが問題を突き止めることをヘルプするために常にこれらをあなたのコードに常に振りかけることができます。行の先頭であなたはこの形式の何かを書くことができます:

#line nnn label

For example:

例えば:

#line 298 myscript.pl
or
#line 890 some_label_to_be_used_in_the_error_message

The '#' must be in the first column, so if you cut and paste from this text you must remember to remove any leading white space.

'#' が最初のカラムでなければなりませんので, あなたがこのテキストからカットアンドペーストする場合あなたは先頭の空白を削除することを忘れないでください。
The label is optional - the filename of the script will be used by default. This directive sets the line number of the following line, not the line the directive is on. You can use a little script to stuff every N lines of your code with these directives, but then you will have to remember to rerun this script every time you add or remove code lines. The script:

ラベルはオプショナルです - スクリプトのファイル名はデフォルトで使われます。このディレクティブはその次の行をセットします, ディレクティブの行ではなく。あなたはあなたのコードの N 行ごとにこれらのディレクティブを詰め込むために小さなスクリプトを使えますが, あなたがコード行を追加や削除するたびにこのスクリプトを再実行することをあなたは覚えておかなければなりません。そのスクリプトがこれです:

#!/usr/bin/perl
# Puts Perl line markers in a Perl program for debugging purposes.
# Also takes out old line markers.
# デバッグ目的で Perl プログラム内に Perl ラインマーカを置きます。
# また古いラインマーカも取りだします。
die "No filename to process.\n" unless @ARGV;
my $filename = shift;
my $lines = 100;
open IN, $filename or die "Cannot open file: $filename: $!\n";
open OUT, ">$filename.marked"
or die "Cannot open file: $filename.marked: $!\n";
my $counter = 1;
while (<IN>) {
print OUT "#line $counter\n" unless $counter++ % $lines;
next if /^#line /;
print OUT $_;
}
close OUT;
close IN;
chmod 0755, "filename.marked";

Another way of narrowing down the area to be searched is to move most of the code into a separate modules. This ensures that the line number will be reported correctly.

検索する範囲を絞り込む別の方法は別のモジュールにコードのほとんどを移動することです。これは行番号が正しくリポートされるようにします。
To have a complete trace of calls add:

コールの完全なトレースをもつにはこれを追加します:

use Carp ();
local $SIG{__WARN__} = \&Carp::cluck;




Getting the trace helps a lot.

トレースの取得は大きなヘルプになります。


グローバル, レキシカルスコープそれから完全修飾された変数 : Variables Globally, Lexically Scoped And Fully Qualified



META: this material is new and requires polishing so read with care.

このマテリアルは新しくて磨く必要があるので注意して読んでください。
You will hear a lot about namespaces, symbol tables and lexical scoping in Perl discussions, but little of it will make any sense without a few key facts:

あなたは Perl のディスカッションで名前空間, シンボルテーブルそれからレキシカルスコーピングについて多くを聞くでしょうが, いくつかの重要な事実なくしてはあまり意味がないものになります:


シンボル, シンボルテーブルそれからパッケージ; タイプグロブ : Symbols, Symbol Tables and Packages; Typeglobs



There are two important types of symbol: package global and lexical. We will talk about lexical symbols later, for now we will talk only about package global symbols, which we will refer to simply as global symbols.

2 つの重要なシンボルのタイプがあります: パッケージグローバルとレキシカルです。私たちはレキシカルシンボルについては後でお話しします, 今のところはパッケージグローバルシンボルについてのみお話しし, それを私たちはシンプルにグローバルシンボルといいます。
The names of pieces of your code (subroutine names) and the names of your global variables are symbols. Global symbols reside in one symbol table or another. The code itself and the data do not; the symbols are the names of pointers which point (indirectly) to the memory areas which contain the code and data. (Note for C/C++ programmers: we use the term `pointer' in a general sense of one piece of data referring to another piece of data not in a specific sense as used in C or C++.)

あなたのコードの一部の名前 (サブルーチン名) とあなたのグローバル変数の名前はシンボルです。グローバルシンボルはいずれかのシンボルテーブルに存在します。コードそれ自体とデータはそうではありません; シンボルはそのコードとデータを含むメモリエリアを (間接的に) 指し示すポインタの名前です。(C/C++ プログラマのためのノート: 私たちは C や C++ で使われる特定の意味でではなくてあるデータの一部が他のデータの一部を参照する一般的な意味で用語 `ポインタ' を使います。)
There is one symbol table for each package, (which is why global symbols are really package global symbols).

各パッケージのためにひとつのシンボルテーブルがあります, (これがグローバルシンボルが実際にはパッケージグローバルシンボルな理由です。)
You are always working in one package or another.

あなたは常にいずれからのパッケージで作業します。
Like in C, where the first function you write must be called main(), the first statement of your first Perl script is in package main:: which is the default package. Unless you say otherwise by using the package statement, your symbols are all in package main::. You should be aware straight away that files and packages are not related. You can have any number of packages in a single file; and a single package can be in one file or spread over many files. However it is very common to have a single package in a single file. To declare a package you write:

最初にあなたが書くファンクションが main() とコールされなければならない, C でのように, あなたの最初の Perl スクリプトの最初のステートメントはパッケージ main:: にありそれがデフォルトのパッケージです。あなたが package ステートメントを使ってあなたが何かをいわない限り, あなたのシンボルはすべてパッケージ main:: です。あなたはファイルとパッケージが関連していないことにすぐに気づくはずです。あなたはひとつのファイルで任意の数の package をもつことができます; それからひとつのパッケージはひとつのファイルや複数のファイルに散らすことができます。しかしひとつのファイルにひとつのパッケージをもつことがとても一般的です。パッケージを宣言するためにあなたはこれを書きます:

package mypackagename;

From the following line you are in package mypackagename and any symbols you declare reside in that package. When you create a symbol (variable, subroutine etc.) Perl uses the name of the package in which you are currently working as a prefix to create the fully qualified name of the symbol.

続く行からあなたはパッケージ mypackagename の中であなたが宣言するすべてのシンボルはそのパッケージにあります。あなたがシンボルを作成したとき (変数, サブルーチン etc.) Perl はシンボルの完全修飾名を作成するためにあなたが現在作業しているパッケージの名前をプレフィックスとして使います。
When you create a symbol, Perl creates a symbol table entry for that symbol in the current package's symbol table (by default main::). Each symbol table entry is called a typeglob. Each typeglob can hold information on a scalar, an array, a hash, a subroutine (code), a filehandle, a directory handle and a format, each of which all have the same name. So you see now that there are two indirections for a global variable: the symbol, (the thing's name), points to its typeglob and the typeglob for the thing's type (scalar, array, etc.) points to the data. If we had a scalar and an array with the same name their name would point to the same typeglob, but for each type of data the typeglob points to somewhere different and so the scalar's data and the array's data are completely separate and independent, they just happen to have the same name.

あなたがシンボルを作成したとき, Perl は現在のパッケージのシンボルテーブル (デフォルトでは main::) にそのシンボルのためにシンボルテーブルエントリを作成します。各シンボルテーブルエントリは typeglob と呼ばれます。各 typeglob はスカラ, 配列, ハッシュ, サブルーチン (code), ファイルハンドル, ディレクトリハンドルそれからフォーマットで情報を保持できて, それらはそれぞれすべて同じ名前を持ちます。ですからあなたはグローバル変数の 2 つの間接参照を見ることになります: シンボル, (そのモノの名前), はその typeglob を指し示しそのモノのタイプ (スカラ, 配列, etc.) の typeglob はそのデータを指し示します。私たちが同じ名前でスカラと配列を持っている場合それらの名前は同じ typeglob を指し示しますが, 各データのタイプではその typeglob はどこかしら違う場所を指し示すのでスカラのデータと配列のデータは完全に分けられていて独立しており, それらはたまたま同じ名前をもっているにすぎません。
Most of the time, only one part of a typeglob is used (yes, it's a bit wasteful). You will by now know that you distinguish between them by using what the authors of the Camel book call a funny character. So if we have a scalar called `line' we would refer to it in code as $line, and if we had an array of the same name, that would be written, @line. Both would point to the same typeglob (which would be called *line), but because of the funny character (also known as decoration) perl won't confuse the two. Of course we might confuse ourselves, so some programmers don't ever use the same name for more than one type of variable.

ほとんどの場合, typeblob の一部のみが使われます (イエス, それは少し無駄です)。あなたはこれでラクダ本の作者がファニーキャラクタと呼ぶものを使ってあなたがこれらを区別することを知ります。ですから私たちが `line' と呼ばれるスカラをもっている場合私たちはコードでそれを $line として参照でき, 私たちが同じ名前の配列をもっていたなら, それは @line, と書かれます。両方とも同じ typeblob (*line と呼ばれる) を指し示しますが, ファニーキャラクタ (デコレーションとしても知られる # あるいはシジル) により perl はその 2 つを混同しません。もちろん私たちは私たち自身で混乱するかもしれませんので, 一部のプログラマは変数の複数のタイプに決して同じ名前を使いません。
Every global symbol is in some package's symbol table. To refer to a global symbol we could write the fully qualified name, e.g. $main::line. If we are in the same package as the symbol we can omit the package name, e.g. $line (unless you use the strict pragma and then you will have to predeclare the variable using the vars pragma). We can also omit the package name if we have imported the symbol into our current package's namespace. If we want to refer to a symbol that is in another package and which we haven't imported we must use the fully qualified name, e.g. $otherpkg::box.

すべてのグローバルシンボルは何らかのパッケージのシンボルテーブル内にあります。グローバルシンボルを参照するために私たちは完全修飾名を書けます, e.g. $main::line。もし私たちがシンボルと同じパッケージにいる場合私たちはパッケージ名を省略できます, e.g. $line (あなたが strict プラグマを使っていないならあなたは vars プラグマを使って変数を事前に宣言しておかなければなりません)。私たちは私たちが私たちの現在のパッケージの名前空間にインポートされたシンボルを持っているならパッケージ名も省略でいます。私たちが他のパッケージのシンボルを参照したくてインポートされたそれをもっていないなら私たちは完全修飾名を使わなければなりません, e.g. $otherpkg::box。
Most of the time you do not need to use the fully qualified symbol name because most of the time you will refer to package variables from within the package. This is very like C++ class variables. You can work entirely within package main:: and never even know you are using a package, nor that the symbols have package names. In a way, this is a pity because you may fail to learn about packages and they are extremely useful.

ほとんどの場合あなたはパッケージ変数をそのパッケージ内から参照するのでほとんどの場合であなたは完全修飾名を使う必要はありません。これは C++ クラス変数ととてもよく似ています。あなたはパッケージ main:: 内ですべての作業ができてあなたがパッケージを使っているだけでなく, シンボルがパッケージ名をもっていることさえ知ることはありません。それが極めて便利であなたがパッケージについて学ぶことができないのである意味, これは残念です。
The exception is when you import the variable from another package. This creates an alias for the variable in the current package, so that you can access it without using the fully qualified name.

例外はあなたが他のパッケージから変数を import するときです。これは現在のパッケージにその変数のエイリアスを作成しますので, あなたは完全修飾名を使うことなくそれにアクセスできます。
Whilst global variables are useful for sharing data and are necessary in some contexts it is usually wisest to minimize their use and use lexical variables, discussed next, instead.

グローバル変数はデータの共有で便利であり状況により必要ですが通常はその利用を最小限にして, かわりに, 次で論じる, レキシカル変数を使用するのがもっとも賢明です。
Note that when you create a variable, the low-level business of allocating memory to store the information is handled automatically by Perl. The intepreter keeps track of the chunks of memory to which the pointers are pointing and takes care of undefining variables. When all references to a variable have ceased to exist then the perl garbage collector is free to take back the memory used ready for recycling. However perl almost never returns back memory it has already used to the operating system during the lifetime of the process.

あなたが変数を作成するとき, 情報を格納するためのメモリ割り当ての低レベルの仕事は Perl によって自動的に処理されることに注意してください。インタプリタはポインタが指し示すメモリチャンク (# 塊り) を追跡し未定義の変数の対処をします。変数へのリファレンスすべてが消滅すると perl ガベージコレクタがリサイクルのために既に使われているメモリを解放します。しかし perl はプロセスのライフタイムの間でオペレーティングシステムにすでに使用されたメモリをほとんどリターンしません。


レキシカル変数とシンボル : Lexical Variables and Symbols



The symbols for lexical variables (i.e. those declared using the keyword my) are the only symbols which do not live in a symbol table. Because of this, they are not available from outside the block in which they are declared. There is no typeglob associated with a lexical variable and a lexical variable can refer only to a scalar, an array, a hash or a code reference. (Since perl-5.6 it can also refer to a file glob).

レキシカル変数のシンボル (i.e. キーワード my を使って宣言されたもの) はシンボルテーブルに存在しない唯一のシンボルです。このため, それらが宣言されたブロックの外側からは利用できません。レキシカル変数と関連づいた typeglob はなくレキシカル変数はスカラ, 配列, ハッシュまたはコードリファレンスとしてのみを参照できます。(perl-5.6 からそれはファイルグロブも参照できます)。
If you need access to the data from outside the package then you can return it from a subroutine, or you can create a global variable (i.e. one which has a package prefix) which points or refers to it and return that. The pointer or reference must be global so that you can refer to it by a fully qualified name. But just like in C try to avoid having global variables. Using OO methods generally solves this problem, by providing methods to get and set the desired value within the object that can be lexically scoped inside the package and passed by reference.

あなたがパッケージの外側からそのデータにアクセスする必要がある場合あなたはサブルーチンからそれをリターンできますし, あるいはあなたはそれを指し示すか参照するグローバル変数 (i.e パッケージプレフィクスをもつもの) を作成しそれをリターンすることができます。そのポインタまたはリファレンスはグローバルでなければならないのであなたは完全修飾名によってそれを参照できます。しかし C と同じくグローバル変数をもつことを避けるようにしてください。一般的には OO (# オブジェクト指向) メソッドを使ってこの問題を解決します, パッケージ内にレキシカルスコープでリファレンスで渡せるオブジェクトの中の望みの値をゲットやセットするメソッドを提供することによってです。
The phrase "lexical variable" is a bit of a misnomer, we are really talking about "lexical symbols". The data can be referenced by a global symbol too, and in such cases when the lexical symbol goes out of scope the data will still be accessible through the global symbol. This is perfectly legitimate and cannot be compared to the terrible mistake of taking a pointer to an automatic C variable and returning it from a function--when the pointer is dereferenced there will be a segmentation fault. (Note for C/C++ programmers: having a function return a pointer to an auto variable is a disaster in C or C++; the perl equivalent, returning a reference to a lexical variable created in a function is normal and useful.)

フレーズ "レキシカル変数" は少しおかしな名前で, 私たちは実際には "レキシカルシンボル" について話をしています。データはグローバルシンボルによっても参照されることができ, そのようなケースでレキシカルシンボルはスコープの外にいってもそのデータはグローバルシンボルを通じてまだアクセスできます。これは完全に正当で C の自動的な変数 (# automatic variable) へのポインタをとってファンクションからそれをリターンするというひどい間違いと比較することはできません -- ポインタがデリファレンスされたときそこでセグメンテーション違反になります。(C/C++ プログラマのためのノート: 自動変変数へのポインタをリターンするファンクションをもつことは C や C++ においては災害です。perl と同等に, ファンクション内で作成されたレキシカル変数への参照をリターンすることはノーマルで便利です。)

  • my () vs. use vars:
    With use vars(), you are making an entry in the symbol table, and you are telling the compiler that you are going to be referencing that entry without an explicit package name.

    use vars() では, あなたはシンボルテーブルにエントリを作成して, あなたはあなたが明示的なパッケージ名を除いてそのエントリを参照するということをコンパイラに伝えます。
    With my (), NO ENTRY IS PUT IN THE SYMBOL TABLE. The compiler figures out at compile time which my () variables (i.e. lexical variables) are the same as each other, and once you hit execute time you cannot go looking those variables up in the symbol table.

    my () では, シンボルテーブルにエントリはおかれません。コンパイラはコンパイル時にどの my () 変数 (i.e. レキシカル変数) がそれぞれ同じなのかを理解して, あなたは実行時でそれらの変数をシンボルテーブルで探すことはできなくなります。

  • my () vs. local():
    local() creates a temporal-limited package-based scalar, array, hash, or glob -- when the scope of definition is exited at runtime, the previous value (if any) is restored. References to such a variable are *also* global... only the value changes. (Aside: that is what causes variable suicide. :)

    local() は一時的に限定されたパッケージベースのスカラ, 配列, ハッシュ, または glob を作成します -- 実行時に定義のスコープが終わると, 以前の値 (もしあれば) が再格納されます。そのような変数へのリファレンス *も* またグローバルで ...その値が変わるだけです。(余談: それは変数の自殺の原因です。 :)
    my () creates a lexically-limited non-package-based scalar, array, or hash -- when the scope of definition is exited at compile-time, the variable ceases to be accessible. Any references to such a variable at runtime turn into unique anonymous variables on each scope exit.

    my () はレキシカルに制限された非パッケージベースのスカラ, 配列, またはハッシュを作成します -- コンパイル時に定義のスコープが終わると, その変数はアクセス可能ではなくなります。実行時でのそのような変数へのリファレンスは各スコープの出口で無名の変数になります。




追加の参考文献 : Additional reading references



For more information see: Using global variables and sharing them between modules/packages and an article by Mark-Jason Dominus about how Perl handles variables and namespaces, and the difference between use vars() and my () - http://www.plover.com/~mjd/perl/FAQs/Namespaces.html .

詳細な情報のために参照してください: モジュール/パッケージ間のグローバル変数の利用とその共有 と どのように Perl は変数と名前空間を処理するかについての Mark-Jason Dominus による記事と, use vars() と my () の間の違いを - http://www.plover.com/~mjd/perl/FAQs/Namespaces.html 。


ネストされたサブルーチンでの my() スコープの変数 : my () Scoped Variable in Nested Subroutines



Before we proceed let's make the assumption that we want to develop the code under the strict pragma. We will use lexically scoped variables (with help of the my () operator) whenever it's possible.

私たちは前進する前に私たちがstrict プラグマのもとでコードを開発したいと仮定してみましょう。私たちは可能ならいつでもレキシカルにスコープされた変数 (my () 演算子の助けによって) を使います。


毒 : The Poison



Let's look at this code:

このコードを見てみましょう:

# nested.pl
#------------
#!/usr/bin/perl

use strict;

sub print_power_of_2 {
my $x = shift;

sub power_of_2 {
return $x ** 2;
}

my $result = power_of_2();
print "$X^2 = $resutlt\n";
}

print_power_of_2(5);
print_power_of_2(6);

Don't let the weird subroutine names fool you, the print_power_of_2() subroutine should print the square of the number passed to it. Let's run the code and see whether it works:

あなたは奇妙なサブルーチン名に惑わされてはいけません, print_power_of_2() サブルーチンはそれに渡された数の 2 乗を出力するはずです。コードを実行してこれが機能するかどうかを見てみましょう:

% ./nested.pl

5^2 = 25
6^2 = 25

Ouch, something is wrong. May be there is a bug in Perl and it doesn't work correctly with the number 6? Let's try again using 5 and 7:

アウチ, 何かが間違っています。 Perl にバグがあって数字 6 で正しく機能しないかもしれない ? 5 と 7 を使って再びトライしてみましょう:

print_power_of_2(5);
print_power_of_2(7);

And run it:

そしてこれを実行します:

% ./nested.pl

5^2 = 25
7^2 = 25

Wow, does it works only for 5? How about using 3 and 5:

ウワォ, これは 5 でだけ機能するのでしょうか ? 3 と 5 を使うのはどうでしょうか:

print_power_of_2(3);
print_power_of_2(5);

and the result is:

そしてその結果は:

% ./nested.pl

3^2 = 9
5^2 = 9

Now we start to understand--only the first call to the print_power_of_2() function works correctly. Which makes us think that our code has some kind of memory for the results of the first execution, or it ignores the arguments in subsequent executions.

私たちはだんだんわかってきました -- print_power_of_2() ファンクションを最初にコールした時にだけ正しく機能します。それは私たちのコードが最初の実行の結果のための何らかの種類の記憶をもっている, または続く実行での引数が無視されているのではないかと私たちに考えさせるものです。


診断 : The Diagnosis



Let's follow the guidelines and use the -w flag. Now execute the code:

次のガイドラインに従い -w フラグを使ってみましょう。そうしてコードを実行します:

% ./nested.pl

Variable "$x" will not stay shared at ./nested.pl line 9.
5^2 = 25
6^2 = 25

We have never seen such a warning message before and we don't quite understand what it means. The diagnostics pragma will certainly help us. Let's prepend this pragma before the strict pragma in our code:

私たちは前にこのような警告メッセージを見たことはなく私たちその意味がまったくわかりません。diagnostic プラグマは確実に私たちをヘルプします。私たちのコードで strict プラグマの前にこのプラグマを付加してみましょう:

#!/usr/bin/perl -w

use diagnostics;
use strict;

And execute it:

そしてこれを実行します:

% ./nested.pl

Variable "$x" will not stay shared at ./nested.pl line 10 (#1)
変数 "$x" は共有されたままにはなりません ./nested.pl 行 10 (#1)

(W) An inner (nested) named subroutine is referencing a lexical
variable defined in an outer subroutine.
(W) 内側の (ネストされた) 名前付きサブルーチンは外側のサブルーチンで
定義されたレキシカル変数を参照していません.

When the inner subroutine is called, it will probably see the value of
the outer subroutine's variable as it was before and during the
*first* call to the outer subroutine; in this case, after the first
call to the outer subroutine is complete, the inner and outer
subroutines will no longer share a common value for the variable. In
other words, the variable will no longer be shared.
内側のサブルーチンがコールされると, これはおそらくそれが外側の
サブルーチンへの *最初* のコールの前と最中であるかのように外側の
サブルーチンの値を見ます; この場合, 外側のサブルーチンへの最初の
コールが完了した後, 内側と外側のサブルーチンは共通の変数の値をもう
共有しなくなります。つまり, 変数はもはや共有されなくなります。

Furthermore, if the outer subroutine is anonymous and references a
lexical variable outside itself, then the outer and inner subroutines
will never share the given variable.
さらに, もし外側のサブルーチンが無名でそれ自身の外側のレキシカル変数を
参照していた場合, 外側と内側のサブルーチンは与えられた変数を決して共有
しません。

This problem can usually be solved by making the inner subroutine
anonymous, using the sub {} syntax. When inner anonymous subs that
reference variables in outer subroutines are called or referenced,
they are automatically rebound to the current values of such
variables.
この問題は sub {} シンタクスを使い, 内側のサブルーチンを無名にすることで
通常解決することができます。外側のサブルーチンの変数を参照する内側の無名の
subs がコールまたは参照されたとき, それはそのような変数の現在の値に自動的
に再バインドします。

5^2 = 25
6^2 = 25

Well, now everything is clear. We have the inner subroutine power_of_2() and the outer subroutine print_power_of_2() in our code.

さて, すべてが明確になりました。私たちは私たちのコードに内側のサブルーチン power_of_2() と外側のサブルーチン print_power_of_2() をもっています。
When the inner power_of_2() subroutine is called for the first time, it sees the value of the outer print_power_of_2() subroutine's $x variable. On subsequent calls the inner subroutine's $x variable won't be updated, no matter what new values are given to $x in the outer subroutine. There are two copies of the $x variable, no longer a single one shared by the two routines.

初回に内側の power_of_2() サブルーチンが呼ばれたとき, それは外側の print_power_of_2() サブルーチンの $x 変数の値をみます。続くコールでは外側のサブルーチンの $x に新しい変数が与えられたとしても, 内側のサブルーチンの $x 変数はアップデートされません。$x 変数の 2 つのコピーがあり, 2 つのルーチンによって共有されるひとつのものはもうありません。


治療 : The Remedy



The diagnostics pragma suggests that the problem can be solved by making the inner subroutine anonymous.

diagnostics プラグマは内側のサブルーチンを無名にすることでこの問題を解決できることを示唆しています。
An anonymous subroutine can act as a closure with respect to lexically scoped variables. Basically this means that if you define a subroutine in a particular lexical context at a particular moment, then it will run in that same context later, even if called from outside that context. The upshot of this is that when the subroutine runs, you get the same copies of the lexically scoped variables which were visible when the subroutine was defined. So you can pass arguments to a function when you define it, as well as when you invoke it.

無名サブルーチンはレキシカルにスコープされたに関するクロージャとして動くことができます。基本的にこれはあなたが特定の時点において特定のレキシカルコンテキストでサブルーチンを定義した場合に, そのコンテキストの外側からコールされたとしても, 後でそれが同じコンテキストで実行されることを意味します。これの結果はサブルーチンを実行したとき, あなたがサブルーチンが定義されたときに見えるのと同じレキシカルにスコープされた変数のコピーをゲットすることです。ですからあなたはあなたがそれを定義したとき, あなたがそれを呼びだすときもファンクションに引数を渡すことができます。
Let's rewrite the code to use this technique:

このテクニックを使うためにコードをリライトしてみましょう:

#anonumous.pl
#--------------
#!/usr/bin/perl

use strict;

sub print_power_of_2 {
my $x = shift;

my $func_ref = sub {
return $x ** 2;
};

my $result = &func_ref();
print "$x^2 = $result\n";
}

print_power_of_2(5);
print_power_of_2(6);

Now $func_ref contains a reference to an anonymous subroutine, which we later use when we need to get the power of two. Since it is anonymous, the subroutine will automatically be rebound to the new value of the outer scoped variable $x, and the results will now be as expected.

これで $func_ref は無名サブルーチンへのリファレンスを含むようになり, 私たちが 2 の累乗をゲットする必要があるときに私たちはそれを後で使います。それは無名なので, サブルーチンが自動的に外側のスコープの変数 $x の新しい値に再バインドして, 結果は期待した通りになります。
Let's verify:

検証してみましょう:

% ./anonymous.pl

5^2 = 25
6^2 = 36

So we can see that the problem is solved.

これで私たちはこの問題が解決されたことを見ることができます。


クロージャを理解する -- 簡単な方法 : Understanding Closures -- the Easy Way



In Perl, a closure is just a subroutine that refers to one or more lexical variables declared outside the subroutine itself and must therefore create a distinct clone of the environment on the way out.

Perl では, クロージャはそのサブルーチン自身の外側で宣言された 1 つ以上のレキシカル変数を参照するただのサブルーチンなので途中でその環境の明確なクローンを作成しなければなりません。
And both named subroutines and anonymous subroutines can be closures.

それから名前付きサブルーチンと無名サブルーチンは両方ともクロージャになれます (# がそれが有用とは限らない; 続きを参照)。
Here's how to tell if a subroutine is a closure or not:

こちらがサブルーチンがクロージャかそうでないかの見分け方です:

for (1..5) {
push @a, sub { "hi there" };
}
for (1..5) {
{
my $b;
push @b, sub { $b. "hi there" };
}
}
print "anon normal:\n", join "\t\n",@a,"\n";
print "anon closure:\n", join "\t\n",@b,"\n";

which generates:

それはこれを生成します:

anon normal:
CODE(0x80568e4)
CODE(0x80568e4)
CODE(0x80568e4)
CODE(0x80568e4)
CODE(0x80568e4)

anon closure:
CODE(0x804b4c0)
CODE(0x8056b54)
CODE(0x8056bb4)
CODE(0x80594d8)
CODE(0x8059538)

Note how each code reference from the non-closure is identical, but the closure form must generate distinct coderefs to point at the distinct instances of the closure.

どうして非クロージャからのコードリファレンスが同一なのに, クロージャ形式がクロージャの別のインスタンスを指し示す別のコードレフを生成することになるのかに注目してください。
And now the same with named subroutines:

そして今度は名前付きサブルーチンで同じものです:

for (1..5) {
sub a { "hi there" };
push @a, \&a;
}
for (1..5) {
{
my $b;
sub b { $b."hi there" };
push @b, \&b;
}
}
print "normal:\n", join "\t\n",@a,"\n";
print "closure:\n", join "\t\n",@b,"\n";

which generates:

それはこれを生成します:

anon normal:
CODE(0x80568c0)
CODE(0x80568c0)
CODE(0x80568c0)
CODE(0x80568c0)
CODE(0x80568c0)

anon closure:
CODE(0x8056998)
CODE(0x8056998)
CODE(0x8056998)
CODE(0x8056998)
CODE(0x8056998)

We can see that both versions has generated the same code reference. For the subroutine a it's easy, since it doesn't include any lexical variables defined outside it in the same lexical scope.

私たちは両方のバージョンが生成された同じコードリファレンスをもっていることを見ることができます。サーブルーチン a は簡単です, それは同じレキシカルスコープ内にその外側で定義されたレキシカル変数を含んでいないからです。
As for the subroutine b, it's indeed a closure, but Perl won't recompile it since it's a named subroutine (see the perlsub manpage). It's something that we don't want to happen in our code unless we want it for this special effect, similar to static variables in C.

サブルーチン b に関しては, それは確かにクロージャですが, Perl はそれが名前付きサブルーチンであるためそれを再コンパイルしません (perlsub man ページを参照してください)。これは C での静的変数と同様に, 私たちがこの特別な効果を望む場合を除いては私たちのコードで発生させたいと思わないものです。
This is the underpinnings of that famous "won't stay shared" message. A my variable in a named subroutine context is generating identical code references and therefore it ignores any future changes to the lexical variables outside of it.

これがその有名な "共有されたままにならない (# won't stay shared)" メッセージの土台です。名前付きサブルーチンコンテキストでの my 変数は同一のコードリファレンスを生成しますのでその外側でのそのレキシカル変数への将来の変更は無視されます。


Mike Guy のインナーサブルーチンの動作の説明 : Mike Guy's Explanation of the Inner Subroutine Behavior



From: mjtg@cus.cam.ac.uk (M.J.T. Guy)
Newsgroups: comp.lang.perl.misc
Subject: Re: Lexical scope and embedded subroutines.
Date: 6 Jan 1998 18:22:39 GMT
Message-ID: <68tspf$9f0$1@lyra.csx.cam.ac.uk>


In article <68sc4k$3p2$1@brokaw.wa.com>, Aaron Harsh <ajh@rtk.com> wrote:

記事 <68sc4k$3p2$1> で, Aaron Harsh は書きました:

> Before I read this thread (and perlsub to get the details) I would
> have assumed the original code was fine.
>
> This behavior brings up the following questions:
> o Is Perl's behavior some sort of speed optimization?

> 私がこのスレッド (and perlsub で詳細をゲット) を読む前
> 私はオリジナルのコードで問題ないと思っていました。
>
> この振る舞いは次の質問を引き起こします
> o Perl の振る舞いは何らかの速度最適化ですか ?
No, but see below.

いいえ, でも以下を参照してください。

> o Did the Perl gods just decide that scheme-like behavior was less
> important than the pseduo-static variables described in perlsub?

> o Perl の神々は scheme ライクな振る舞いが perlsub で説明されている疑似スタティック変数よりも
> 重要ではないと判断しただけですか ?
This subject has been kicked about at some length on perl5-porters.
The current behaviour was chosen as the best of a bad job. In the
context of Perl, it's not obvious what "scheme-like behavior" means.
So it isn't an option. See below for details.

この主題については perl5-porters で長い間反対されてきました。現在の振る舞いは悪い仕事の中でのベストとして選択されています。Perl のコンテキストでは, "scheme ライクな振る舞い" が何を意味するのか明らかではありません。ですからそれはオプションではありません。詳細は以下を参照してください。

> o Does anyone else find Perl's behavior counter-intuitive?

> o Perl の振る舞いが直感に反すると感じている人は他に誰かいますか ?
*Everyone* finds it counterintuitive. The fact that it only generates
a warning rather than a hard error is part of the Perl Gods policy of
hurling thunderbolts at those so irreverent as not to use -w.

*誰もが* これを反直感的だと思っています。ハードエラーではなくこれが watning だけを生成するという事実は-w を使わないような不遜な人々に雷を投げつける Perl の神々のポリシーの一部です。

> o Did programming in scheme destroy my ability to judge a decent
> language
> feature?

> o scheme で行ったプログラミングがまともな言語機能をジャッジする私の能力を壊したのかな ?
You're still interested in Perl, so it can't have rotted your brain completely.

あなたはまだ Perl に興味があるので, あなたの脳を完全に腐らせることにはなりません。

> o Have I misremembered how scheme handles these situations?

> o 私は scheme がこれらの状況をどのように処理するかを間違って覚えていたのかな ?
Probably not.

おそらくそうではないです。

> o Do Perl programmers really care how much Perl acts like scheme?

> o Perl が scheme のように動くことを気にする Perl プログラマーはどのくらいいますか ?
Some do.

一部です。

> o Should I have stopped this message two or three questions ago?

> o 私はこのメッセージを 2 - 3 前の質問で止めるべきでした ?
Yes.

イエス。

The problem to be solved can be stated as

解決するべきこの問題はこのように規定できます

   "When a subroutine refers to a variable which is instantiated more
   than once (i.e. the variable is declared in a for loop, or in a
   subroutine), which instance of that variable should be used?"

   "サブルーチンが複数回インスタンス化される変数を参照しているとき
   (i.e. その変数がfor ループ, あるいはサブルーチンで宣言されている),
   その変数のどのインスタンスを使うべきか ?"
The basic problem is that Perl isn't Scheme (or Pascal or any of the
other comparators that have been used).

基本的な問題は Perl が Scheme (または Pascal あるいは他のコンパレータ (# 比較器) を使うもの) ではないことです。

In almost all lexically scoped languages (i.e. those in the Algol60
tradition), named subroutines are also lexically scoped. So the scope
of the subroutine is necessarily contained in the scope of any
external variable referred to inside the subroutine. So there's an
obvious answer to the "which instance?" problem.

レキシカルスコープ化するほとんどすべての言語 (i.e. Algo60 伝統のものたち) では, 名前付きサブルーチンもレキシカルスコープ化されます。ですからサブルーチンのスコープはサブルーチンの内側で参照される外部変数のスコープに必然的に含まれます。ですから "どのインスタンス ?" 問題への明確な答えがあります。
But in Perl, named subroutines are globally scoped. (But in some
future Perl, you'll be able to write

しかし Perl では, 名前付きサブルーチンがグローバルスコープになります。 (が将来の Perl で, あなたはこう書けるようになります

my sub lex { ... }

to get lexical scoping.) So the solution adopted by other languages
can't be used.

レキシカルスコープをゲットするために。) ですから他の言語で採用されている解決策を使うことはできません。
The next suggestion most people come up with is "Why not use the most
recently instantiated variable?". This Does The Right Thing in many
cases, but fails when recursion or other complications are involved.

多くの人が思いつく次の提案は "直近でインスタンス化された変数をなぜ使わないのか ?" です。これは多くのケースで正しいことを行いますが, 再帰や他の複雑さが伴われると失敗します。
Consider:

考えてみましょう:

sub outer {
inner();
outer();
my $trouble;
inner();
sub inner { $trouble };
outer();
inner();
}

Which instance of $trouble is to be used for each call of inner()?
And why?

inner() コールのそれぞれで $trouble のどのインスタンスが使われますか ? そしてなぜ ?
The consensus was that an incomplete solution was unacceptable, so the
simple rule "Use the first instance" was adopted instead.

コンセンサスは不完全な解決策は受けいれられないなので, シンプルなルール "最初のインスタンスを使う" がかわりに採用されました。
And it is more efficient than possible alternative rules. But that's
not why it was done.

そしてそれは可能な代替のルールよりも効果的です。しかしこれはそれがなぜ行われたかではありません。

Mike Guy


インナーサブルーチンの除去ができないとき : When You Cannot Get Rid of The Inner Subroutine



First you might wonder, why in the world will someone need to define an inner subroutine? Well, for example to reduce some of Perl's script startup overhead you might decide to write a daemon that will compile the scripts and modules only once, and cache the pre-compiled code in memory. When some script is to be executed, you just tell the daemon the name of the script to run and it will do the rest and do it much faster since compilation has already taken place.

最初にあなたは不思議に思うかもしれません, なぜ世界ではインナーサブルーチンの定義を誰かが必要とするのか ? えぇ, 例えば Perl スクリプトのスタートアップオーバーヘッドの一部を減らすためにあなたはスクリプトとモジュールを 1 度だけコンパイルして, 事前コンパイルしたコードをメモリにキャッシュするデーモンを書くことを決めるかもしれません。何かのスクリプトを実行するとき, あなたはその走らせたいスクリプトの名前をデーモンに伝えるだけでそれが残りを行ってそれはすでにコンパイルされているのでより高速に行われるのです。
Seems like an easy task, and it is. The only problem is once the script is compiled, how do you execute it? Or let's put it the other way: after it was executed for the first time and it stays compiled in the daemon's memory, how do you call it again? If you could get all developers to code their scripts so each has a subroutine called run() that will actually execute the code in the script then we've solved half the problem.

簡単なタスクに見えますが, そうです。唯一の問題はスクリプトが 1 度コンパイルされたら, あなたはそれをどのようにして実行するか ? または別の言い方にすると: 初回にそれが実行されてそれがデーモンのメモリにコンパイルされたままになった後, あなたはどのようにしてそれを再びコールするのか ? もしあなたがすべての開発者にそのスクリプトをコードにしてもらいそれぞれがスクリプト内のコードを実際に実行する run() と呼ばれるサブルーチンをもってもらうようにできれば私たちは問題の半分は解決されます。
But how does the daemon know to refer to some specific script if they all run in the main:: name space? One solution might be to ask the developers to declare a package in each and every script, and for the package name to be derived from the script name. However, since there is a chance that there will be more than one script with the same name but residing in different directories, then in order to prevent namespace collisions the directory has to be a part of the package name too. And don't forget that the script may be moved from one directory to another, so you will have to make sure that the package name is corrected every time the script gets moved.

しかしそれらがすべて main:: 名前空間で実行されていた場合そのデーモンはどのようにして参照する何らか特定のスクリプトを知るのでしょうか ? 1 つの解決策はそれぞれすべてのスクリプトでパッケージを宣言して, パッケージ名をそのスクリプト名から派生させるよう開発者に依頼することかもしれません。しかし, 同じ名前だが異なるディレクトリに存在する複数のスクリプトがある可能性があるので, 名前空間の衝突を防止するためにディレクトリもパッケージ名の一部でなければなりません。そしてそのスクリプトがあるディレクトリから他のディレクトリへ移動されるかもしれないことを忘れてはいけませんので, あなたはそのパッケージ名がそのスクリプトが移動するたびに訂正されたことを確認しなければなりません。
But why enforce these strange rules on developers, when we can arrange for our daemon to do this work? For every script that the daemon is about to execute for the first time, the script should be wrapped inside the package whose name is constructed from the mangled path to the script and a subroutine called run(). For example if the daemon is about to execute the script /tmp/hello.pl:

しかし私たちが私たちのデーモンがこの作業を行うように手配できるときに, なぜ開発者にこれらの奇妙なルールを強制するのでしょうか ? デーモンが最初に実行しようとしているすべてのスクリプトのために, 名前がそのスクリプトへのマングル (# 修飾) されたパスで run() とコールされるサブルーチンから構築されたパッケージの内側でそのスクリプトはラップされなければなりません。例えばデーモンがスクリプト /tmp/hello.pl を実行しようとしている場合:

#hello.pl
#--------
#!/usr/bin/perl
print "Hello\n";

Prior to running it, the daemon will change the code to be:

これを実行する前に, デーモンはコードをこのように変更します:

#wrapped_hello.pl
#----------------
package cache::tmp::hello_2epl;

sub run{
#!/usr/bin/perl
print "Hello\n";
}

The package name is constructed from the prefix cache::, each directory separation slash is replaced with ::, and non alphanumeric characters are encoded so that for example . (a dot) becomes _2e (an underscore followed by the ASCII code for a dot in hex representation).

このパッケージ名はプレフィクス cache::, 区切りのスラッシュが :: でリプレイスされた各ディレクトリ, それと例のように . (ドット) が _2e (アンダースコアに続く 16 進数表現でのドットの ASCII コード) にエンコードされた非英数字で構築されています。

% perl -e 'printf "%x",ord(".")'

prints: 2e. The underscore is the same you see in URL encoding except the % character is used instead (%2E), but since % has a special meaning in Perl (prefix of hash variable) it couldn't be used.

主力します: 2e。アンダースコアは URL エンコーディングで % キャラクタがかわりに使われる (%2E) を除いてあなたがみるのと同じですが, Perl では % が特別な意味をもつ (ハッシュ変数のプレフィクス) のでこれは使えませんでした。
Now when the daemon is requested to execute the script /tmp/hello.pl, all it has to do is to build the package name as before based on the location of the script and call its run() subroutine:

これでデーモンがスクリプト /tmp/hello.pl の実行をリクエストされたとき, それが行うのは前のようにスクリプトの位置に基づいてパッケージ名を構築してその run() サブルーチンをコールするだけになりました。:

use cache::tmp::hello_2epl;
cache::tmp::hello_2epl::run();

We have just written a partial prototype of the daemon we wanted. The only outstanding problem is how to pass the path to the script to the daemon. This detail is left as an exercise for the reader.

私たちは私たちが必要なデーモンの部分的なプロトタイプを書きました。唯一未解決の問題はどのようにスクリプトへのパスをデーモンに渡すかです。この詳細は読者のための演習として残っています。
If you are familiar with the Apache::Registry module, you know that it works in almost the same way. It uses a different package prefix and the generic function is called handler() and not run(). The scripts to run are passed through the HTTP protocol's headers.

あなたが Apache::Registry モジュールに親しんでいるなら, あなたはそれがほとんど同じように機能することを知っているでしょう。それは異なるパッケージプレフィクスを使い汎用のファンクションは run() ではなく handler() とコールされます。実行するスクリプトは HTTP プロトコルヘッダを通じて渡されます。
Now you understand that there are cases where your normal subroutines can become inner, since if your script was a simple:

これであなたはあなたのスクリプトがシンプルな場合に, あなたのノーマルなサブルーチンがインナーになる場合があるケースがあることを理解しました:

#simple.pl
#---------
#!/usr/bin/perl
sub hello { print "Hello" }
hello();

Wrapped into a run() subroutine it becomes:

run() サブルーチンにラップされるとこのようになります:

#simple.pl
#---------
package cache::simple_2epl;

sub run{
#!/usr/bin/perl
sub hello { print "Hello" }
hello();
}

Therefore, hello() is an inner subroutine and if you have used my () scoped variables defined and altered outside and used inside hello(), it won't work as you expect starting from the second call, as was explained in the previous section.

したがって, hello() はインナーサブルーチンでもしあなたが外側で定義し変更され hello() の内側で使われる my() を使ってスコープされた変数をもっている場合, それは前のセクションで説明した通り, 2 番目のコールからあなたの期待したようには機能しません。


インナーサブルーチンの救済策 : Remedies for Inner Subroutines



First of all there is nothing to worry about, as long as you don't forget to turn the warnings On. If you do happen to have the "my () Scoped Variable in Nested Subroutines" problem, Perl will always alert you.

まず最初にあなたが warnings を On にすることを忘れない限り, 心配することはありません。あなたが "my () Scoped Variable in Nested Subroutines 問題をもったら, Perl は常にあなたにアラートします。
Given that you have a script that has this problem, what are the ways to solve it? There have been many suggested in the past, and we discuss some of them here.

あなたがこの問題をもつスクリプトをもっているとしたら, それを解決するための方法は何ですか ? 過去に多くの提案がありましたが, 私たちはここでそのいくつかを論じます。
We will use the following code to show the different solutions.

私たちは異なる解決策を示すために次のコードを使います。

#multirun.pl
#-----------
#!/usr/bin/perl

use strict;
use warnings;

for (1..3) {
print "run: [time $_]\n";
run();
}

sub run{

my $counter = 0;

increment_counter();
increment_counter();

sub increment_counter{
$counter++:
print "Counter is equal to $counter !\n";
}
} # end of sub run

This code executes the run() subroutine three times, which in turn initializes the $counter variable to 0, every time it is executed and then calls the inner subroutine increment_counter() twice. Sub increment_counter() prints $counter's value after incrementing it. One might expect to see the following output:

このコードは run() サブルーチンを 3 回実行し, それが実行されるたびに, $counter 変数は 0 に初期化されてインナーサブルーチン increment_counter() を 2 回コールします。サブルーチン increment_counter() はインクリメントした後で $counter の値を出力します。次のような出力をみることが期待されるかもしれません:

run: [time 1]
Counter is equal to 1 !
Counter is equal to 2 !
run: [time 2]
Counter is equal to 1 !
Counter is equal to 2 !
run: [time 3]
Counter is equal to 1 !
Counter is equal to 2 !

But as we have already learned from the previous sections, this is not what we are going to see. Indeed, when we run the script we see:

しかし私たちが前のセクションですでに学んだように, これは私たちが見たいものにはなりません。実際に, 私たちがこのスクリプトを実行すると私たちはこれをみます:

% ./multirun.pl

Variable "$counter" will not stay shared at ./nested.pl line 18.
run: [time 1]
Counter is equal to 1 !
Counter is equal to 2 !
run: [time 2]
Counter is equal to 3 !
Counter is equal to 4 !
run: [time 3]
Counter is equal to 5 !
Counter is equal to 6 !

Apparently, the $counter variable is not reinitialized on each execution of run(), it retains its value from the previous execution, and increment_counter() increments that. Actually that is not quite what happens. On each execution of run() a new $counter variable is initialized to zero but increment_counter() remains bound to the $counter variable from the first call to run().

見たところ, $counter 変数は run() の各実行で再初期化されず, 前の実行からの値を保っていて, increment_counter() がそれをインクリメントしているようです。実際にはそれが起こったことのすべてではありません。run() の各実行で $counter 変数はゼロに初期化されますが increment_counter() は依然として最初の run() へのコールからの $counter 変数にバインドされたままです。
The simplest of the work-rounds is to use package-scoped variables. These can be declared using our or, on older versions of Perl, the vars pragma. Note that whereas using my declaration also implicitly initializes variables to undefined the our declaration does not, and so you will probably need to add explicit initialisation for variables that lacked it.

もっともシンプルな回避策はパッケージスコープの変数を使うことです。これらは our や, Perl の古いバージョンでは, vars プラグマを使って宣言できます。my を使った宣言は暗黙的に変数を未定義に初期化する一方で our 宣言はそうではありません (# 未定義にはならない) ので, あなたはおそらくそれを欠いたその変数のために明示的な初期化を追加する必要があることに注意してください。

#multirun1.pl
#------------
#!/usr/bin/perl

use strict;
use warnings;

for (1..3) {
print "run: [time $_]\n";
runt();
}

sub run {

our $counter = 0;

increment_counter();
increment_counter();

sub increment_counter{
$counter++;
print "Counter is equal to $counter !\n";
}
} # end of sub run

If you run this and the other solutions offered below, the expected output will be generated:

あなたがこれと以下で提供された他の解決策を実行すると, 期待される出力が生成されます:

% ./multirun1.pl

run: [time 1]
Counter is equal to 1 !
Counter is equal to 2 !
run: [time 2]
Counter is equal to 1 !
Counter is equal to 2 !
run: [time 3]
Counter is equal to 1 !
Counter is equal to 2 !

By the way, the warning we saw before has gone, and so has the problem, since there is no my () (lexically defined) variable used in the nested subroutine.

ちなみに, ネストされたサブルーチンで使われていた my () (レキシカル宣言した) 変数がないので, 私たちが前にみた warning はどこかへ行きました, もっていた問題も。
In the above example we know $counter is just a simple small scalar. In the general case variables could reference external resource handles or large data structures. In that situation the fact that the variable would not be released immediately when run() completes could be a problem. To avoid this you can put local in front of the our declaration of all variables other than simple scalars. This has the effect of restoring the variable to its previous value (usually undefined) upon exit from the current scope. As a side-effect local also initializes the variables to undef. So, if you recall that thing I said about adding explicit initialization when you replace my by our, well, you can forget it again if you replace my with local our.

上記の例で私たちは $counter がただのシンプルで小さいスカラだとしっています。一般的なケースでは変数は外部のリソースのハンドルや大きなデータ構造を参照することができます。そのような状況ではその変数が run() が完了した時すぐにリリースされない事実が問題になるかもしれません。これを回避するためにあなたはシンプルなスカラ以外にもすべての変数の our 宣言の前に local をおくことができます。これは現在のスコープからでる際に変数をその前の値 (通常は未定義) にリストアする効果をもちます。副作用として local は変数を undef に初期化します。ですから, あなたが my を our でリプレイスするときに明示的な初期化を追加することについて私が言ったことをあなたが思い出すなら, えぇ, あなたが local our で my をリプレイスするならあなたはそれを再び忘れることができます。
Be warned that local will not release circular data structures. If the original CGI script relied upon process termination to clean up after it then it will leak memory as a registry script.

local が循環データ構造をリリースしないことを注意してください。オリジナルの CGI スクリプトがその後のクリーンアップのためにプロセスの終了に依存している場合レジストリスクリプトとしてメモリをリークします。
A varient of the package variable approach is not to declare your variables, but instead to use explicit package qualifiers. This has the advantage on old versions of Perl that there is no need to load the vars module, but it adds a significant typing overhead. Another downside is that you become dependant on the "used only once" warning to detect typos in variable names. The explicit package name approach is not really suitable for registry scripts because it pollutes the main:: namespace rather than staying properly within the namespace that has been allocated. Finally, note that the overhead of loading the vars module only has to be paid once per Perl interpreter.

パッケージ変数のアプローチのバリエーションはあなたの変数を宣言するのではなく, かわりにパッケージ修飾子を使います。これは Perl の古いバージョンで vars モジュールのロードを必要としないアドバンテージをもちますが, それは著しいタイピングのオーバーヘッドを追加します。他の欠点は変数名のタイポ (# タイプミス) を検出するために "used only once (1 度のみ使われた)" warning にあなたが依存するようになることです。明示的なパッケージ名のアプローチはそれが割当てられたその名前空間に適切にとどまるのではなく main:: 名前空間をよごすのでレジストリスクリプトにはあまり適していません。最後に, vars モジュールをロードするオーバヘッドは Perl インタプリタ毎に 1 度支払わなければならないことに注意してください。

#multirun2.pl
#------------
#!/usr/bin/perl -w

use strict;

for (1..3) {
print "run: [time $_]\n";
runt();
}

sub run {

$main::counter = 0;

increment_counter();
increment_counter();

sub increment_counter{
$main::counter++;
print "Counter is equal to $main::counter !\n";
}

} # end of sub run

You can also pass the variable to the subroutine by value and make the subroutine return it after it was updated. This adds time and memory overheads, so it may not be good idea if the variable can be very large, or if speed of execution is an issue.

あなたはサブルーチンに値で変数を渡してそれがアップデートされた後にサブルーチンがそれをリターンするようにができます。これは時間とメモリのオーバヘッドを追加しますので, 変数がとても大きくなったり, 実行速度が課題である場合はあまり良いアイデアではないかもしれません。
Don't rely on the fact that the variable is small during the development of the application, it can grow quite big in situations you don't expect. For example, a very simple HTML form text entry field can return a few megabytes of data if one of your users is bored and wants to test how good your code is. It's not uncommon to see users copy-and-paste 10Mb core dump files into a form's text fields and then submit it for your script to process.

アプリケーションの開発の間に変数が小さいという事実に依存しないで下さい, それはあなたが予期しない状況でかなり大きくなることができます。例えば, とてもシンプルな HTML フォームのテキストエントリフィールドはあなたのユーザの 1 人が退屈でありあなたのコードがどれだけ良いかをテストしようとした場合に数メガバイトのデータをリターンすることができます。ユーザの 10Mb のコアダンプファイルをフォームのテキストフィールドにコピーアンドペーストしあなたのスクリプトが処理するようにそれを投稿することは珍しい事ではありません。

#multirun3.pl
#------------
#!/usr/bin/perl

use strict;
use warnings;

for (1..3) {
print "run: [time $_]\n";
run();
}

sub run {

my $counter = 0;

$counter = increment_counter($counter);
$counter = increment_counter($counter);

sub increment_counter{
my $counter = shift;

$counter++;
print "Counter is equal to $counter !\n";

return $counter;
}

} # end of sub run

Finally, you can use references to do the job. The version of increment_counter() below accepts a reference to the $counter variable and increments its value after first dereferencing it. When you use a reference, the variable you use inside the function is physically the same bit of memory as the one outside the function. This technique is often used to enable a called function to modify variables in a calling function.

最後に, あなたはこのジョブを行うためにリファレンスを使うことができます。以下の increment_counter() のバージョンは $counter 変数へのリファレンスを受けいれてその最初のデリファレンスの後にその値をインクリメントします。あなたがリファレンスを使うとき, ファンクションの内側であなたが使うその変数はファンクションの外側のものと物理的に同じメモリのビットです。このテクニックはコールされたファンクションでコールしたファンクションの変数を編集できるようにするためによく使われます。

#multirun4.pl
#------------
#!/usr/bin/perl

use strict;
use warnings;

for (1..3) {
print "run: [time $_]\n";
run();
}

sub run {

my $counter = 0;

increment_counter(\$counter);
increment_counter(\$counter);

sub increment_counter{
my $r_counter = shift;

$$r_counter++;
print "Counter is equal to $$r_counter !\n";
}

} # end of sub run

Here is yet another and more obscure reference usage. We modify the value of $counter inside the subroutine by using the fact that variables in @_ are aliases for the actual scalar parameters. Thus if you called a function with two arguments, those would be stored in $_[0] and $_[1]. In particular, if an element $_[0] is updated, the corresponding argument is updated (or an error occurs if it is not updatable as would be the case of calling the function with a literal, e.g. increment_counter(5)).

こちらはまた別のより曖昧なリファレンスの使用法です。私たちは @_ の変数が実際のスカラパラメータのエイリアスという事実を使ってサブルーチンの内側で $counter の値を修正します。ですからあなたが 2 つの引数でファンクションをコールすると, それらは $_[0] と $_[1] に格納されます。具体的には, エレメント $_[0] がアップデートされると, 対応する引数がアップデートされます (またはリテラルでファンクションがコールされたケースのようにそれがアップデートできない場合はエラーが発生します, e.g. increment_counter(5))。

#multirun5.pl
#------------
#!/usr/bin/perl

use strict;
use warnings;

for (1..3){
print "run: [time $_]\n";
run();
}

sub run {

my $counter = 0;

increment_counter($counter);
increment_counter($counter);

sub increment_counter{
$_[0]++;
print "Counter is equal to $_[0] !\n";
}

} # end of sub run

The approach given above should be properly documented of course.

上記のアプローチはもちろん適切にドキュメント化されるはずです。
Here is a solution that avoids the problem entirely by splitting the code into two files; the first is really just a wrapper and loader, the second file contains the heart of the code. This second file must go into a directory in your @INC. Some people like to put the library in the same directory as the script but this assumes that the current working directory will be equal to the directory where the script is located and also that @INC will contain '.', neither of which are assumptions you should expect to hold in all cases.

こちらはコードを 2 つのファイルに分割することで問題を完全に回避する解決策です; 最初のものは実際は単なるラッパーとローダで, 2 番目のファイルがコードのハートを含みます。この 2 番目のファイルはあなたの @INC ディレクトリに行かなければなりません。一部の人はスクリプトと同じディレクトリにライブラリを置くことを好みますがこれは現在のワーキングディレクトリがスクリプトがロードされるディレクトリとイコールでありその @INC が "." を含むことを想定しいて, そのどちらともにあなたがすべてのケースで保持されていることを期待すべき前提ではありません。
Note that the name chosen for the library must be unique throughout the entire server and indeed every server on which you many ever install the script. This solution is probably more trouble than it is worth - it is only oncluded because it was mentioned in previous versions of this guide.

ライブラリの名前選択はサーバ全体と実際にあなたがそのスクリプトをインストールするだろうすべてのサーバでユニークでなければならないことに注意して下さい。この解決策はおそらくその価値よりも厄介です - それはこのガイドの前のバージョンで言及されていて結論づいています。

#multirun6.pl
#------------
#!/usr/bin/perl

use strict;
use warnings;

require 'multirun6-lib.pl';

for (1..3) {
print "run: [time $_]\n";
run();
}

Separete file:

分割ファイル:

#multirun6-lib.pl
#----------------
use strict;
use warnings;

my $counter;

sub run {
$counter = 0;

increment_counter();
increment_counter();
}

sub increment_counter{
$counter++;
print "Counter is equal to $counter !\n";
}

1;

An alternative verion of the above, that mitigates some of the disadvantages, is to use a Perl5-style Exporter module rather than a Perl4-style library. The global uniqueness requirement still applies to the module name, but at least this is a problem Perl programmers should already be familiar with when creating modules.

いくつかのディスアドバンテージを緩和する, 上記の代替バージョンは, Perl4 スタイルのライブラリではなく Perl5 スタイルの Exporter モジュールを使うことでです。モジュール名にグローバルなユニーク性の要件はまだ適用されますが, 少なくともこれは Perl プログラマがモジュールを作成するときにすでに馴染んでいる問題です。

#multirun7.pl
#------------
#!/usr/bin/perl

use strict;
use warnings;
use My::Multirun7;

for (1..3) {
print "run: [time $_]\n";
run();
}

Separate file:

分割ファイル:

#My/Multirun7.pm
#---------------
package My::Multirun7;
use strict;
use warnings;
use base qw( Exporter );
our @EXPORT = qw( run );

my $counter;

sub run {
$counter = 0;

increment_counter();
increment_counter();
}

sub increment_counter{
$counter++;
print "Counter is equal to $counter !\n";
}

1;

Now you have at least five workarounds to choose from (not counting numbers 2 and 6).

これであなたは少なくとも選択可能な 5 つの回避策をもちました (ナンバー 2 と 6 は数えません)。
For more information please refer to perlref and perlsub manpages.

詳細な情報のために perlref と perlsub man ページを参照するようにしてください。


use(), require(), do(), %INC and @INC Explained




@INC 配列 : The @INC array



@INC is a special Perl variable which is the equivalent of the shell's PATH variable. Whereas PATH contains a list of directories to search for executables, @INC contains a list of directories from which Perl modules and libraries can be loaded.

@INC は特別な Perl 変数でそれはシェルの PATH 変数と同等のものです。PAHT が実行可能なものをサーチするためのディレクトリリストを含むのにたいして, @INC は Perl モジュールとライブラリをロードできるディレクトリリストを含んでいます。
When you use(), require() or do() a filename or a module, Perl gets a list of directories from the @INC variable and searches them for the file it was requested to load. If the file that you want to load is not located in one of the listed directories, you have to tell Perl where to find the file. You can either provide a path relative to one of the directories in @INC, or you can provide the full path to the file.

あなたがファイル名やモジュールに use(), require(), do() をしたとき, Perl は @INC からディレクトリリストをゲットしてロードがリクエストされたファイルのためにそれらをサーチします。あなたがロードしたいファイルがリストされたディレクトリに配置されていない場合, あなたはどこでそのファイルが見つかるかを Perl に伝えなければなりません。あなたは @INC のディレクトリへの相対パスを提供するか, ファイルへのフルパスを提供するのいずれかを行えます。


%INC ハッシュ : The %INC hash



%INC is another special Perl variable that is used to cache the names of the files and the modules that were successfully loaded and compiled by use(), require() or do() statements. Before attempting to load a file or a module with use() or require(), Perl checks whether it's already in the %INC hash. If it's there, the loading and therefore the compilation are not performed at all. Otherwise the file is loaded into memory and an attempt is made to compile it. do() does unconditional loading--no lookup in the %INC hash is made.

%INC はまた別の特別な Perl 変数で use(), require() または do() ステートメントでロードとコンパイルに成功したファイルとモジュールの名前のキャッシュに使われます。use() または require() で前にロードを試みたファイルやモジュールは, それがすでに %INC ハッシュにあるかどうかを Perl はチェックします。もしそれがあれば, それをロードするのでコンパイルはまったく実行されません。そうでなければファイルはメモリにロードされてそれをコンパイルすることを試みます。do() は無条件にロードを行います -- %INC ハッシュのルックアップは行われません。
If the file is successfully loaded and compiled, a new key-value pair is added to %INC. The key is the name of the file or module as it was passed to the one of the three functions we have just mentioned, and if it was found in any of the @INC directories except "." the value is the full path to it in the file system.

ファイルが正常にロードされコンパイルされると, 新しいキー - バリューペアが %INC に追加されます。キーは私たちがさきほど言及した 3 つのファンクションの 1 つに渡されたファイルやモジュールの名前で, それが "." 以外の @INC ディレクトリのいずれかで見つかった場合その値はそのファイルシステムでそれへのフルパスです。
The following examples will make it easier to understand the logic.

次の例はこのロジックを簡単に理解できるようにします。
First, let's see what are the contents of @INC on my system:

最初に, 私のシステムで @INC のコンテンツが何かを見てみましょう:

% perl -e 'print join "\n", @INC'
/usr/lib/perl5/5.00503/i386-linux
/usr/lib/perl5/5.00503
/usr/lib/perl5/site_perl/5.005/i386-linux
/usr/lib/perl5/site_perl/5.005
.

Notice the . (current directory) is the last directory in the list.

. (カレントディレクトリ) がリストの最後のディレクトリであることに注意してください。
Now let's load the module strict.pm and see the contents of %INC:

では strict.pm をロードして %INC の内容を見てみましょう:

% perl -e 'use strict; print map {"$_ => $INC{$_}\n"} keys %INC'

strict.pm => /usr/lib/perl5/5.00503/strict.pm

Since strict.pm was found in /usr/lib/perl5/5.00503/ directory and /usr/lib/perl5/5.00503/ is a part of @INC, %INC includes the full path as the value for the key strict.pm.

strict.pm が /usr/lib/perl5/5.00503 ディレクトリでみつかり, /usr/lib/perl5/5.00503 が @INC の一部なので, %INC はキー strict.pm の値としてそのフルパスを含んでいます。
Now let's create the simplest module in /tmp/test.pm:

では /tmp/test.pm で最もシンプルなモジュールを作成してみましょう:

test.pm
-------
1;

It does nothing, but returns a true value when loaded. Now let's load it in different ways:

これは何もしませんが, ロードされた時に true をリターンします。ではこれをさまざまなやり方でロードしてみましょう:

% cd /tmp
% perl -e 'use test; print map {"$_ => $INC{$_}\n"} keys %INC'

test.pm => test.pm

Since the file was found relative to . (the current directory), the relative path is inserted as the value. If we alter @INC, by adding /tmp to the end:

ファイルが . (現在のディレクトリ) に関連して見つかったので, 相対パスが値として挿入されます。その末尾に /tmp を追加することで, 私たちが @INC を変更する場合:

% cd /tmp
% perl -e 'BEGIN{push @INC, "/tmp"} use test; \
print map {"$_ => $INC{$_}\n"} keys %INC'

test.pm => test.pm

Here we still get the relative path, since the module was found first relative to ".". The directory /tmp was placed after . in the list. If we execute the same code from a different directory, the "." directory won't match,

ここで私たちはまだ相対パスをゲットしています, モジュールが "." に関連して最初に見つかったためです。(# @INC の中で) ディレクトリ /tmp はリストの中で (# push によって) . の後に配置されています。私たちが異なるディレクトリで同じコードを実行すると, "." ディレクトリはマッチしません,

% cd /
% perl -e 'BEGIN{push @INC, "/tmp"} use test; \
print map {"$_ => $INC{$_}\n"} keys %INC'

test.pm => /tmp/test.pm

so we get the full path. We can also prepend the path with unshift(), so it will be used for matching before "." and therefore we will get the full path as well:

ですから私たちはフルパスをゲットします。私たちは unshift() でパスの前につけることもできて, それを "." の前にマッチングさせるために使うことができるので私たちはフルパスもゲットできます:

% cd /tmp
% perl -e 'BEGIN{unshift @INC, "/tmp"} use test; \
print map {"$_ => $INC{$_}\n"} keys %INC'

test.pm => /tmp/test.pm

The code:

このコードは:

BEGIN{unshift @INC, "/tmp"}

can be replaced with the more elegant:

よりエレガントにリプレイスできます:

use lib "/tmp";

Which is almost equivalent to our BEGIN block and is the recommended approach.

これは私たちの BEGIN ブロックとほとんど同等で推奨されるアプローチです。
These approaches to modifying @INC can be labor intensive, since if you want to move the script around in the file-system you have to modify the path. This can be painful, for example, when you move your scripts from development to a production server.

@INC を修正するこれらのアプローチはかなり面倒な仕事になります, あなたがスクリプトをファイルシステム内で移動したい場合にはあなたはパスを修正しなければならないからです。これは痛みをともなうことになります, 例えば, あなたがあなのスクリプトを開発からプロダクションサーバに移動するときにです。
There is a module called FindBin which solves this problem in the plain Perl world, but unfortunately up untill perl 5.9.1 it won't work under mod_perl, since it's a module and as any module it's loaded only once. So the first script using it will have all the settings correct, but the rest of the scripts will not if located in a different directory from the first. Perl 5.9.1 provides a new function FindBin::again which will do the right thing. Also the CPAN module FindBin::Real provides a working alternative working under mod_perl.

プレーンな Perl の世界にはこの問題を解決する FindBin と呼ばれるモジュールがありますが, それは残念ながら perl 5.9.1 まで mod_perl のもとでは機能しません, それがモジュールであり他のモジュールと同じく 1 度だけロードされるからです。ですからそれを使った最初のスクリプトはすべてが正しいセッティングをもちますが, それ以降のスクリプトが最初とは違うディレクトリに配置されていたらそうではなくなります。Perl 5.9.1 は正しいことを行う新しいファンクション FindBin::again を提供しています。また CPAN モジュール FindBin::Real も mod_perl のもとで動く代替の機能を提供します。
For the sake of completeness, I'll present the FindBin module anyway.

万全を期すために, なんにせよ私は FindBin を紹介します。
If you use this module, you don't need to write a hard coded path. The following snippet does all the work for you (the file is /tmp/load.pl):

あなたこのモジュールを使うなら, あなたはハードコードのパスを書く必要はありません。次のスニペットはあなたのためにすべての作業を行います (ファイルは /tmp/load.pl):

#load.pl
#-------
#!/usr/bin/perl

use FindBin ();
use lib "$FindBin::Bin";
use test;
print "test.pm => $INC{'test.pm'}\n";

In the above example $FindBin::Bin is equal to /tmp. If we move the script somewhere else... e.g. /tmp/new_dir in the code above $FindBin::Bin equals /tmp/new_dir.

上の例で $FindBin::Bin は /tmp と同等です。私たちがスクリプトをどこかへ移動すると... e.g. /tmp/new_dir 上のコードで $FindBin::Bin は /tmp/new_dir と同等です。

% /tmp/load.pl

test.pm => /tmp/test.pm

This is just like use lib except that no hard coded path is required.

これはハードコードのパスが要求されることを除いて use lib と同様です。
You can use this workaround to make it work under mod_perl.

あなたは mod_perl のもとでそれを機能させるためにこの回避策を使うことができます。

do 'FindBin.pm';
unshift @INC, "$FindBin::Bin";
require test;
#maybe test::import( ... ) here if need to import stuff
#インポートが必要なものがあるならおそらくここで test::import( ... )

This has a slight overhead because it will load from disk and recompile the FindBin module on each request. So it may not be worth it.

各リクエストで FindBin モジュールをディスクからロードして再コンパイルするためこれはわずかなオーバヘッドをもっています。ですからこれは価値がないかもしれません。


モジュール, ライブラリそれからプログラムファイル : Modules, Libraries and Program Files



Before we proceed, let's define what we mean by module, library and program file.

私たちが先に進む前に, 私たちが意味するモジュール, ライブラリそれからプログラムファイルが何かを定義しましょう。


  • ライブラリ : Libraries
    These are files which contain Perl subroutines and other code.

    これらは Perl サブルーチンやその他のコードを含むファイルです。
    When these are used to break up a large program into manageable chunks they don't generally include a package declaration; when they are used as subroutine libraries they often do have a package declaration.

    大きなプログラムを管理できるチャンクに分割するためにこれらが使われるときそれらは通常 package 宣言を含みません; それらがサブルーチンライブラリとして使われるときはしばしば package 宣言をもちます。
    Their last statement returns true, a simple 1; statement ensures that.

    それらの最後のステートメントは true をリターンします, シンプルな 1; ステートメントがそれを保証します。
    They can be named in any way desired, but generally their extension is .pl.

    それらはいかようにも望ましい名前付けができますが, 通常それらの拡張子は .pl です。
    Examples:

    例:

    #config.pl
    #----------
    # No package so default to main::
    # パッケージではないのでデフォルトで main::
    $dir = "/home/httpd/cgi-bin";
    $cgi = "/cgi-bin";
    1;

    #mysubs.pl
    #----------
    # No package so defaults to main::
    # パッケージではないのでデフォルトで main::
    sub print_header{
    print "Content-type: text/plain\r\n\r\n";
    }
    1;

    #web.pl
    #-----------
    package web ;
    # Call like this: web::print_with_class('loud',"Don't shout!");
    # これをこのようにコールします: web::print_with_class('loud',"Don't shout!");
    sub print_with_class{
    my ( $class, $text ) = @_;
    print qq{<span class="$class">$text</span>};
    }
    1;



  • モジュール : Modules
    A file which contains perl subroutines and other code.

    perl サブルーチンとその他のコードを含むファイルです。
    It generally declares a package name at the beginning of it.

    これは通常その先頭でパッケージ名を宣言します。
    Modules are generally used either as function libraries (which .pl files are still but less commonly used for), or as object libraries where a module is used to define a class and its methods.

    モジュールは通常ファンクションライブラリ (.pl ファイルはまだありますが一般的にはあまり使われていません) として, またはモジュールがクラスとメソッドを定義するために使われるオブジェクトライブラリとしてのいずれかで使われます。
    Its last statement returns true.

    そのサイトのステートメントは true をリターンします。
    The naming convention requires it to have a .pm extension.

    その命名規則は .pm 拡張子をもっていることを必要とします。
    Example:

    例:

    MyModule.pm
    -----------
    package My::Module;
    $My::Module::VERSION = 0.01;

    sub new{ return bless {}, shift;}
    END { print "Quitting\n"}
    1;



  • プログラムファイル : Program Files
    Many Perl programs exist as a single file. Under Linux and other Unix-like operating systems the file often has no suffix since the operating system can determine that it is a perl script from the first line (shebang line) or if it's Apache that executes the code, there is a variety of ways to tell how and when the file should be executed. Under Windows a suffix is normally used, for example .pl or .plx.

    多くのプログラムは単一のファイルとして存在します。Linux や他の Unix ライクのオペレーティングシステムのもとではオペレーティングシステムが最初の行 (シェバン行) からそれが perl スクリプトであることを判断できますしもしそれが Apache が実行するコードなら, いつどのようにそのファイルを実行しなければならないかを伝えるためのさまざまな方法があるのでファイルはしばしばサフィックス (# 接尾辞) をもっていません。Windows のもとではサフィックスが普通に使われます, 例えば .pl や .plx です。
    The program file will normally require() any libraries and use() any modules it requires for execution.

    プログラムファイルは普通実行に必要なライブラリを require() モジュールを use() します。
    It will contain Perl code but won't usually have any package names.

    これは Perl コードを含みますが通常はパッケージ名をもちません。
    Its last statement may return anything or nothing.

    その最後のステートメントは何かをリターンするかもしれませんし何もしないかもしれません。




require()



require() reads a file containing Perl code and compiles it. Before attempting to load the file it looks up the argument in %INC to see whether it has already been loaded. If it has, require() just returns without doing a thing. Otherwise an attempt will be made to load and compile the file.

require() は Perl コードを含んでいるファイルを読んでそれをコンパイルします。これはファイルのロードを試みる前に %INC でその引数を探してそれがすでにロードされているかどうかを見ます。それがあれば, require() は何かを行うことなくリターンするだけです。そうでなければファイルのロードとコンパイルすることを試みます。
require() has to find the file it has to load. If the argument is a full path to the file, it just tries to read it. For example:

require() はロードしなければならないファイルを見つけなければなりません。その引数がファイルへのフルパスの場合, 単にそれを読むことをトライします。例えば:

require "/home/httpd/perl/mylibs.pl";

If the path is relative, require() will attempt to search for the file in all the directories listed in @INC. For example:

もしパスが相対なら, require() は @INC にリストされたすべてのディレクトリでファイルのサーチを試みます。例えば:

require "mylibs.pl";

If there is more than one occurrence of the file with the same name in the directories listed in @INC the first occurrence will be used.

@INC でリストされたディレクトリで 1 つ以上の同じ名前のファイルがあった場合は最初にあったものが使われます。
The file must return TRUE as the last statement to indicate successful execution of any initialization code. Since you never know what changes the file will go through in the future, you cannot be sure that the last statement will always return TRUE. That's why the suggestion is to put "1;" at the end of file.

ファイルは初期化コードの実行が成功したことを示すために最後のステートメントとして TRUE をリターンしなければなりません。あなたはそのファイルが将来にわたって何が変更されるかを知ることができないので, あなたはその最後のステートメントが常に TRUE をリターンすることを確認できません。だからこそファイルの最後には 1; をおくことを推奨します。
Although you should use the real filename for most files, if the file is a module, you may use the following convention instead:

あなたはほとんどのファイルでリアルのファイル名を使うはずですが, ファイルがモジュールの場合, あなたはかわりに次の規則を使うこともできます:

require My::Module;

This is equal to:

これはこれとイコールです:

require "My/Module.pm";

If require() fails to load the file, either because it couldn't find the file in question or the code failed to compile, or it didn't return TRUE, then the program would die(). To prevent this the require() statement can be enclosed into an eval() exception-handling block, as in this example:

対象のファイルが見つからないまたはコードのコンパイルが失敗した, あるいは TRUE がリターンされないのいずれかの理由で, require() がファイルのロードに失敗した場合, プログラムは die() します。これを防止するために require() ステートメントを eval() 例外処理ブロックに囲いこむことができます, この例のように:

#require.pl
#----------
#!/usr/bin/perl -w

eval { require "/file/that/does/not/exists"};
if ($@) {
print "Failed to load, because : $@"
}
print "\nHello\n";

When we execute the program:

私たちがこのプログラムを実行すると:

% ./require.pl

Failed to load, because : Can't locate /file/that/does/not/exists in
@INC (@INC contains: /usr/lib/perl5/5.00503/i386-linux
/usr/lib/perl5/5.00503 /usr/lib/perl5/site_perl/5.005/i386-linux
/usr/lib/perl5/site_perl/5.005 .) at require.pl line 3.

Hello

We see that the program didn't die(), because Hello was printed. This trick is useful when you want to check whether a user has some module installed, but if she hasn't it's not critical, perhaps the program can run without this module with reduced functionality.

私たちはこのプログラムが die() しなかったことを見ます, Helo が出力されているからです。このトリックはユーザがインストールされたモジュールをもっているかどうかをあなたがチェックしたいときに役立ちますが, もし彼女がそれをもっていないのは重要ではなく, プログラムはこのモジュールなしで機能を減らして実行できるはずです。
If we remove the eval() part and try again:

私たちが eval() パートを削除してこれを再びトライすると:

#require.pl
#----------
#!/usr/bin/perl -w

require "/file/that/does/not/exists";
print "\nHello\n";


% ./require1.pl

Can't locate /file/that/does/not/exists in @INC (@INC contains:
/usr/lib/perl5/5.00503/i386-linux /usr/lib/perl5/5.00503
/usr/lib/perl5/site_perl/5.005/i386-linux
/usr/lib/perl5/site_perl/5.005 .) at require1.pl line 3.

The program just die()s in the last example, which is what you want in most cases.

最後の例のこのプログラムは die() するだけです, それはあなたが多くのケースで望むものです。
For more information refer to the perlfunc manpage.

詳細は perlfunc man ページを参照してください。


use()



use(), just like require(), loads and compiles files containing Perl code, but it works with modules only and is executed at compile time.

use() は, require() と同じく, Perl コードを含んでいるファイルをロードしてコンパイルしますが, これはモジュールでのみ機能しコンパイルタイムで実行されます。
The only way to pass a module to load is by its module name and not its filename. If the module is located in MyCode.pm, the correct way to use() it is:

モジュールを渡してロードするための唯一の方法はそのファイル名でなくモジュール名によるものです。モジュールが MyCode.pm で配置されているなら, それを use() する正しい方法はこれです:

use MyCode

and not:

そしてこれではありません:

use "MyCode.pm"

use() translates the passed argument into a file name replacing :: with the operating system's path separator (normally /) and appending .pm at the end. So My::Module becomes My/Module.pm.

use() はオペレーティングシステムのパスセパレータ (普通は /) を :: でリプレイスしその末尾に .pm を追加して渡された引数をファイル名に変換します。ですから My::Module は My/Module.pm になります。
use() is exactly equivalent to:

use() はこれとまったく同等です:

BEGIN { require Module; Module->import(LIST); }

Internally it calls require() to do the loading and compilation chores. When require() finishes its job, import() is called unless () is the second argument. The following pairs are equivalent:

内部的にこれはロードとコンパイルの雑用をするために require() をコールします。require() のジョブがフィニッシュするとき, () が 2 番目の引数でない限りは import() がコールされます。次のペアは同等です:

use MyModule;
BEGIN {require MyModule; MyModule->import; }

use MyModule qw(foo bar);
BEGIN {require MyModule; MyModule->import("foo","bar"); }

use MyModule ();
BEGIN {require MyModule; }

The first pair exports the default tags. This happens if the module sets @EXPORT to a list of tags to be exported by default. The module's manpage normally describes what tags are exported by default.

最初のペアはデフォルトのタグをエクスポートします。これはモジュールがタグのリストをデフォルトでエクスポートするために @EXPORT をセットしている場合に発生します。モジュールの man ページはデフォルトで何のタグがエクスポートされるかを普通説明しています。
The second pair exports only the tags passed as arguments.

2 番目のペアは引数として渡されたタグのみをエクスポートします。
The third pair describes the case where the caller does not want any symbols to be imported.

3 番目のペアはコーラー (# 呼び出し元) がシンボルのインポートを望まない場合を説明するケースです。
import() is not a builtin function, it's just an ordinary static method call into the "MyModule" package to tell the module to import the list of features back into the current package. See the Exporter manpage for more information.

import() は (# perl にデフォルトで) 組み込みのファンクションではなく, 現在のパッケージにインポートする機能のリストをモジュールに伝えるために MyModule パッケージにコールする単なる普通の静的メソッドです。詳細な情報は Exporter man ページを参照してください。
When you write your own modules, always remember that it's better to use @EXPORT_OK instead of @EXPORT, since the former doesn't export symbols unless it was asked to. Exports pollute the namespace of the module user. Also avoid short or common symbol names to reduce the risk of name clashes.

あなたがあなた独自のモジュールを書くときは, @EXPORT_OK を @EXPORT のかわりに使うことがベターであることを常に覚えておいてください, 前者はそれが要求されない限りシンボルをエクスポートしないからです。エクスポートはモジュールユーザの名前空間をよごします。また名前のクラッシュのリスクを軽減するために短かかったり一般的なシンボル名は避けてください。
When functions and variables aren't exported you can still access them using their full names, like $My::Module::bar or $My::Module::foo(). By convention you can use a leading underscore on names to informally indicate that they are internal and not for public use.

ファンクションと変数がエクスポートされないときでもあなたはそれらにそのフルネームでアクセスできます, $My::Module::bar や $My::Module::foo() のように。慣例によりあなたはそれらが内部的で公用ではないことを非公式に示すために名前の先頭のアンダースコアを使うことができます。
There's a corresponding "no" command that un-imports symbols imported by use, i.e., it calls Module->unimport(LIST) instead of import().

use によってインポートされたシンボルをアンインポートすることに対応する "no" コマンドがあります, i.e., import() のかわりに Module->unimport(LIST) をコールします。


do()



While do() behaves almost identically to require(), it reloads the file unconditionally. It doesn't check %INC to see whether the file was already loaded.

do() は require() とほとんど同じように振る舞いますが, これは無条件にファイルをリロードします。これはそのファイルがすでにロードされているかどうかをみるために %INC をチェックすることはしません。
If do() cannot read the file, it returns undef and sets $! to report the error. If do() can read the file but cannot compile it, it returns undef and puts an error message in $@. If the file is successfully compiled, do() returns the value of the last expression evaluated.

do() がファイルを読めない場合は, undef をリターンしてそのエラーをリポートするために $! をセットします。do() がファイルを読めたがそのコンパイルができなかった場合は, undef をリターンしてエラーメッセージを $@ に置きます。ファイルが正常にコンパイルされた場合, do() は最後に評価された式の値をリターンします。


グローバル変数の使用とそれをモジュール/パッケージ間で共有する : Using Global Variables and Sharing Them Between Modules/Packages



It helps when you code your application in a structured way, using the perl packages, but as you probably know once you start using packages it's much harder to share the variables between the various packagings. A configuration package comes to mind as a good example of the package that will want its variables to be accessible from the other modules.

これは perl パッケージを使って, あなたのアプリケーションを構造化した方法であなたがコーディングするときに役立ちますが, おそらくあなたが知っている通りあなたがパッケージの利用をスタートすると変数をさまざまなパッケージの間でシェアすることはかなり難しいです。構成パッケージは他のモジュールからその変数にアクセスできるようにするパッケージのグッドな例として思い浮かびます。
Of course using the Object Oriented (OO) programming is the best way to provide an access to variables through the access methods. But if you are not yet ready for OO techniques you can still benefit from using the techniques we are going to talk about.

もちろんオブジェクト指向 (OO) プログラミングはアクセスメソッドを通じて変数へのアクセスを提供するためのベストな方法です。もしあなたが OO テクニックのための準備がまだだったとしてもあなたは私たちがこれからお話しするテクニックを使うことでベネフィットを得ることができます。


変数をグローバルにする : Making Variables Global



When you first wrote $x in your code you created a (package) global variable. It is visible everywhere in your program, although if used in a package other than the package in which it was declared (main:: by default), it must be referred to with its fully qualified name, unless you have imported this variable with import(). This will work only if you do not use strict pragma; but you have to use this pragma if you want to run your scripts under mod_perl. Read The strict pragma to find out why.

あなたがあなたのコードで $x を最初に書いたときあなたは (パッケージ) グローバル変数を作成したことになります。これはあなたのプログラムのどこでも見えますが, それが宣言された (デフォルトで main::) パッケージではないパッケージで使う場合, あなたがこの変数を import() であなたがインポートしていない限りは, これはその完全修飾名で参照されなければなりません。これはあなたが strict プラグマの利用をしていない場合でのみ機能します; しかしあなたはあなたのスクリプトを mod_perl のもとで実行たいのであればこのプラグマを使わなければなりません。なぜなのかを調べるために The strict pragma (# https://perl.apache.org/docs/1.0/guide/porting.html#The_strict_pragma) を読んでください。

via: https://perl.apache.org/docs/1.0/guide/porting.html#The_strict_pragma


The strict pragma



It's _absolutely_ mandatory (at least for development) to start all your scripts with:

すべてのあなたのスクリプトをこれでスタートすることは _絶対に_ 必須です (少なくとも開発では):

use strict;

If needed, you can always turn off the 'strict' pragma or a part of it inside the block, e.g:

もし必要なら, あなたはブロックの内側で 'strict' (# 厳格な) プラグマやその一部を常にオフにできます, e.g:

{
no strict 'refs';
... some code
}

It's more important to have the strict pragma enabled under mod_perl than anywhere else. While it's not required by the language, its use cannot be too strongly recommended. It will save you a great deal of time. And, of course, clean scripts will still run under mod_cgi (plain CGI)!

他のどこよりも mod_perl のもとで strict プラグマを有効化しておくことはより重要です。これは言語により要求されているわけではありませんが, その利用を強く推奨してもし過ぎることはありません。これはあなたのかなりの時間を節約します。そして, もちろん, クリーンなスクリプトが mod_cgi (プレーン CGI) のもとで走ります !




strict プラグマ On で変数をグローバルにする : Making Variables Global With strict Pragma On



First you use :

まずあなたはこれを使います:

use strict;

Then you use:

それからあなたはこれを使います:

use vars qw($scalar %hash @array);

This declares the named variables as package globals in the current package. They may be referred to within the same file and package with their unqualified names; and in different files/packages with their fully qualified names.

これは現在のパッケージのパッケージグローバルとして名前付き変数を宣言します。これらは同じファイルやパッケージ内ではその被修飾名で; そして異なるファイル/パッケージではその完全修飾名で参照できるはずです。
With perl5.6 you can use the our operator instead:

perl5.6 (# 以降) でかわりにあなたは our オペレータを使うことができます:

our($scalar, %hash, @array);

If you want to share package global variables between packages, here is what you can do.

あなたがパッケージ間でパッケージグローバル変数のシェアをしたい場合は, こちらがあなたが行えることです。


グローバル変数のために Exporter.pm を使う : Using Exporter.pm to Share Global Variables



Assume that you want to share the CGI.pm object (I will use $q) between your modules. For example, you create it in script.pl, but you want it to be visible in My::HTML. First, you make $q global.

あなたがあなたのモジュール間で CGI.pm オブジェクト (私は $q を使います) をシェアしたいと想定します。例えば, あなたはそれを script.pl で作成しますが, あなたは My::HTML でそれを表示しようとします。まず, あなたは $q をグローバルにします。

#script.pl:
#---------------
use vars qw($q);
use CGI;
use lib qw(.);
use My::HTML qw($q); # My/HTML.pm は script.pl と同じ dir (My/HTML.pm is the same dir as script.pl)
$q = CGI->new;

My::HTML::printmyheader();

Note that we have imported $q from My::HTML. And My::HTML does the export of $q:

私たちは My::HTML からインポートされた $q をもっていることに注意してください。それと My::HTML は $q のエクスポートを行います。

#My/HTML.pm
#----------------
package My::HTML;
use strict;

BEGIN {
use Exporter ();

@My::HTML::ISA = qw(Exporter);
@My::HTML::EXPORT = qw();
@My::HTML::EXPORT_OK = qw($q);

}

use vars qw($q);

sub printmyheader{
# $q でやりたいことはなんでも... e.g. (Whatever you want to do with $q... e.g.)
print $q->header();
}
1;

So the $q is shared between the My::HTML package and script.pl. It will work vice versa as well, if you create the object in My::HTML but use it in script.pl. You have true sharing, since if you change $q in script.pl, it will be changed in My::HTML as well.

これで $q が My::HTML パッケージと script.pl との間でシェアされます。これはあなたが My::HTML でオブジェクトを作成するが script.pl で使うという, 逆でも同様に機能します。あなたが script.pl で $q を変更した場合, それは My::HTML でも変更されるので, あなたは真の共有をもっています。
What if you need to share $q between more than two packages? For example you want My::Doc to share $q as well.

あなたが 2 つ以上のパッケージで $q をシェアしたい場合はどうなる ? 例えばあなたが My::Doc でも $q をシェアしたいとします。
You leave My::HTML untouched, and modify script.pl to include:

あなたは My::HTML を手つかずのままにしておいて, これを含めるために script.pl を修正します:

use My::Doc qw($q);

Then you add the same Exporter code that we used in My::HTML, into My::Doc, so that it also exports $q.

それから My::Doc に, 私たちが My::HTML で使ったのと同じ Exporter のコードをあなたが追加して, それも $q をエクスポートするようにします。
One possible pitfall is when you want to use My::Doc in both My::HTML and script.pl. Only if you add

可能性のある落とし穴のひとつはあなたが My::Doc を My::HTML と script.pl の両方で使おうとするときです。あなたが My::HTML にこれだけを追加したときのみ

use My::Doc qw($q);

into My::HTML will $q be shared. Otherwise My::Doc will not share $q any more. To make things clear here is the code:

$q は共有されます。そうでなければ My::Doc は $q を共有されません。こちらが物事をクリアにするためのコードです:

#script.pl
#---------------
use vars qw($q);
use CGI;
use lib qw(.);
use My::HTML qw($q); # My/HTML.pm is in the same dir as script.pl
use My::Doc qw($q); # 同じく (Ditto)

My::HTML::printmyheader();

#My/HTML.pm
#----------------
package My::HTML;
use strict;

BEGIN {
use Ecporter ();

@My::HTML::ISA = qw(Exporter);
@My::HTML::EXPORT = qw();
@My::HTML::EXPORT_OK = qw($q);
}

use vars qw($q);
use My::Doc qw($q);

sub printmyheader{
# Whatever you want to do with $q... e.g.
print $q->header();

My::Doc::printtitle('Guide');
}
1;

#My/Doc.pm
#---------------
package My::Doc;
use strict;

BEGIN {
use Exporter ();

@My::HTML::ISA = qw(Exporter);
@My::HTML::EXPORT = qw();
@My::HTML::EXPORT_OK = qw($q);
}

use vars qw($q);

sub printtitle{
my $title = shift || 'None';

print $q->h1($title);
}
1;



Perl エイリアシング機能を使ったグローバル変数の共有 : Using the Perl Aliasing Feature to Share Global Variables



As the title says you can import a variable into a script or module without using Exporter.pm. I have found it useful to keep all the configuration variables in one module My::Config. But then I have to export all the variables in order to use them in other modules, which is bad for two reasons: polluting other packages' name spaces with extra tags which increases the memory requirements; and adding the overhead of keeping track of what variables should be exported from the configuration module and what imported, for some particular package. I solve this problem by keeping all the variables in one hash %c and exporting that. Here is an example of My::Config:

タイトルがいうようにあなたは Exporter.pm を使うことなくスクリプトやモジュールに変数をインポートできます。わたしはすべての構成変数を 1 つのモジュール My::Config でキープすると便利であることを見つけました。しかし私はそれらを他のモジュールで使うためにエクスポートしなければならず, それは 2 つの理由でバッドです: メモリ要件を増加させる余分なタグで他のパッケージの名前空間を汚す; それからある特定のパッケージのために, どの変数が構成モジュールからエクスポートされて何にインポートされるかを追跡するオーバヘッドを追加する。私はこの問題をひとつのハッシュ %c にすべての変数をキープしてそれをエクスポートすることで解決します。こちらが My::Config の例です:

package My::Config;
use strict;
use vars qw(%c);
%c = (
# All the configs go here
scalar_var => 5,

array_var => [qw(foo bar)],

hash_var => {
foo => 'Foo',
bar => 'BARRR',
},
);
1;

Now in packages that want to use the configuration variables I have either to use the fully qualified names like $My::Config::test, which I dislike or import them as described in the previous section. But hey, since we have only one variable to handle, we can make things even simpler and save the loading of the Exporter.pm package. We will use the Perl aliasing feature for exporting and saving the keystrokes:

これで構成変数を使いたいパッケージで私は私が好まない, $My::Config::test のような完全修飾名を使うか前のセクションで説明したようにそれらをインポートするかのいずれかをしなければいけなくなりました。しかしまあ, 私たちは処理する変数を 1 つしかもっていないので, 私たちは物事をよりシンプルにして Exporter.pm パッケージのローディングを節約できます。私たちはエクスポートとキーストロークの節約に Perl エイリアシング機能を使えます:

package My::HTML;
use strict;
use lib qw(.);
# グローバル構成がグローバル %c にエイリアスされるようになります (Global Configuration now aliased to global %c)
use My::Config (); # My/Config.pm in the same dir as script.pl
use vars qw(%c);
*c = \%My::Config::c;

# あなたは My::Config から変数にアクセスできるようになります
# Now you can access the variables from the My::Config
print $c{scalar_var};
print $c{array_var}[0];
print $c{hash_var}{foo};

Of course $c is global everywhere you use it as described above, and if you change it somewhere it will affect any other packages you have aliased $My::Config::c to.

もちろん $c は上記のとおりあなたがそれを使うどこででもグローバルで, あなたがどこかでそれを変更するとそれはあなたがエイリアスされた $My::Config::c をもつ他のすべてのパッケージに影響しまします。
Note that aliases work either with global or local() vars - you cannot write:

エイリアスはグローバルか local() の変数のどちらかで機能します - あなたはこのように書いてはいけません:

my *c = \%My::Config::c; # ERROR!

Which is an error. But you can write:

それはエラーです。しかしあなたはこのように書けます:

local *c = \%My::Config::c;

For more information about aliasing, refer to the Camel book, second edition, pages 51-52.

エイリアシングの詳細は, ラクダ本の, 第二版, ページ 51-52 を参照してください。


非ハードコードの構成モジュール名を使う : Using Non-Hadcoded Configuration Module Names



You have just seen how to use a configuration module for configuration centralization and an easy access to the information stored in this module. However, there is somewhat of a chicken-and-egg problem--how to let your other modules know the name of this file? Hardcoding the name is brittle--if you have only a single project it should be fine, but if you have more projects which use different configurations and you will want to reuse their code you will have to find all instances of the hardcoded name and replace it.

あなたは構成を一元化してこのモジュールに格納された情報に簡単にアクセスするためにどのように構成モジュールを使うかを見てきました。しかし, 多少の鶏と卵の問題があります -- どのようにしてあなたの他のモジュールがこのファイルの名前を知るようにしますか ? 名前のハードコーディングは脆弱です -- もしあなたがひとつのプロジェクトだけをもっているなら良いですが, もしあなたが異なる構成を使うより多くのプロジェクトをもっていてあなたがそれらのコードの再利用をしたいならあなたはハードコードされた名前のすべてインスタンスを見つけてそれをリプレイスしなければなりません。
Another solution could be to have the same name for a configuration module, like My::Config but putting a different copy of it into different locations. But this won't work under mod_perl because of the namespace collision. You cannot load different modules which uses the same name, only the first one will be loaded.

他の解決策は My::Config のように, 構成モジュールを同じ名前をもつようにするが異なるロケーションに異なるそのコピーを置くことです。しかしこれは名前空間の衝突によってmod_perl のもとでは機能しません。あなたは異なるモジュールを同じ名前を使ってロードすることはできません, 最初のものがロードされるだけです。
Luckily, there is another solution which allows us to stay flexible. PerlSetVar comes to rescue. Just like with environment variables, you can set server's global Perl variables which can be retrieved from any module and script. Those statements are placed into the httpd.conf file. For example

運よく, 私たちを柔軟でいられるようにしてくれる他の解決策があります。PerlSetVar が救いになります。環境変数と同じく, あなたは任意のモジュールとスクリプトから取得できるサーバのグローバルな Perl 変数をセットすることができます。これらのステートメントは httpd.conf に配置されます。例えば

PerlSetVar FooBaseDir /home/httpd/foo
PerlSetVar FooConfigModule Foo::Config

Now we require() the file where the above configuration will be used.

これで私たちは上の構成を使うファイルを require() します。

PerlRequire /home/httpd/perl/startup.pl

In the startup.pl we might have the following code:

startup.pl で私たちは次のコードをもっているはずです:

# 構成モジュールのパスを取得する (retrieve the configuration module path)
use Apache;
my $s = Apache->server;
my $base_dir = $s->dir_config('FooBaseDir') || '';
my $config_module = $s->dir_config('FooConfigModule') || '';
die "FooBaseDir and FooConfigModule aren't set in httpd.conf"
unless $base_dir and $config_module;

# 構成モジュールへのリアルなパスを構築 (build the real path to the config module)
my $path = "$base_dir/$config_module";
$path =~ s|::|/|;
$path .= ".pm";
# 私たちは "/home/httpd/foo/Foo/Config.pm" のようなものをもちます
# (we have something like "/home/httpd/foo/Foo/Config.pm")

# これで私たちは構成モジュールを引き込むことができるようになりました。
# (now we can pull in the configuration module)
require $path;

Now we know the module name and it's loaded, so for example if we need to use some variables stored in this module to open a database connection, we will do:

これで私たちをモジュール名を知りそれがロードされますので, 例えば私たちがデータベースコネクションを開くためにこのモジュールに格納された何らかの変数を使いたい場合, 私たちはこれを行います:

Apache::DBI->connect_on_init
(DBI::mysql:${$config_module.'::DB_NAME'}::${$config_module.'::SERVER'}",
${$config_module.'::USER'},
${$config_module.'::USER_PASSWD'},
{
PrintError => 1, # warn() on errors
RaiseError => 0, # don't die on error
AutoCommit => 1, # commit executes immediately
}
);

Where variable like:

このような変数の場所は:

${$config_module.'::USER'}

In our example are really:

私たちの例で実際にはこれです:

$Foo::Config::USER

If you want to access these variable from within your code at the run time, instead accessing to the server object $c, use the request object $r:

あなたがランタイムにあなたのコードの中からこれらの変数にアクセスしたいなら, サーバオブジェクト $c にアクセスするかわりにリクエストオブジェクト $r を使います:

my $r = shift;
my $base_dir = $r->dir_config('FooBaseDir') || '';
my $config_module = $r->dir_config('FooConfigModule') || '';



特別な Perl 変数のスコープ : The Scope of the Special Perl Variables



Special Perl variables like $| (buffering), $^T (script's start time), $^W (warnings mode), $/ (input record separator), $ (output record separator) and many more are all true global variables; they do not belong to any particular package (not even main::) and are universally available. This means that if you change them, you change them anywhere across the entire program; furthermore you cannot scope them with my (). However you can local()ise them which means that any changes you apply will only last until the end of the enclosing scope. In the mod_perl situation where the child server doesn't usually exit, if in one of your scripts you modify a global variable it will be changed for the rest of the process' life and will affect all the scripts executed by the same process. Therefore localizing these variables is highly recommended, I'd say mandatory.

$| (バッファリング), $^T (スクリプトのスタートタイム), $^W (ワーニングスモード), $/ (インプットレコードセパレータ), $\ (アウトプットレコードセパレータ) などのような特別な Perl 変数はすべて真のグローバル変数です; それらは特定のパッケージに属しておらず (main:: ですらない) 普遍的に利用可能です。これはあなたがそれらを変更すると, あなたはプログラム全体にわたってそれらを変更することを意味します; さらにあなたはそれらを my () でスコープすることはできません。しかしあなたはそれらを local() ise することができてそれは囲んでいるスコープの終わりまでに限って任意の変更をあなたが適用できることを意味します。child (# 子) サーバが通常は終了しない mod_perl のシチュエーションで, あなたのスクリプトのひとつであなたがグローバル変数を修正するとそれは残りのプロセスのライフで変更されることになり同じプロセスで実行されるすべてのスクリプトに影響します。したがってこれらの変数をローカライズすることはかなり推奨されていて, 私は必須だと思っています。
We will demonstrate the case on the input record separator variable. If you undefine this variable, the diamond operator (readline) will suck in the whole file at once if you have enough memory. Remembering this you should never write code like the example below.

私たちはインプットレコードセパレータ変数のケースをデモンストレーションします。あなたがこの変数を未定義にすると, あなたが十分なメモリをもっていればダイアモンドオペレータ (readline) はファイル全体を 1 度で吸い込みます。これを覚えておいてあなたは以下の例のようなコードを決して書かないように。

$/ = undef; # BAD!
open IN, "file" ....
# slurp it all into a variable
$all_the_file = <IN>;

The proper way is to have a local() keyword before the special variable is changed, like this:

適切な方法は特別な変数が変更される前に local() キーワードをもつことです, このように:

local $/ = undef;
open IN, "file" ....
# slurp it all inside a variable
$all_the_file = <IN>;

But there is a catch. local() will propagate the changed value to the code below it. The modified value will be in effect until the script terminates, unless it is changed again somewhere else in the script.

しかし罠があります。local() はその変更された値をそのしたのコードに伝播します。修正された値はそれがそのスクリプトのどこかで再び変更されるまで, スクリプトの終端まで影響します。
A cleaner approach is to enclose the whole of the code that is affected by the modified variable in a block, like this:

よりクリーンなアプローチはブロックで修正された変数によって影響されるコード全体を囲むことです, このようにして:

{
local $/ = undef;
open IN, "file" ....
# slurp it all inside a variable
$all_the_file = <IN>;
}

That way when Perl leaves the block it restores the original value of the $/ variable, and you don't need to worry elsewhere in your program about its value being changed here.

そうすれば Perl がこのブロックを去るときに $/ 変数のオリジナルの値がリストアされるので, あなたはあなたのプログラムの他の場所でここで変更されたこの値について心配する必要はありません。
Note that if you call a subroutine after you've set a global variable but within the enclosing block, the global variable will be visible with its new value inside the subroutine.

あなたがグローバル変数をセットした後であなたがサブルーチンをコールした場合でもそれを囲むブロック内であれば, グローバル変数はサブルーチンの内側でその新しい値とともに表示されることに注意してください。


コンパイルされた正規表現 : Compiled Reqular Expressions



When using a regular expression that contains an interpolated Perl variable, if it is known that the variable (or variables) will not change during the execution of the program, a standard optimization technique is to add the /o modifier to the regex pattern. This directs the compiler to build the internal table once, for the entire lifetime of the script, rather than every time the pattern is executed. Consider:

差し込まれた Perl 変数を含む正規表現を使うとき, プログラムの実行中にその変数 (または複数の変数) を変更しないことがわかっているなら, 標準の最適化テクニックはその正規表現パターンに /o 修飾子を追加することです。これはそのパターンが実行されるたびにではなくスクリプトのライフタイム全体で, 内部テーブルを 1 度構築するようにコンパイラに指示します。考えてみます:

my $pat = '^foo$'; # HTML フォームフィールドから入力されそうなもの (likely to be input from an HTML form field)
foreach( @list ) {
print if /$pat/o;
}

This is usually a big win in loops over lists, or when using the grep() or map() operators.

これは通常リストのループや, grep() および map() オペレータを使うときにビッグウィンです。
In long-lived mod_perl scripts, however, the variable may change with each invocation and this can pose a problem. The first invocation of a fresh httpd child will compile the regex and perform the search correctly. However, all subsequent uses by that child will continue to match the original pattern, regardless of the current contents of the Perl variables the pattern is supposed to depend on. Your script will appear to be broken.

しかし, 長く続く mod_perl スクリプトでは, 変数は各呼び出しで変更されるかもしれずこれは問題を引き起こします。フレッシュな httpd child の最初の呼び出しは正しく正規表現のコンパイルとそのサーチを実行します。しかし, 後に続くその child によるすべての利用はパターンが頼ることになっている現在の Perl の変数のコンテンツに関係なくオリジナルパターンにマッチし続けます。あなたのスクリプトは壊れているようにみえます。
There are two solutions to this problem:

この問題のために 2 つの解決策があります:
The first is to use eval q//, to force the code to be evaluated each time. Just make sure that the eval block covers the entire loop of processing, and not just the pattern match itself.

最初のものはコードを毎回評価することを強制するために, eval q// を使うことです。eval ブロックがパターンマッチそれ自体だけでなく, 処理のループ全体をカバーしていることを確認してください。
The above code fragment would be rewritten as:

上記コードの断片はこのようにリライトします:

my $pat = '^foo$';
eval q{
foreach( @list ) {
print if /$pat/o;
}
}

Just saying:

こういうのは:

foreach( @list ) {
eval q{ print if /$pat/o; };
}

means that we recompile the regex for every element in the list even though the regex doesn't change.

正規表現を変更していなかったとしもリストのすべての要素のために私たちが正規表現をリコンパイルすることを意味します。
You can use this approach if you require more than one pattern match operator in a given section of code. If the section contains only one operator (be it an m// or s///), you can rely on the property of the null pattern, that reuses the last pattern seen. This leads to the second solution, which also eliminates the use of eval.

あなたはあなたがコードの特定のセクションで 1 つ以上のパターンマッチオペレータを要求する場合にこのアプローチを使えます。そのセクションが 1 つのオペレータのみ (m// や s///) を含んでいる場合, あなたは最後に見たパターンを再利用する, null パターンのプロパティに頼ることができます。これは 2 つ目の解決策につながり, eval の利用も除去します。
The above code fragment becomes:

上記コードの断片はこうなります:

my $pat = '^foo$';
"something" =~ /$pat/; # ダミーマッチ (失敗してはならない !) (dummy match (MUST NOT FAIL!))
foreach( @list ) {
print if //;

The only gotcha is that the dummy match that boots the regular expression engine must absolutely, positively succeed, otherwise the pattern will not be cached, and the // will match everything. If you can't count on fixed text to ensure the match succeeds, you have two possibilities.

唯一の問題は正規表現エンジンを起動するダミーマッチが絶対に, 必ず成功しなければならないことで, そうでなければそのパターンはキャッシュされず, // はすべてにマッチします。あなたがマッチを成功させるために固定のテキストを当てにできない場合, あなたには 2 つの可能性があります。
If you can guarantee that the pattern variable contains no meta-characters (things like *, +, ^, $...), you can use the dummy match:

あなたがパターン変数がメタキャラクタ (*, +, ^, $... のようなもの) を含まないことを保証できるなら, あなたはこのダミーマッチを使えます:

$pat =~ /\Q$pat\E/; # メタキャラクタが存在しないなら保証される (guaranteed if no meta-characters present)

If there is a possibility that the pattern can contain meta-characters, you should search for the pattern or the non-searchable \377 character as follows:

パターンがメタキャラクタを含む可能性があるなら, あなたは次のようにパターン or 検索できない \377 キャラクタを検索する必要があります。

"\377" =~ /$pat|^\377$/; # メタキャラクタが存在するなら保証される (quaranteed if meta-characters present)

Another approach:

別のアプローチ:
It depends on the complexity of the regex to which you apply this technique. One common usage where a compiled regex is usually more efficient is to "match any one of a group of patterns" over and over again.

これはあなたがこのテクニックを適用する正規表現の複雑さに依存します。コンパイルされた正規表現の方が通常より効率的な一般的な使用法の 1 つは "パターンのグループのいずれか 1 つとのマッチ" を何度も繰り返すことです。
Maybe with a helper routine, it's easier to remember. Here is one slightly modified from Jeffery Friedl's example in his book "Mastering Regular Expressions".

たぶんヘルパルーチンなら, 覚えやすいです。こちらは Jeffery Friedl の本 "マスタリング 正規表現" での彼の例を少し変更したものです。

#####################################################
# Build_MatchMany_Function
# -- 入力 (Input): パターンのリスト (list of patterns)
# -- 主力 (Output): 効率的に, "Input" で与えられた
# パターンのいずれかに対して
# $_[0] をマッチするコードレフ。
# (A code ref which matches its $_[0]
# against ANY of the patterns given in the
# "Input", efficiently.)
#
sub Build_MatchMany_Function {
my @R = @_;
my $expr = join '||', map { "\$_[0] =~ m/\$R[$_]/o" } ( 0..$#R );
my $matchsub = eval "sub { $expr }";
die "Failed in building regex @R: $@" if $@;
$matchsub;
}

Example usage:

使用例:

@some_browsers = qw(Mozilla Lynx MSIE AmigaBoyager lwp libwww);
$Known_Browser = Build_MatchMany_Funtion(@some_browsers);

while (<ACCESS_LOG>) {
# ...
$browser = get_browser_field($_);
if ( ! &$Known_Browser($browser) ) {
print STDERR "Unknown Browser: $browser\n";
}
# ...
}

And of course you can use the qr() operator which makes the code even more efficient:

そしてもちろんあなたはコードをより効率的にする qr() オペレータを使うことができます:

my $pat = '^foo$';
my $re = qr($pat);
foreach( @list ) {
print if /$re/;
}

The qr() operator compiles the pattern for each request and then use the compiled version in the actual match.

qr() オペレータは各リクエストのためにパターンをコンパイルして実際のマッチでそのコンパイルされたバージョンを使います。


mod_perl の例外処理 : Exception Handling for mod_perl



Here are some guidelines for clean(er) exception handling in mod_perl, although the technique presented can be applied to all of your Perl programming.

こちらは mod_perl での clean(er) な例外処理のためのいくつかのガイドラインですが, 提示されたテクニックはあなたの Perl プログラミングのすべてに適用できます。
The reasoning behind this document is the current broken status of $SIG{__DIE__} in the perl core - see both the perl5-porters and the mod_perl mailing list archives for details on this discussion. (It's broken in at least Perl v5.6.0 and probably in later versions as well). In short summary, $SIG{__DIE__} is a little bit too global, and catches exceptions even when you want to catch them yourself, using an eval{} block.

このドキュメントの根拠は perl core での $SIG{__DIE__} の現在の壊れたステータスです -- この議論の詳細は perl5-porters と mod_perl のメーリングリストアーカイブの両方を参照してください。(これは少なくとも Perl v5.6.0 で壊れていておそらく後のバージョンでも同様です)。ショートサマリ, $SIG{__DIE__} はややグローバルすぎで, あなたがそれを eval{} ブロックを使い, あなた自身でキャッチしたいときであっても例外をキャッチします。


Perl で例外をトラップする : Trapping Exceptions in Perl



To trap an exception in Perl we use the eval{} construct. Many people initially make the mistake that this is the same as the eval EXPR construct, which compiles and executes code at run time, but that's not the case. eval{} compiles at compile time, just like the rest of your code, and has next to zero run-time penalty. For the hardcore C programmers among you, it uses the setjmp/longjmp POSIX routines internally, just like C++ exceptions.

Perl で例外をトラップするために私たちは eval{} 構造を使います。多くの人はこれがランタイムでコードをコンパイルして実行する, eval EXPR 構造と同じだと最初に間違いをしますが, そうではありません。eval{} はあなたの残りのコードと同じくコンパイルタイムでコンパイルし, ランタイムのペナルティはゼロに近いです。あなたの中のハードコアな C プログラマのために, これは C++ の例外と同じく, 内部的に setjmp/longjmp POSIX ルーチンを使います。
When in an eval block, if the code being executed die()'s for any reason, an exception is thrown. This exception can be caught by examining the $@ variable immediately after the eval block; if $@ is true then an exception occurred and $@ contains the exception in the form of a string. The full construct looks like this:

eval ブロック内で, 何らかの理由でコードが die() の実行をした場合, 例外がスローされます。この例外は eval ブロックの直後に$@ 変数を調べることでキャッチできます; $@ が true の場合は例外が発生していて $@ は文字列形式で例外を含みます。完全な構造はこのようになります:

eval {
# ここに何かのコード (Some code here)
}; # そこの重要なセミコロンに注意 (Note important semi-colon there)
if ($@) # スローされた例外を含む $@ ($@ contains the exception that was thrown)
{
# 例外で何かをする (Do something with the exeption)
}
else # オプショナル (optional)
{
# 例外が投げられていない (No exception was thrown)
}

Most of the time when you see these exception handlers there is no else block, because it tends to be OK if the code didn't throw an exception.

あなたがこれらの例外処理を見るときのほとんどの場面で else ブロックはありません, なぜならコードが例外を投げない場合それは OK な傾向だからです。
Perl's exception handling is similar to that of other languages, though it may not seem so at first sight:

Perl の例外処理は他の言語のそれと似ていますが, 初見ではそう見えないかもしれません:

Perl Other language
------------------------------- ------------------------------------
eval { try {
# ここで実行
# execute here // execute here
# 私たち独自の例外を起こす
# raise our own exception: // raise our own exception:
die "Oops" if /error/; if(error==1){throw Exception.Oops;}
# さらに実行
# execute more // execute more
} ; }
if($@) { catch {
# 例外処理
# handle exceptions
switch( Exception.id ) {
if( $@ =~ /Fail/ ) { Fail : fprintf( stderr, "Failed\n" ) ;
print "Failed\n" ; break ;
}
elsif( $@ =~ /Oops/ ) { Oops : throw Exception ;
# チェーンを断つ (# ?)
# Pass it up the chain
die if $@ =~ /Oops/;
}
else { default :
# 他のすべて例外を
# ここで処理
# handle all other }
# exceptions here }
// ここまできたらすべて OK か処理済み
} // If we got here all is OK or handled
}
else { # optional
# すべてヨシ
# all is well
}
# すべてヨシ or 処理された
# all is well or has been handled



代替の例外処理テクニック : Alternative Exception Handling Techniques



An often suggested method for handling global exceptions in mod_perl, and other perl programs in general, is a __DIE__ handler, which can be set up by either assigning a function name as a string to $SIG{__DIE__} (not particularly recommended, because of the possible namespace clashes) or assigning a code reference to $SIG{__DIE__}. The usual way of doing so is to use an anonymous subroutine:

mod_perl や他の一般的な perl プログラムで, グローバルの例外を処理するためにしばしば提案される手法は, __DIE__ ハンドラで, これは文字列の $SIG{__DIE__} (特にお勧めはしません, 名前空間クラッシュの可能性があるからです) または $SIG{__DIE__} へのコードリファレンスのいずれかをファンクション名をアサインすることでセットアップできます。通常それを行う方法は無名サブルーチンを使います。

$SIG{__DIE__} = sub { print "Eek - we died with:\n", $_[0]; };

The current problem with this is that $SIG{__DIE__} is a global setting in your script, so while you can potentially hide away your exceptions in some external module, the execution of $SIG{__DIE__} is fairly magical, and interferes not just with your code, but with all code in every module you import. Beyond the magic involved, $SIG{__DIE__} actually interferes with perl's normal exception handling mechanism, the eval{} construct. Witness:

これの現在の問題は $SIG{__DIE__} があなたのスクリプトでのグローバルセッティングなので, 外部モジュールであなたの例外を隠してしまうことができる可能性があります, $SIG{__DIE__} の実行はかなりマジカルで, あなたのコードだけでなく, あなたがインポートしたモジュールのすべてのコードに干渉します。伴われるマジックを超えて, 実際に $SIG{__DIE__} は perl のノーマルな例外処理メカニズムの, eval{} 構造に干渉します。証人:

$SIG{__DIE__} = sub { print "handler\n"; };

eval {
print "In eval\n";
die "Failed for some reason\n";
};
if ($@) {
print "Caught exception: $@;
}

The code unfortunately prints out:

このコードは残念ながらこれを出力します:

In eval
handler

Which isn't quite what you would expect, especially if that $SIG{__DIE__} handler is hidden away deep in some other module that you didn't know about. There are work arounds however. One is to localize $SIG{__DIE__} in every exception trap you write:

これはまったくあなたが期待したものではないでしょう, $SIG{__DIE__} ハンドラがあなたがそれについて知らない他のモジュールの深くに隠されている場合は特にです。しかし回避策があります。ひとつはあなたが書くすべての例外トラップで $SIG{__DIE__} をローカライズすることです:

eval {
local $SIG{__DIE__};
...
};

Obviously this just doesn't scale - you don't want to be doing that for every exception trap in your code, and it's a slow down. A second work around is to check in your handler if you are trying to catch this exception:

あきらかにこれはスケールしません - あなたはあなたのコードのすべての例外トラップでは行わないほうがよいですし, これは遅くなります。2 つ目の回避策はあなたがこの例外のキャッチをトライする場合にあなたのハンドラでチェックすることです:

$SIG{__DIE__} = sub {
die $_[0] if $^S;
print "handler\n";
};

However this won't work under Apache::Registry - you're always in an eval block there!

しかしこれは Apache::Registry のもとでは機能しません - あなたは常に eval ブロック内にいるのです !
$^S isn't totally reliable in certain Perl versions. e.g. 5.005_03 and 5.6.1 both do the wrong thing with it in certain situations. Instead, you use can use the caller() function to figure out if we are called in the eval() context:

$^S は特定の Perl バージョンでは完全には信頼できません。e.g. 5.005_03 と 5.6.1 は両方とも特定の状況で間違ったことを行います。かわりに, あなたは caller() ファンクションを使って私たちが eval() コンテキストでコールしたかを確認することができます:

$SIG{__DIE__} = sub {
my $in_eval = 0;
for (my $stack = 1; my $sub = (CORE::caller($stack))[3]; $stack++) {
$in_eval = 1 if $sub =~ /^\(eval\)/;
}
my_die_handler(@_) unless $in_eval;
};

The other problem with $SIG{__DIE__} also relates to its global nature. Because you might have more than one application running under mod_perl, you can't be sure which has set a $SIG{__DIE__} handler when and for what. This can become extremely confusing when you start scaling up from a set of simple registry scripts that might rely on CGI::Carp for global exception handling (which uses $SIG{__DIE__} to trap exceptions) to having many applications installed with a variety of exception handling mechanisms in place.

$SIG{__DIE__} のもうひとつの問題はそのグローバルな性質にも関連しています。あなたは mod_perl のもとで 1 つ以上のアプリケーションを実行している可能性があるので, あなたはその $SIG{_DIE__} ハンドラがいつ何のためにセットされたのかを確認することができません。あなたがグローバルな例外処理のために CGI::Carp に依存する可能性があるシンプルなレジストリスクリプトのセットからさまざまな例外処理メカニズムが整っている多くのアプリケーションをインストールすることでスケールアップをスタートするとこれは極めて複雑になります。
You should warn people about this danger of $SIG{__DIE__} and inform them of better ways to code. The following material is an attempt to do just that.

あなたは $SIG{__DIE__} のこの危険について人々に警告しコードのためのよりよい方法を知らせなければなりません。次のマテリアルはそれを行うことを試みます。


ベターな例外処理 : Better Exception Handling



The eval{} construct in itself is a fairly weak way to handle exceptions as strings. There's no way to pass more information in your exception, so you have to handle your exception in more than one place - at the location the error occurred, in order to construct a sensible error message, and again in your exception handler to de-construct that string into something meaningful (unless of course all you want your exception handler to do is dump the error to the browser). The other problem is that you have no way of automatically detecting where the exception occurred using eval{} construct. In a $SIG{__DIE__} block you always have the use of the caller() function to detect where the error occurred. But we can fix that...

eval{} 構造自体は例外を文字列で処理するにはかなり弱い方法です。あなたの例外でより多くの情報を渡す方法がないので, エラーが発生した場所で, センスのあるエラーメッセージを構築するために - あなたはあなたの例外を 1 つ以上の場所で処理しなければなりません, そして再びあなたの例外ハンドラでその文字列を何か意味のあるものに分解します (もちろんあなたがあなたの例外ハンドラに行わせたいことがブラウザにエラーをダンプしたい場合を除きます)。もうひとつの問題はあなたが eval{} 構造を使ってエラーが発生した場所を自動的に検出する方法をもたないことです。 $SIG{__DIE__} ブロックではエラーが発生した場所を検出するためにあなたは常に caller() ファンクションを利用します。しかし私たちはそれをフィックスできます...
A little known fact about exceptions in perl 5.005 is that you can call die with an object. The exception handler receives that object in $@. This is how you are advised to handle exceptions now, as it provides an extremely flexible and scalable exceptions solution, potentially providing almost all of the power Java exceptions.

perl 5.005 での例外についてほとんど知られていない事実は, あなたはオブジェクトで die をコールできるということです。例外ハンドラはそのオブジェクトを $@ で受けとります。これは潜在的に Java 例外のパワーのほとんどすべてを提供する, 非常に柔軟でスケーラブルな例外ソリューションを提供して, すぐにあなたがどのように例外を処理するかを知らせます。
[As a footnote here, the only thing that is really missing here from Java exceptions is a guaranteed Finally clause, although its possible to get about 98.62% of the way towards providing that using eval{}.]

[ここでの脚注として, Java 例外からここで実際に見あたらないものは保証付きの Finally 句だけですが, eval{} を使ってそれが提供するその方法に対して約 98.62% をゲットすることが可能です。]


ちょっとしたハウスキーピング : A Little Housekeeping



First though, before we delve into the details, a little housekeeping is in order. Most, if not all, mod_perl programs consist of a main routine that is entered, and then dispatches itself to a routine depending on the parameters passed and/or the form values. In a normal C program this is your main() function, in a mod_perl handler this is your handler() function/method. The exception to this rule seems to be Apache::Registry scripts, although the techniques described here can be easily adapted.


最初に, 私たちは詳細を掘り下げる前に, ちょっとしたハウスキーピングをします。すべてではありませんが, ほとんどの, mod_perl プログラムはそれが入力された main ルーチンで構成され, パラメータ and/or フォームの値に応じてそれ自身をルーチンにディスパッチします。ノーマルな C プログラムでこれはあなたの main() ファンクションで, mod_perl ハンドラでこれはあなたの handler() ファンクション/メソッドです。このルールの例外は Apache::Registry スクリプトのように見えますが, ここで説明されるこのテクニックは簡単に適応させることができます。
In order for you to be able to use exception handling to its best advantage you need to change your script to have some sort of global exception handling. This is much more trivial than it sounds. If you're using Apache::Registry to emulate CGI you might consider wrapping your entire script in one big eval block, but I would discourage that. A better method would be to modularize your script into discrete function calls, one of which should be a dispatch routine:

あなたが例外処理をそのベストアドバンテージで使えるようにするためにあなたはあなたのスクリプトを何らかのグローバル例外処理をもつように変更する必要があります。これは思ったよりもずっと些細なことです。あなたが CGI をエミュレートするために Apache::Registry を使っているならあなたはあなたのスクリプト全体をひとつの大きな eval ブロックでラッピングすることも考慮できますが, 私はそれを阻止するでしょう。ベターな手法はあなたのスクリプトを分離したファンクションコールにモジュール化することで, そのひとつをディスパッチルーチンにします:

#!/usr/bin/perl -w
# Apache::Registry script

eval {
dispatch();
};
if ($@) {
# 例外処理 (handle exception)
}

sub dispatch {
...
}

This is easier with an ordinary mod_perl handler as it is natural to have separate functions, rather than a long run-on script:

これは長く実行され続けるスクリプトではなく, 分割したファンクションをもつことが自然な普通の mod_perl ハンドラで簡単です:

# MyHandler.pm
#-------------
sub handler {
my $r = shift;

eval {
dispatch($r);
};
if ($@) {
# handle excaption
}
}

sub dispatch {
my $r = shift;
...
}

Now that the skeleton code is setup, let's create an exception class, making use of Perl 5.005's ability to throw exception objects.

スケルトンコードをセットアップしたので, Perl 5.005 の例外オブジェクトをスローする能力を利用して, 例外クラスを作成しましょう。


例外クラス : An Exception Class



This is a really simple exception class, that does nothing but contain information. A better implementation would probably also handle its own exception conditions, but that would be more complex, requiring separate packages for each exception type.

これは本当にシンプルな例外クラスで, 何もせず情報だけを含みます。ベターな実装はおそらくそれ自身の例外条件も処理しますが, それはより複雑で, 例外のタイプごとに別のパッケージを必要とします。

#My/Exception.pm
#---------------
package My::Exception;

sub AUTOLOAD {
no strict 'refs', 'subs';
if ($AUTOLOAD =~ /.*::([A-Z]\w+)$/) {
my $exception = $1;
*{$AUTOLOAD} =
sub {
shift;
my ($package, $filename, $line) = caller;
push @_, caller => {
package => $package,
filename => $filename,
line => $line,
};
bless { @_ }, "My::Exception::$exception";
};
goto &{$AUTOLOAD};
}
else {
die "No such exception class: $AUTOLOAD\n";
}
}

1;

OK, so this is all highly magical, but what does it do? It creates a simple package that we can import and use as follows:

OK, これはすべて高度にマジカルですが, これは何をするのでしょう ? これは私たちが次のようにインポートして使えるシンプルなパッケージを作成します:

use My::Exception;

die My::Exception->SomeException( foo => "bar");

The exception class tracks exactly where we died from using the caller() mechanism, it also caches exception classes so that AUTOLOAD is only called the first time (in a given process) an exception of a particular type is thrown (particularly relevant under mod_perl).

例外クラスは caller() メカニズムを使って私たちが die した場所を正確に追跡し, 例外クラスもキャッシュするので AUTOLOAD は (特に mod_perl に関連している) 特定の例外タイプがスローされた (与えられたプロセスで) 初回にのみコールされます。


キャッチされない例外をキャッチ : Catching Uncaught Exceptions



What about exceptions that are thrown outside of your control? We can fix this using one of two possible methods. The first is to override die globally using the old magical $SIG{__DIE__}, and the second, is the cleaner non-magical method of overriding the global die() method to your own die() method that throws an exception that makes sense to your application.

あなたのコントロールの外側でスローされた例外はどうなるでしょうか ? 私たちは 2 つの可能な手法の 1 つを使ってこれをフィックスできます。1 つ目は 古いマジカルな $SIG{__DIE__} を使って die をグローバルにオーバライドすることで, 2 つ目は, グローバルな die() メソッドをあなたのアプリケーションに意味がある例外をスローするあなた独自の die() メソッドでオーバライドするよりクリーンで非マジカルな手法です


$SIG{__DIE__} を使う : Using $SIG{__DIE__}



Overloading using $SIG{__DIE__} in this case is rather simple, here's some code:

こちらのコード, このケースの $SIG{__DIE__} を使ったオーバーライディングはずいぶんシンプルです:

$SIG{__DIE__} = sub {
if(!ref($_[0])) {
$err = My::Exception->UnCaught(text => join('', @_));
}
die $err;
};

All this does is catch your exception and re-throw it. It's not as dangerous as we stated earlier that $SIG{__DIE__} can be, because we're actually re-throwing the exception, rather than catching it and stopping there. Even though $SIG{__DIE__} is a global handler, because we are simply re-throwing the exception we can let other applications outside of our control simply catch the exception and not worry about it.

これがすることのすべてはあなたの例外をキャッチしてそれを再びスローすることです。$SIG{__DIE__} ができることは私たちが前に述べたことほどはデンジャラスではありません, それをキャッチしてそこで停止するのではなく私たちは実際に例外を再びスローするからです。$SIG{__DIE__} はグローバルハンドラではありますが, 私たちは例外をシンプルに再スローしているだけ私たちはコントロール外の他のアプリケーションに例外をシンプルにキャッチするようにさせることができるのでそれについて心配することはありません。
There's only one slight buggette left, and that's if some external code die()'ing catches the exception and tries to do string comparisons on the exception, as in:

わずかなバグ (# ?) がひとつだけ残っていて, それは何らかの外部コードが die() して例外をキャッチしてその例外で文字列比較を行おうとした場合です, このように:

eval {
... # some code
die "FATAL ERROR!\n";
};
if ($@) {
if ($@ =~ /^FATAL ERROR/) {
die $@;
}
}

In order to deal with this, we can overload stringification for our My::Exception::UnCaught class:

これに対処するために, 私たちは私たちの My::Exception::UnCaught クラスのための文字列化をオーバーロードできます:

{
package My::Exception::UnCaught;
use overload '""' => \&str;

sub str {
shift->{text};
}
}

We can now let other code happily continue. Note that there is a bug in Perl 5.6 which may affect people here: Stringification does not occur when an object is operated on by a regular expression (via the =~ operator). A work around is to explicitly stringify using qq double quotes, however that doesn't help the poor soul who is using other applications. This bug has been fixed in later versions of Perl.

私たちはこれで他のコードをいい感じに継続するようにできます。Perl 5.6 ではここの人々に影響がありそうなバグがあることに注意してください: 正規表現によってオブジェクトが操作されたとき文字列化が発生しません (via =~ オペレータ)。回避策は qq ダブルクォートを使って明示的に文字列化することですが, しかしそれは他のアプリケーションを使っている哀れな人のヘルプになりません。このバグは Perl の新しいバージョンでフィックスされています。


コアの die() ファンクションをオーバーライドする : Overriding the Core die() Function



So what if we don't want to touch $SIG{__DIE__} at all? We can overcome this by overriding the core die function. This is slightly more complex than implementing a $SIG{__DIE__} handler, but is far less magical, and is the right thing to do, according to the perl5-porters mailing list.

では私たちが $SIG{__DIE__} をまったくさわりたくない場合はどうでしょうか? 私たちはコアの die ファンクションによってこれを克服できます。$SIG{__DIE__} ハンドラを実装するよりもこれはやや複雑ですが, マジカルはずっと少なくて, perl5-porters メーリングリストによれば正しい行動です。
Overriding core functions has to be done from an external package/module. So we're going to add that to our My::Exception module. Here's the relevant parts:

コアファンクションのオーバーライディングは外部のパッケージ/モジュールから行われる必要があります。ですから私たちは私たちの My::Exception モジュールにそれを追加します。こちらが関連する部分です:

use vars qw/@ISA @EXPORT/;
use Exporter;

@EXPORT = qw/die/;
@ISA = 'Exporter';

sub die (@); # CORE::die にマッチするプロトタイプ (prototype to match CORE:die)

sub import {
my $pkg = shift;
$pkg->export('CORE::GLOBAL', 'die');
Exporter::import($pkg,@_);
}

sub die (@) {
if (!ref($_[0])) {
CORE::die My::Exception->UnCaught(text => join('', @_));
}
CORE::die $_[0]; # only use first element because its an object
}

That wasn't so bad, was it? We're relying on Exporter's export() function to do the hard work for us, exporting the die() function into the CORE::GLOBAL namespace. If we don't want to overload die() everywhere this can still be an extremely useful technique. By just using Exporter's default import() method we can export our new die() method into any package of our choosing. This allows us to short-cut the long calling convention and simply die() with a string, and let the system handle the actual construction into an object for us.

それほど悪くない, でしょ ? 私たちは私たちのためのハードワークに Exporter の export() ファンクションを頼りにして, CORE::GLOBAL 名前空間に die() ファンクションをエクスポートしています。私たちがどこででも die() をオーバーロードしたくないとしてもこれは極めて便利なテクニックです。Exporter のデフォルトの import() メソッドを使うだけで私たちは私たちの新しい die() メソッドを私たちが選んだ任意のパッケージにエクスポートできます。これは長い呼びだし規約をショートカットして文字列でシンプルに die() し, 実際に私たちのオブジェクトを構築する処理をシステムにさせることができるようになります。
Along with the above overloaded stringification, we now have a complete exception system (well, mostly complete. Exception die-hards would argue that there's no "finally" clause, and no exception stack, but that's another topic for another time).

上記のオーバーロードされた文字列化とともに, 私たちは完全な例外システムを持つことになりました (まあ, ほとんど完全。例外ダイハード (# 頑固者) は "finally" 句も, 例外スタックもないと異議を唱えるでしょうが, それはまた別のお話しです)。


単一の非キャッチ例外クラス : A Single UnCaught Exception Class



Until the Perl core gets its own base exception class (which will likely happen for Perl 6, but not sooner), it is vitally important that you decide upon a single base exception class for all of the applications that you install on your server, and a single exception handling technique. The problem comes when you have multiple applications all doing exception handling and all expecting a certain type of "UnCaught" exception class. Witness the following application:

Perl コアが独自のベース例外クラスを得るまで (これは Perl 6 でそうなるかもしれませんが, すぐではありません), あなたがあなたのサーバでインストールするすべてのアプリケーションのための単一のベース例外クラスと, 単一の例外処理テクニックをあなたが取り決めることは非常に重要です。問題はあなたの複数のアプリケーションすべてが例外処理を行ってすべてが特定の "UnCaught" 例外クラスを期待しているときときです。次のアプリケーションを見てください:

package Foo;

eval {
# 何かする (do something)
}
if ($@) {
if ($@->isa('Foo::Exception::Bar')) {
# "Bar" 例外を処理 (handle "Bar" exception)
}
elsif ($@->isa('Foo::Exception::UnCaught')) {
# 非キャッチ例外を処理 (handle uncaught exceptions)
}
}

All will work well until someone installs application "TrapMe" on the same machine, which installs its own UnCaught exception handler, overloading CORE::GLOBAL::die or installing a $SIG{__DIE__} handler. This is actually a case where using $SIG{__DIE__} might actually be preferable, because you can change your handler() routine to look like this:

誰かがアプリケーション "TrapMe" を同じマシンにインストールするまですべては上手く機能します, それは CORE::GLOBAL::die をオーバーローディングするか $SIG{__DIE__} ハンドラをインストールする, 独自の UnCaught 例外ハンドラをインストールします。これはまさに$SIG{__DIE__} を使うほうが良い実際のケースです, あなたは私たちの handler() ルーチンをこのように変更できるからです:

sub handler {
my $r = shift;

local $SIG{__DIE__};
Foo::Exception->Init(); # sets $SIG{__DIE__}

eval {
dispatch($r);
};
if ($@) {
# handle exception
}
}

sub dispatch {
my $r = shift;
...
}

In this case the very nature of $SIG{__DIE__} being a lexical variable has helped us, something we couldn't fix with overloading CORE::GLOBAL::die. However there is still a gotcha. If someone has overloaded die() in one of the applications installed on your mod_perl machine, you get the same problems still. So in short: Watch out, and check the source code of anything you install to make sure it follows your exception handling technique, or just uses die() with strings.

このケースでは $SIG{__DIE__} の性質がレキシカル変数になっていることが私たちの助けになっています, 私たちは CORE::GLOBAL::die のオーバーローディングでは何かを修正できません。しかしまだ問題があります。誰かがあなたの mod_perl マシンでインストールされたアプリケーションのひとつでオーバーロードした die() をもっていた場合, あなたはまだ同じ問題をゲットします。ですから: 気をつけて, それがあなたの例外処理テクニックに従うか, 文字列で die() を使っているだけかを確認するためにあなたがインストールするもののソースコードをチェックしてください


用途 : Some Uses



I'm going to come right out and say now: I abuse this system horribly! I throw exceptions all over my code, not because I've hit an "exceptional" bit of code, but because I want to get straight back out of the current call stack, without having to have every single level of function call check error codes. One way I use this is to return Apache return codes:

私は思い切って言うことにします: 私はこのシステムをものすごく乱用します ! 私は私のコードのいたるところで例外をスローします, 私が少し "例外的" なコードにヒットしたからではなく, 私はすべてのファンクションコールのシングルレベルでエラーコードのチェックをもっていなくても, 現在のコールスタックからすぐに戻りたいからです。私がこれで使うひとつの方法は Apache リターンコードをリターンすることです:

# パラノイドなセキュリティチェック (paranoid security check)
die My::Exception->RetCode(code => 204);

Returns a 204 error code (HTTP_NO_CONTENT), which is caught at my top level exception handler:

204 エラーコード (HTTP_NO_CONTENT) をリターンします, これは渡したのトップレベルの例外ハンドラでキャッチされます:

if ($@->isa('My::Exception::RetCode')) {
return $@->{code};
}

That last return statement is in my handler() method, so that's the return code that Apache actually sends. I have other exception handlers in place for sending Basic Authentication headers and Redirect headers out. I also have a generic My::Exception::OK class, which gives me a way to back out completely from where I am, but register that as an OK thing to do.

その最後の return ステートメントは私の handler() メソッドにありますので, それが Apache が実際に送信するリターンコードです。私は Basic Authentication (# 基本認証) ヘッダと Redirect (# リダイレクト) ヘッダを送信できるようにした他の例外ハンドラをもっています。私は汎用の My::Exception::OK クラスももっています, それはわたしがどこからでも完全に戻る方法を私にあたえますが、それを行って OK なものとしてそれを登録します。
Why do I go to these extents? After all, code like slashcode (the code behind http://slashdot.org) doesn't need this sort of thing, so why should my web site? Well it's just a matter of scalability and programmer style really. There's a lot of literature out there about exception handling, so I suggest doing some research.

なぜ私はこれほどのことをするのでしょうか ? 結局は, slashcode (http://slashdot.org の背後のコード) のようなコードはこの種のものを必要としないのに, 私のウェブサイトはなぜ ? まあそれはホントにスケーラビリティとプログラマのスタイルだけの問題です。例外処理についての文献はたくさんあるので, 私はいくらかリサーチすることをお勧めします。


結論 : Conclusions



Here I've demonstrated a simple and scalable (and useful) exception handling mechanism, that fits perfectly with your current code, and provides the programmer with an excellent means to determine what has happened in his code. Some users might be worried about the overhead of such code. However in use I've found accessing the database to be a much more significant overhead, and this is used in some code delivering to thousands of users.

ここで私はシンプルでスケーラブル (それから便利) な例外処理のメカニズムをデモンストレーションしました, それはあなたの現在のコードに完全にフィットして, 彼のコードで何が起こったかを判断するためのエクセレントな手段をプログラマに提供します。一部のユーザはそのようなコードのオーバヘッドについて心配するかもしれません。しかし私は使用中にデータベースへのアクセスがはるかに重要なオーバヘッドであることを見つけ, これは数千のユーザに配信する一部のコードで使われています。

For similar exception handling techniques, see the section "Other Implementations".

似たような例外処理テクニックは, "Other Implementations" セクションを参照してください。

My::Exception クラス全体 : The My::Exception class in its entirety




package My::Exception;

use vars qw/@ISA @EXPORT $AUTOLOAD/;
use Exporter;
@ISA = 'Exporter';
@EXPORT = qw/die/;

sub die (@);

sub import {
my $pkg = shift;
# ローカルでのみ import する "use My::Exception 'die';" を許可することを意味する
# allow "use My::Exception 'die';" to mean import locally only
$pkg->export('CORE::GLOBAL', 'die') unless @_;
Exporter::import($pkg,@_);
}

sub die (@) {
if (!ref($_[0])) {
CORE::die My::Exception->UnCaught(text => join('', @_));
}
CORE::die $_[0];

}

{
package My::Exception::UnCaught;
use overload '""' => sub { shift->{text} } ;
{

sub AUTOLOAD {
no strict 'refs', 'subs';
if ($AUTOLOAD =~ /.::([A-Z]\w+$/) {
my $exception = $1;
*{$AUTOLOAD} =
sub {
shift;
my ($package, $filename, $line) = caller;
push @_, caller => {
package => $package,
filename => $filename,
line => $line,
};
bless { @_ }, "My::Exception::$exception";
};
goto &{AUTOLOAD};
}
else {
CORE::die "No such exception class: $AUTOLOAD\n";
}
}

1;



他の実装 : Other Implementations



Some users might find it very useful to have the more C++/Java like interface of try/catch functions. These are available in several forms that all work in slightly different ways. See the documentation for each module for details:

一部のユーザはより C++/Java のようなtry/catch ファンクションのインターフェースをもつことがとても便利だと気づくかもしれません。これらはやや異なる方法ですべて機能するいくつかの形式で利用可能です。詳細は各モジュールのドキュメントを参照してください:

  • Error.pm
    Graham Barr's excellent OO styled "try, throw, catch" module (from CPAN). This should be considered your best option for structured exception handling because it is well known and well supported and used by a lot of other applications.

    Graham Barr のエクセレントな OO (# オブジェクト指向) スタイルの "try, throw, catch" モジュールです (from CPAN).これはよく知られていてよくサポートされており多くの他のアプリケーションによって使われているため構造化された例外処理であなたのベストオプションと考えられるはずです。

  • Exception::Class and Devel::StackTrace
    by Dave Rolsky both available from CPAN of course.

    Dave Rolsky によるものでもちろんどちらも CPAN から利用可能です.
    Exception::Class is a bit cleaner than the AUTOLOAD method from above as it can catch typos in exception class names, whereas the method above will automatically create a new class for you. In addition, it lets you create actual class hierarchies for your exceptions, which can be useful if you want to create exception classes that provide extra methods or data. For example, an exception class for database errors could provide a method for returning the SQL and bound parameters in use at the time of the error.

    Exception::Class は 例外クラス名でのタイプミスをキャッチするので上の AUTOLOAD メソッドよりすこしクリーンですが, 一方上のメソッドはあなたのための新しいクラスを自動的に作成します。その上で, これはあなたの例外のための実際のクラスヒエラルキーをあなたが作成できるようにします, それは追加のメソッドやデータを提供する例外クラスをあなたが作成したい場合に便利です。例えば, データベースエラーのための例外クラスはエラー時に使用していた SQL とバインドされたパラーメータをリターンするためのメソッドを提供します。

  • Try.pm
    Tony Olekshy's. Adds an unwind stack and some other interesting features. Not on the CPAN. Available at http://www.avrasoft.com/perl6/try6-ref5.txt

    Tony Olekshy のものです。アンワインドスタック (# スタックを解く) といくつか他の興味深い機能を追加します。CPAN にありません。http://www.avrasoft.com/perl6/try6-ref5.txt で利用可能です




カスタマイズされた __DIE__ ハンドラ : Customized __DIE__ handler



As we saw in the previous sections it's a bad idea to do:

私たちが前のセクションで見たようにこれをするのはバッドアイデアです:

require Carp;
$SIG{__DIE__} = \&Carp::confess;

since it breaks the error propogations within eval {} blocks,. But starting from perl 5.6.x you can use another solution to trace errors. For example you get an error:

これは eval {} ブロックでのエラー伝播をブレイクするからです,。しかし 5.6.x からあなたはエラーをトレースするための他の解決策を使えます。例えばあなたがこのエラーをゲットしたとして:

"exit" is not exported by the GLOB(0x88414cc) module at (eval 397) line 1

and you have no clue where it comes from, you can override the exit() function and plug the tracer inside:

あなたがそれがどこから来たものか見当もつかないなら, あなたは exit() ファンクションをオーバライドして内側にトレーサを差し込めます:

require Carp;
use subs qw(CORE::GLOBAL::die);
*CORE::GLOBAL::die = sub {
if ($_[0] =~ /"exit" is not exported/) {
local *CORE::GLOBAL::die = sub { CORE::die(@_) };
Carp::confess(@_); # Carp は内部で die() を使う ! (Carp uses die() internally!)
} else {
CORE::die(@_); # @_ を転送するために &CORE::die も書ける (could write &CORE::die to forward @_)
}
};

Now we can test that it works properly without breaking the eval {} blocks error propogation:

これで私たちは eval {} ブロックのエラー伝播をブレイクすることなくこれが適切に機能するかをテストができます:

eval { foo(); }; warn $@ if $@;
print "\n";
eval { poo(); }; warn $@ if $@;

sub foo{ bar(); }
sub bar{ die qq{"exit" is not exported}}

sub poo{ tar(); }
sub tar{ die "normal exit"}

prints:

出力します:

$ perl -w test
Subroutine die redefined at test line 5.
"exit" is not exported at test line 6
main::__ANON__('"exit" is not exported') called at test line 17
main::bar() called at test line 16
main::foo() called at test line 12
eval {...} called at test line 12

normal exit at test line 5.

the 'local' in:

ここでの 'local' は

local *CORE::GLOBAL::die = sub { CORE::die(@_) };

is important, so you won't lose the overloaded CORE::GLOBAL::die.

重要で, あなたはオーバーロードした CORE::GLOBAL::die を失うことはありません。


メンテナ : Maintainers



Maintainer is the person(s) you should contact with updates, corrections and patches.
  • Stas Bekman [http://stason.org/]


作者 : Authors




  • Stas Bekman [http://stason.org/]

  • Matt Sergeant



Only the major authors are listed above. For contributors see the Changes file.


NEXT



次回は、「 Documentation / General Documentation / Part II: Packaging and Testing / Preparing mod_perl modules for CPAN 」を「 mod_perl 」公式サイト (https://perl.apache.org/index.html) より確認します。


参考情報は書籍「 続・初めての Perl 改訂版 」, 「 Effective Perl 第 2 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。

目次 - Perl Index






















同じカテゴリー(Perl)の記事
 Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228) (2023-10-11 23:49)
 Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227) (2023-05-26 15:41)
 Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226) (2023-05-19 17:05)
 Perl mp2 翻訳 テンプレートシステムの選択 (d225) (2022-08-15 22:23)
 Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224) (2022-06-15 20:43)
 Perl mp2 翻訳 チュートリアル (d223) (2022-06-15 20:42)
上の画像に書かれている文字を入力して下さい
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。

Llama
リャマ
TI-DA
てぃーだブログ
プロフィール
セラ (perlackline)
セラ (perlackline)
QRコード
QRCODE
オーナーへメッセージ

PAGE TOP ▲