同じモジュールを複数回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済みフラグ」が立っててもちゃんと実行されると。何が何やら。