Perl Perl_6
Perl モジュール Exporter 00 use, import (d089)

目次 - Perl Index
Theme
Perl について、復習を兼ねて断片的な情報を掲載して行く連載その d089 回。
Perl で、サブルーチンを呼び出し元にエクスポートするためのモジュール「 Exporter 」を確認する。
今回は、モジュール「 Exporter 」の動作を理解するために、サブルーチン「 import() 」を確認します。
use
Perl で外部モジュールやプラグマを読み込む場合に利用する「 use 」を改めて確認します。
「 use 」は、(d001) や (d057) で確認したとおり「 BEGIN 」(d066) と「 require 」を使った文と等価な処理を行います。
use Module List;
# exactly equivalent to
BEGIN {
require Module;
Module->import( LIST );
}
BEGIN ブロックの require では裸の単語 ( bareword ) で「 Module 」を指定していますが、これにより require はカレントまたは「 @INC 」のディレクトリからサフィックスが「 .pm 」のファイル、つまり「 Module.pm 」を探し出します (d000)。
この動作は、use に裸の単語でモジュール名を指定することと同じです。
それから、読み込んだ Module を使ってメソッド「 import() 」を呼び出しています。
今回はこの「 import() 」を少し詳しく確認します。
import()
前項で「 import() 」を "メソッド" と呼びましたが、実際には単なるサブルーチンです。
use - perldoc で解説されているように、import() は Perl 組み込みの関数ではなく、ユーザが必要に応じて定義するものです ( see import )。
import() の役割は、モジュール側からモジュールを利用するパッケージに対して特定の機能 ( サブルーチンや変数 ) をインポートすることです。
import() によってインポートされた機能は、あたかもそのパッケージで定義された機能かのように扱うことができます。
なお、モジュール側に import() が用意されていない場合は、たとえメソッド「 AUTOLOAD() 」(d086) が定義されていたとしても use は import() の呼び出しをスキップするそうです。
import() を定義する
サブルーチン「 import() 」の動作を確認するために、名前 ( name ) を set/get するモジュール ( package ) 「 People.pm 」を定義してみます。
package People;
use strict;
use warnings;
sub import {
# 呼び出し元のパッケージ名をセット
my $package = caller;
# シンボリックリファレンス ( 型グロブ ) を操作する
no strict 'refs';
# 呼び出し元のパッケージにインポート
for (qw( set_name get_name )){
*{$package. "::$_"} = \&$_;
# or
#*{"$package\::$_"} = \&$_;
}
}
# アトリビュートを無名ハッシュレフで格納するためのスカラ
my $atr = {};
# 名前をセットするサブルーチン
sub set_name {
my $name = shift;
$atr->{Name} = $name;
}
# 名前をゲットするサブルーチン
sub get_name {
if ($atr->{Name}){
$atr->{Name};
}else{
"Please use set_name() first";
}
}
このモジュールは、27 行目の「 set_name() 」と 32 行目の「 get_name() 」を、6 行目の「 import() 」を使って呼び出し元のパッケージにインポートします。
import() 内ではまず、組み込みの関数「 caller 」で呼び出し元のパッケージ名を取得し、それを「 $package 」にセットします ( 9 行目 )。
それから $package を set_name と get_name の名前とともに利用して、呼び出し元のパッケージの名前空間にセットします ( 16 行目 )。
名前空間へのセットは、「 アクセサの自動生成 」 (d088) でも確認した型グロブを応用したテクニックを利用しています。
import() の動作を確認する
「 import() 」の動作を確認するために、前項の People.pm と同じディレクトリに「 people.pl 」を作成します。
people.pl のコードは次のものです。
#!/usr/bin/perl
use strict;
use warnings;
use People;
# People.pm のサブルーチンを実行する
# 名前をセット
set_name('Bellri');
# 名前をゲット
my $name = get_name();
print "That name is $name\n";
サブルーチン「 set_name() 」と「 get_name() 」の定義はどこにもありませんが、「 use 」が呼び出す「 import() 」の機能によってプログラムは問題なく動作します。
That name is Bellri
use の代わりに BEGIN と require を使っても同じ結果を得られます。
# use People;
BEGIN {
require People;
People->import();
}
変数名をインポートする
例えば「 import() 」を次のように書き換えれば、呼び出し元のパッケージに対して任意の変数もセットできます。
# in People.pm
my $modules_scalar = 'Hello';
my @modules_array = qw/one two three/;
my %modules_hash = (key => 'val');
sub import {
my $package = caller;
no strict 'refs';
# 変数をセット
*{$package. "::modules_scalar"} = \$modules_scalar;
*{$package. "::modules_array"} = \@modules_array;
*{$package. "::modules_hash"} = \%modules_hash;
# サブルーチンをセット
for (qw( set_name get_name set_age get_age )){
*{$package. "::$_"} = \&$_;
}
}
これを people.pl で use します。
#!/usr/bin/perl
use strict;
use warnings;
use People;
# 外部の変数
print "scalar: $modules_scalar\n";
print "array : @modules_array\n";
print "hash : $_ : $modules_hash{$_}\n" for keys %modules_hash;
print "---\n";
# 外部のサブルーチン
set_name('Bellri');
my $name = get_name();
print "That name is $name\n";
変数「 $modules_scalar 」, 「 @modules_array 」, 「 %modules_hash 」の定義はどこにもありませんが、プログラムは問題なく動作します。
scalar: Hello
array : one two three
hash : key : val
---
That name is Bellri
なお、「 続・始めての Perl 改訂版 」( P.197 脚注 ) によれば、このように変数を呼び出し元にインポートすることはサブルーチンのそれに比べてまれなことであり、おそらくすべきではないことと解説されています。
Exporter
ここまでで確認した「 import() 」の処理は「 呼び出し元に任意の機能を *インポート* する 」ものでしたが、同じ処理をモジュール側からみると「 呼び出し元へ任意の機能を *エクスポート* する 」ものと言えます。
Perl には、こうした「 エクスポート 」( export ) の処理を一括して担うスタンダードなコアモジュール「 Exporter 」が用意されています。
NEXT
次回は、モジュール「 Exporter 」を確認します。
参考情報は書籍「 続・初めての Perl 改訂版 」, 「 Effective Perl 第 2 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。
目次 - Perl Index
Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)
Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227)
Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226)
Perl mp2 翻訳 テンプレートシステムの選択 (d225)
Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224)
Perl mp2 翻訳 チュートリアル (d223)