同じモジュールを複数回useしたときの挙動とかシンボルテーブルとか

神ネタ。もう神タグ作ろうかな。


perlではモジュールをuseすると、use元のシンボルテーブルに、そのモジュールをuseしたよっていうフラグみたいなものが付くらしい。
で、同じモジュールを複数回useしても、そのフラグを見て、既にuseされてたらuseの処理は走らない、らしい。

Mod.pm

package Mod;
use base qw/Exporter/;
use strict;
use warnings;

our @EXPORT = qw/hoge/;
sub hoge { 1 }

1;

main.pl

use strict;
use warnings;

use Mod;
sub hoge { 2 }


ここでいうと、use Modにより、main::の名前空間hogeという関数がエクスポートされる。
で、main.plの中でもhogeという関数を定義する事で、redefineな警告が出る。

% perl main.pl   
Subroutine hoge redefined at main.pl line 5.

Mod.pmを複数回useして、redefineな警告が複数回出るなら、useする度にuseの処理が走ってるってことになる、と。

main.pl

use strict;
use warnings;

use Mod;
use Mod;
use Mod;
sub hoge { 2 }
% perl main.pl  
Subroutine hoge redefined at main.pl line 7.

なるほど確かにuseの処理は1度しか走らないようだ。
んじゃuseしたフラグとやらを消してみよう。

main.pl

use strict;
use warnings;

BEGIN {
    delete $INC{q{Mod.pm}};
    use Mod;
}

use Mod;
sub hoge { 2 }
% perl main.pl  
Subroutine hoge redefined at Mod.pm line 7.
Subroutine hoge redefined at main.pl line 10.

useの処理が2回走ったようだ。BEGINとuseの処理の優先順位は分からんけど、BEGINの前にuse Mod書くと1度しか警告出ないから、えーとBEGINが先?


神ネタここまで。ここから俺ネタ。


と、ここまで書いておいて何なのだけど、複数回同じモジュールをuseしてフラグ消さない場合でも、useの処理は一部分だけ走ってんじゃね疑惑。

Mod.pm

package Mod;
use base qw/Exporter/;
use strict;
use warnings;

our @EXPORT = qw/hoge/;
sub hoge { 1 }

sub import {
    __PACKAGE__->export_to_level(1,@_);
    warn "use Mod";
}

1;

main.pl

use strict;
use warnings;

use Mod;
use Mod;
use Mod;
sub hoge { 2 }
% perl main.pl
use Mod at Mod.pm line 11.
use Mod at Mod.pm line 11.
use Mod at Mod.pm line 11.
Subroutine hoge redefined at main.pl line 7.

importは「use済みフラグ」が立っててもちゃんと実行されると。何が何やら。

続・同じモジュールを複数回useしたときの挙動とかシンボルテーブルとか

道家からコメント拝啓。毎度感謝です。

useの処理

BEGIN { require Module; import Module LIST; }

perldoc -f require

Note that the file will not be included twice under the same specified name.

同じ名前のブツは2回は展開されませんよ的。


複数回useしたらuseの処理がちゃんと複数回走る。
require Moduleは上記の通り、2回目以降は働かない模様。
importは普通に走る。
以上。何も問題なし。

で、何でそんなネタを調べていたのか

オレオレActiveRecordが、同じモジュールを複数回useするというか、循環参照する作りになってしまっていて動かないとき、神にその部分を遅延評価するようにして動くように修正してもらったのだけど、
「何で2回useして問題にならないんだろう」と疑問に思ったのがきっかけ。

その後は
特定のモジュールだけ書き換えたときにそのモジュールだけ再読み込みしたいときのあれこれ
とか
catalystのserver.plのリスタートの仕組みが想像と違ってた
とかを話してますた。

@cpan.org充てのメール

cpan authorになってから、cpanに登録してるアドレスにちらほらメールが来るようになった。
cpanに載ってるアドレス自体はただのエイリアスではあるけれど、届くのには変わりない。
で、困ったのが、届くメールは今のところ全て英語なので、cpan的なメールなのかスパムなのかの判断をつけづらい。
cpanな内容かスパムな内容かはちゃんと読めば分かるのだけど、長文メールとか「明らかにスパムっぽいけどもしかしたらcpan的なメールかもしれない」のがめどい
今のところcpan的な内容とスパムなのはちゃんと振り分けされて、スパムだけ迷惑メールフォルダに入ってるけど、それらも一応全部見る。めどい。だって万が一cpanの重要なメールだったら困るし。


cpan的な内容のメールだったとしても返信書くのに一苦労するわけだけど。
言ってる意味は分かっても英語的なニュアンスとかまで分からんからアレコレ説明して返事作るし。
「誤解していたら申し訳ありません、こういう意味でよろしいですか?」的な。yahoo翻訳万歳。
今日も返信したけど疲れた。