Perl Quiz - 解説

解答一覧(敬称略)

パッケージの「名前」について

mattn氏,fbis氏,hakobe932氏が解答してくれたのが今回のPerl Quizの動機なので,解説します。
まず以下のコード:

#!perl -w
{
  package Foo;
  package ::main::Bar;
}
print ref(bless {}, '::Foo');           # => "Foo" (1)
print ref(bless {}, 'main::main::Foo'); # => "Foo" (2)
print ref(bless {}, 'Bar');             # => "::main::Bar" (3)
__END__

Perlはパッケージ名の先頭の"::"を無視するので,"::Foo"という名前でブレスしても実際にブレスされるのはパッケージ"Foo"です。また,"main::"についても同様で,パッケージ名の先頭にいくつ"main::"が付いていようと全て無視されます。
さてここで,同一パッケージであってもプログラムによっては異なる名前を持つことがあります。これは,最初に参照した名前がそのパッケージの名前となるためです*1。それを示すのが(3)です。Barパッケージは確かにBarパッケージとして存在しますが,最初に参照したのが"::Bar"という名前なので,Barパッケージの名前は"::main::Bar"です。しかしその実体はBarパッケージであることに違いはなく,"Bar"という名前でブレスすると,"Bar"と"::main::Bar"が同一パッケージであるということが分かります。
このような仕様のため,ref(bless {}, 'Foo')と'Foo'がいつも真になるとは限らないのです。
なお,UNIVERSAL::isa()はこのあたりの事情を酌んでくれるので,通常はこの仕様が問題になることはありません。

*1:perl5.10.0の場合,gv.cのPerl_gv_stashpvn()におけるhv_name_set()の呼び出しで名前が設定される。