Home > Perl > Perl の use と require の違い

Perl の use と require の違い

  • 2005-12-05 (月)
  • Perl
  • このエントリーを含むはてなブックマーク

以前飲み会で、会社の先輩と「use と require の違いってなんじゃ?」てな話をした際、知識不足ゆえうまく答えが出せなかったのですが、Programming Perl 等をちょろちょろ読み始めた今なら、ちょっとはマシな回答が出来る気がした /w のでまとめてみました。

目次:

use と require の違い

perldoc を始め、色々なサイトや書籍でも既に述べられているとおり、

use はコンパイル時に評価される - module load happens at comile time.
require は実行時に評価される - module load happens at run time.

が明確な違いになります。また、 perldoc(*) によると use は実際には以下のコードを実行するのと同等だそうです :

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

特殊ブロック BEGIN で括る = コンパイル時に評価される事に加え、

use はロードしたモジュールの import 関数を実行している

点も明確な違いになりますね。では以上2点の違いをもう少し具体的に説明してみます。

*perldoc での記述箇所例) $ perldoc perlmod → Perl Modules の章 (/use Module でsearchするべし)

▲RETURN TO TOP

メモリロードのタイミングが違う

use の場合はコード中のどんな場所に宣言があろうが、すべての対象モジュールを、コンパイル時にメモリにロードします。片や require の方は、実際に require 文が実行されるタイミングになって、初めて対象モジュールをメモリにロードします。以下サンプルコード:

if($needs == 1){
require "Hoge.pm"; # $needsが1だった場合のみメモリにロードされる
use Hoge; # $needsの値に関係なく、コンパイル時にメモリにロードされる
}

てな違いになります。require は条件文で true になった場合にロードされるのに対し、use の場合は条件文に入る前から既にロードされている事になります。この違いを理解したうえで、うまく使い分ければ、例えば

必要性が実行時まで不明確なモジュールは require で読み込む事により、ソース全体の起動時のオーバーヘッドを減らす事が可能

だったり、

子プロセスを fork していくようなコードの場合は use を使うことにより、効率的なメモリ使用による全体効率の向上が可能

だったりします。※後者の話は second life 氏の LLDN 記事や naoya 氏の Perl の use と mod_perl、あと LLDN 感想ちょっと。 記事辺りで miyagawa氏を交えて詳しく語られています。

▲RETURN TO TOP

特殊ブロックの挙動が違う

モジュールの中では、コンパイル時に実行される特殊なブロック - BEGIN, CHECK, INIT - を記述しておくことが出来ますが、use と require ではこれらの実行タイミング、及び実行有無がそれぞれ異なります。

use の場合

  1. BEGIN
  2. CHECK
  3. INIT     --- 3種すべてコンパイル時に実行

require の場合

  1. BEGIN - メモリロードされたタイミングで実行
  2. CHECK - 無視される
  3. INIT - 無視される

以下、これらブロックが記述されたモジュール UseReq を使ったサンプルコードを書いてみました:

UseReq.pm

package UseReq;
use strict;
INIT { print "UseReq init\n" }
BEGIN { print "UseReq begin\n" }
CHECK { print "UseReq check\n" }
sub hoge { print "hoge called\n" }
1;

use の場合

#!/usr/bin/perl
print "--- script start ---\n";
use UseReq;
UseReq::hoge(); ### 実行結果 ##### $ ./use.pl UseReq begin
UseReq check
UseReq init
--- script start ---
hoge called

各種特殊ブロック実行 → コード実行 の順番になっています。

reqiure の場合

#!/usr/bin/perl
print "--- script start ---\n";
require 'UseReq.pm';
UseReq::hoge(); ### 実行結果 ##### $ ./req.pl --- script start ---
UseReq begin
hoge called

require の場合、INIT と CHECK ブロックは実行されず、かつ 全体コード実行 → require 評価時点で BEGIN 実行 の順番になっています。

※なお END, DESTROY ブロックについては違いは無い模様。

▲RETURN TO TOP

Exporter の利用可・不可の違い

2つ目の違いとして挙げた

use はロードしたモジュールの import 関数を実行している

点について、use と require の違いがもっとも判りやすい例が Exporter だと思います。Exporter モジュールが何をするものかは perldoc を参照してもらうとして、両者の違いは何かと言うと、

use → Exporter による関数インポートが利用可能
require → 利用不可

という事になります(単純)。サンプルコードでこの事を表すと以下のようになります:

UseReq.pm

package UseReq;
use base Exporter;
use strict;
our @EXPORT_OK = qw(hoge);
sub hoge { print "hoge called\n" }
1;

use の場合

#!/usr/bin/perl
use UseReq qw(hoge);
hoge();
### 実行結果 ### $ ./use.pl hoge called

require の場合

#!/usr/bin/perl
require 'UseReq.pm';
hoge();
### 実行結果 ###
$ ./req.pl
Undefined subroutine &main::hoge called at ./usereq.pl line 3.

require の場合だと Exporter モジュールの import 関数が自動実行されない為、関数インポートができていませんね。require しつつ Exporter を使いたい場合は、require 宣言の直後に自分で import 関数を実行する必要があります:

#!/usr/bin/perl
require 'UseReq.pm';
UseReq->import('hoge');
hoge();
### 実行結果 ###
$ ./req.pl
hoge called

▲RETURN TO TOP

以上、長くなってしまいましたが、こんな感じにまとめてみました。... ゆうごさん (先輩) どうでしょうか?

Comments:0

Comment Form

コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。

Remember personal info

Home > Perl > Perl の use と require の違い

Search
Feeds

Page Top