ついでなので、perlのpackageについて。
odz buffer - Perl は 1ファイルに複数のパッケージを書けるはず・・・違いますよ、と突っ込もうと思ったけど、自信がないので確認(おぃ)。
Perl5におけるpackageというのは、単なるnamespaceの宣言に過ぎず、それ以上でもそれ以下でもありません。package Foo;というのは、「このlexical scopeにおけるnamespaceはFooである」という宣言なのです。なので、
ちなみに HTTP::Proxyの SYNOPSIS なんかみると、
{
package FilterPerl;
use base qw( HTTP::Proxy::BodyFilter );
# snip
}
な感じでブロック中でクラス定義してたりする。なぜかは知らない。
というのは、{}の中のみがFilterPerlという意味になります。これは以下を見ればすぐにわかるでしょう。
use strict;
use warnings;
{
package Foo;
warn __PACKAGE__;
}
warn __PACKAGE__;
package Baz;
warn __PACKAGE__;
package main;
warn __PACKAGE__;
実行すると、
Foo at pkg.pl line 5. main at pkg.pl line 7. Baz at pkg.pl line 9. main at pkg.pl line 11.
となります。元来packageというのはファイルとは関係なしに存在する概念なのです。
ただし、require Foo::Barおよびuse Foo::Barでは、様相が少し違います。この二つにおいては、「Foo/Bar.pmというファイルがロードされていなければ、@INC中のDirectoryにFoo/Bar.pmにそれを探しに行く」という意味になります。ロードされているかどうかという判定は、$INC{'Foo/Bar.pm'}が存在するかでなされます。
% perl -le 'print "$_ => $INC{$_}" for keys %INC'
% perl -MCGI -le 'print "$_ => $INC{$_}" for keys %INC'
warnings/register.pm => /usr/local/lib/perl5/5.8.8/warnings/register.pm
Carp.pm => /usr/local/lib/perl5/5.8.8/Carp.pm
vars.pm => /usr/local/lib/perl5/5.8.8/vars.pm
strict.pm => /usr/local/lib/perl5/5.8.8/strict.pm
Exporter.pm => /usr/local/lib/perl5/5.8.8/Exporter.pm
constant.pm => /usr/local/lib/perl5/5.8.8/constant.pm
warnings.pm => /usr/local/lib/perl5/5.8.8/warnings.pm
CGI/Util.pm => /usr/local/lib/perl5/5.8.8/CGI/Util.pm
overload.pm => /usr/local/lib/perl5/5.8.8/overload.pm
CGI.pm => /usr/local/lib/perl5/5.8.8/CGI.pm
よって、use Foo::Barは、実はpackage Foo::Barとは関係ないのです。以下も問題なく動いてしまいます。
% cat Foo/Bar.pm
package Baz;
warn __PACKAGE__;
1;
% perl -MFoo::Bar -le 'print "$_ => $INC{$_}" for keys %INC'
Baz at Foo/Bar.pm line 2.
Foo/Bar.pm => Foo/Bar.pm
もっとも、これではわかりにくいので、たいていの場合はFoo/Bar.pmの最初にpackage Foo::Bar;という宣言を入れておくわけです。
一見非直感的ですが、これのおかげでこんな技も使えます。
Dan.pm
use strict;
use warnings;
use utf8; # これを宣言しておく必要あり
package 小飼;
sub 弾 {
my $クラス = shift;
bless { @_ }, $クラス
};
for my $メソッド (qw/空気/){
no strict 'refs';
*{$メソッド} = sub{
my $俺 = shift;
$俺->{$メソッド} = shift if @_;
$俺->{$メソッド};
};
};
1;
dan.pl
use strict;
use warnings;
use utf8;
use Dan;
use Data::Dumper;
binmode STDOUT => ':utf8';
sub say { print @_, "\n" };
my $私 = 小飼->弾('空気' => '嫁');
warn Dumper $私;
say $私->空気;
1;
% perl dan.pl
$VAR1 = bless( {
"\x{7a7a}\x{6c17}" => "\x{5ac1}"
}, '小飼' );
嫁
Dan the Perl Monger
例えば、
Foo/Baa/Multi/Complexed/Functions/Lasy.pm内において
--
package Foo::Baa::Multi::Complexed::Functions::Lasy;
〜
何かめんどくさいこと
〜
...
package FBMCFL;
@ISA = qw( Foo::Baa::Multi::Complexed::Functions::Lasy );
1;
--
とかやって、
package mainでは
use Foo::Baa::Multi::Complexed::Functions::Lasy;
my $o = FBMCFL->new();
みたいな書き方実際にしてたんですが、弾さんはこれを許容しますか?