正しい use の使い方

.pm 散策をすると、入門書には書いてない use の使い方がたくさんでてきます。man perlfunc をてがかりに use の正しい使い方について勉強しましょう。man perlfunc で引くと次のように use の記法の4つのバリエーションが書いてあります。

       use Module LIST

       use Module

       use Module VERSION LIST

       use VERSION

use Module LIST が一般的な使い方です。これば次のような文と同じことになります。

       BEGIN { require Module; import Module LIST; }

上の文では、先ず Module を読み込んだ後、import 関数に Module LIST が渡されて実行されます。import 関数は組み込みの関数ではなく、Module 側で記述しなければなりません。テスト用に次のモジュールを Use_sample.pm という名前で作成します。

package Use_sample;

sub import {
    my $package = shift;
    my $a = shift;
    $a = ( $a ? $a : 'hello' );
    ${"${$package}::imported"} = $a;
}
1;

簡単に説明すると、import 関数の$packageには、use を使って Use_sample.pm を呼び出した側のパッケージのパッケージ名が入ります。$a は use Use_sample LIST; と記述されたときのリスト(この例では引数が1個の場合を想定しているのでスカラーになります)の値です。$a に引数が渡されていれば $a のまま、引数がない場合は $a = 'hello' となります。

use Module LIST という呼び出し方をすると、Module の import 関数に LIST が引き渡されます。次のようなテストプログラムを test_use_2.pl と言う名前で作成します。

#!/usr/bin/perl
use Use_sample 'Hi';
print "$imported\n";

test_use_2.pl を走らせると 'Hi' が import 関数に引き渡され $imported 変数の値が 'Hi' になって表示されます。

$ perl test_use_2.pl 
Hi

つぎに import 関数に引数を渡さない test_use_1.pl スクリプトを作成します。

#!/usr/bin/perl
use Use_sample;
print "$imported\n";

test_use_1.pl では、import 関数に引数が渡されないので $imported の値は 'hello' になります。

$ perl test_use_1.pl
hello

Module を読み込んでも import 関数を動かしたくない場合は、明示的に use Module(); とします。次の test_use_0.pl がその例です。

#!/usr/bin/perl
use Use_sample();
print "$imported\n";

この場合 import 関数が呼び出されないので $import は空になります。

$ perl test_use_0.pl

例として、標準パッケージの vars のコード部分は次のようになります。

package vars;

require 5.002;

# The following require can't be removed during maintenance
# releases, sadly, because of the risk of buggy code that does
# require Carp; Carp::croak "..."; without brackets dying
# if Carp hasn't been loaded in earlier compile time. :-(
# We'll let those bugs get found on the development track.
require Carp if $] < 5.00450;

sub import {
    my $callpack = caller;
    my ($pack, @imports, $sym, $ch) = @_;
    foreach $sym (@imports) {
        if ($sym =~ /::/) {
            require Carp;
            Carp::croak("Can't declare another package's variables");
        }
        ($ch, $sym) = unpack('a1a*', $sym);
        *{"${callpack}::$sym"} =
          (  $ch eq "\$" ? \$   {"${callpack}::$sym"}
           : $ch eq "\@" ? \@   {"${callpack}::$sym"}
           : $ch eq "\%" ? \%   {"${callpack}::$sym"}
           : $ch eq "\*" ? \*   {"${callpack}::$sym"}
           : $ch eq "\&" ? \&   {"${callpack}::$sym"}
           : do {
                require Carp;
                Carp::croak("'$ch$sym' is not a valid variable name\n");
             });
    }
};

1;

vars.pm では import メソッドだけが記述されています。したがって、グローバル変数を導入する use vars <変数のリスト> というのは組み込みの関数ではなくて、普通に use を使ってモジュールを導入しただけだということが分かります。

use の最初の引数がモジュール名ではなくて Perl のバージョンナンバーの場合、そのパッケージを利用する Perl のバージョンがそれより旧い場合はエラーメッセージが出てスクリプトの実行が強制終了されます。

use 5.003_90;

また use Module VERSION LIST と、Module と LIST の間にバージョンナンバーが入っている場合、use は Module の VERSION メソッドにバージョンナンバーを渡して実行します。デフォールトでは Module の $Module::VERSION 番号よりバージョンナンバーが大きかった場合、プログラムはエラーとなって強制終了されます。