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_6

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

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)の記事
 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 ▲