require

実行時にライブラリーから外部関数をロードする

require には、Perl 本体のバージョン番号を指定して該当の Perl プログラムがそれより以前のバージョンで動作しないようにする機能、 そして、引数に指定したモジュールをロードする機能の 2 つの役割があります。

Perl バージョンを指定する

構文

  • require VERSION

解説

require VERSION 構文の場合は、Perl のバージョンが VERSION に指定したバージョン以上であることを要求します。 もし VERSION が現在の Perl インタプリタのバージョンより大きい場合は例外が投げられます。

VERSION には v5.24.1 のようなリテラルを指定することができます。 これは $^V (または、English$PERL_VERSION) にセットされている値の形式と同じです。

VERSION には 5.024001 のような形式の数値で指定することもできます。 これは $] にセットされている値の形式と同じです。 しかしこういった形式の数値を VERSION に指定するのは一般的には避けるべきです。 なぜなら、v5.24.1 という表記と比べて、古くて読みづらい構文だからです。 2002 年にリリースした Perl 5.8.0 より前では、もっと冗長な数値形式しか構文としてサポートされていませんでした。 そのため、次のようなコードを見たことがあるかもしれません。

require v5.24.1;    # 推奨の形式
require 5.24.1;     # 先頭に v がないが許されている
require 5.024001;   # 読みづらいので非推奨
require 5.024_001;  # Perl 5.6 時代の古い構文なので、現在は非推奨

モジュールをロードする

構文

  • require EXPR
  • require

解説

require EXPR 構文は、モジュールファイルを現在のスクリプトに組み込みます。 EXPR が省略された場合は $_ が適用されます。 同じファイルを指定している限り、何度 require を実行しても、最初の 1 度しか読み込まれません。

歴史的に、モジュールファイルは初期化コードの実行が成功したことを示すために、最後のステートメントで true を返さなければいけません。 一般的にはモジュールファイルの最後を 1; とすることが慣例になっています。 しかし、Perl 5.37.6 以降なら、use feature 'module_true'; とすれば 1; は不要です。 または、use v5.37; でも 1; を書かなくても良くなります。

EXPR がベアワードなら、require は、EXPR の値からモジュールファイルを検索します。 次の例を使って、モジュールファイルの検索方法を解説します。

use Foo::Bar;

このモジュールのファイルを検索する際に、まずモジュールのファイル拡張子は .pm だと仮定します。 次に EXPR の値の中に :: が存在すれば、それを / に置換します。 もし EXPRFoo::Bar なら、Foo/Bar.pm になります。

次に特殊変数 @INC の中にセットされているパスを最初から順に走査します。 もし @INC('/usr/share/perl5', '/usr/local/lib/site_perl') だったとすると、次の順にファイルを探すことになります。

/usr/share/perl5/Foo/Bar.pm
/usr/local/lib/site_perl/Foo/Bar.pm

このように @INC のディレクトリパスを検索対象にすることから、 EXPR にベアワードを指定する方法は主に標準モジュールをロードしたい場合に使われます。

しかし、Foo::Bar を文字列として指定すると、それはファイルパスとみなされるため、上記の変換は行われません。

my $class = 'Foo::Bar';
require $class;       # $class はベアワードではない
#または
require "Foo::Bar";   # "" を使っているためベアワードではない

もし、どうしても文字列で指定したいなら、次のように eval を使います。

eval "require $class";

または、該当のモジュールのファイルパスを指定します。 この場合でも前述の @INC のディレクトリパス検索は有効です。

require "Foo/Bar.pm";

以上、require がベアワードの引数からどうやってファイルを探すのかを解説しましたが、 裏で進行している機能がもう少しあります。 require は、拡張子 .pm を探す前に、拡張子が .pmc のファイルを検索します。 このファイルが見つかれば、拡張子 .pm のファイルの代わりに、それをロードします。 これは、明示的な require "Foo/Bar.pm"; の形式と require Foo::Bar; の形式の両方に当てはまります。

userequire の違い

userequire はいずれもモジュールをロードする役割を持ちます。 しかし、それぞれ異なる点があります。

もっとも大きな違いは、モジュールをロードするタイミングです。 use はコンパイル時に処理されます。 一方、require はスクリプトの実行時に処理されます。 この違いは、状況によってモジュールをロードするかを決定したい場合に問題となります。 もしそうしたい場合は、require を使います。 require は実行時にモジュールを読み込むため、if などのフロー制御が効きます。

if ( $^O eq 'MSWin32' ) {
    require './MyPackage.pm';
}

もし、ここで require の代わりに use を使うと、 コンパイル時に処理されてしまうため、if の存在に関わらず、モジュールをロードしようとします。

次に、userequire の違いとして大きいのは、 use は読み込むモジュールに import 関数があれば、 それを呼び出す点です。requireimport 関数を呼び出しません。

import 関数は、多くのモジュールで Exporter が使われています。 これは、モジュールが提供する変数や関数を、呼び出し元の名前空間にインポートします。 たとえば、Foo::Bar モジュールに do_something という関数が実装されていたとしましょう。 本来なら、そのメソッドを呼び出す際には、Foo::Bar::do_something() のように名前空間も含めた完全修飾名でコードに書く必要があります。 しかし、Exporter によって、あたかも自身の関数であったかのように do_something() で呼び出すことができます。 次のコードは、File::Copy の例です。

use File::Copy;
copy( 'orig.txt', 'copy.txt' );

このコードでは use を使って File::Copy をロードしたため、 File::Copy の copy 関数が呼び出し元の名前空間にインポートされます。 そのため、完全修飾名をコードに書く必要がありません。

一方、もし File::Copy を require でロードすると、 copy 関数は完全修飾しないと呼び出すことができません。

require File::Copy;
File::Copy::copy( 'orig.txt', 'copy.txt' );

また、requireeval でモジュールが見つからなかった場合の処理を書くことが可能です。

eval { require Foo::Bar; };
if ($@) {
    print "Foo::Bar が見つかりませんでした: $@\n";
}

use では、コンパイル時にモジュールをロードしようとするため、 これを実現することはできません。 use の場合、もしモジュールが見つからなければ例外が投げられてしまい、 強制的にスクリプトは終了してしまいます。