autobox - 組み込み型をファーストクラスオブジェクトとして利用
use autobox;
# call methods on builtin values and literals
# 組み込みの値やリテラルからメソッド呼び出し
# integers
# 整数
my $range = 10->to(1); # [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]
# floats
# 浮動小数点数
my $error = 3.1415927->minus(22/7)->abs();
# strings
# 文字列
my $uri = 'www.%s.com/foo.pl?arg=%s'->f($domain, $arg->escape());
my $links = 'autobox'->google();
my $word = 'rubicund';
my $definition = $word->lookup_on_dictionary_dot_com();
my $greeting = "Hello, World"->upper(); # "HELLO, WORLD"
$greeting->to_lower(); # greeting is now "hello, world"
$greeting->for_each(\&character_handler);
# ARRAY refs
# 配列リファレンス
my $schwartzian = [ @_ ]->map(...)->sort(...)->map(...);
my $sd = [ 1, 8, 3, 3, 2, 9 ]->standard_deviation();
# HASH refs
# ハッシュリファレンス
{ alpha => 'beta', gamma => 'vlissides' }->for_each(...);
# CODE refs
# CODE リファレンス
my $plus_five = (\&add)->curry()->(5);
my $minus_three = sub { $_[0] - $_[1] }->reverse->curry->(3);
# can() and isa() work as expected
# can(), 及び isa() は想定通りに動作します
if ("Hello, World"->can('foo')) ...
if (3.1415927->isa('SCALAR')) ...
autobox プラグマは Perl の組み込み型にファーストクラスオブジェクト としての能力を賦与します. これは ARRAY, HASH, CODE リファレンスや 生のスカラーからブレスされたリファレンスと全く同じようにメソッドを 呼べることを許可します. autoboxは透過的に行われます: autoboxされた 値は(ユーザが定義した)実装クラスにブレスされることはありません( メソッドがブレスのようななにかを与えることを選ぶことなしに) - それにもかかわらず単純にそのメソッドを利用します.
autobox はレキシカルスコープにあり, 外部のスコープのハンドラ(後述)は 内側のスコープで上書き又は取り消すことができます.
{
use autobox; # default handlers
...
{
use autobox SCALAR => 'MyScalar';
...
}
# back to the default
...
}
autobox化は no 構文を使うことで完全に解除できます:
{
use autobox;
...
no autobox;
...
}
- undef を単独でデフォルトの値に指定しても同様です(後述):
use autobox DEFAULT => undef;
autobox化は裸の単語(bareword)には影響しません, すなわち,
my $foo = Foo->new();
及び:
my $foo = new Foo;
は思った通りに振る舞います.
加えて, 名前付きのメソッドのみを対象とします, つまりこれは動作しますが:
my $foobar = { foo => 'bar' }->some_method();
これは動作しません:
my $method1 = 'some_method';
my $method2 = \&HASH::some_method;
my $error1 = { foo => 'bar' }->$method1();
my $error2 = { foo => 'bar' }->$method2();
コアタイプがbox化されるクラスは完全に設定可能です. デフォルトでは オブジェクトではない値から呼び出されるメソッドは, その値の ref() と対応するパッケージ名か, リファレンスでなければ 'SCALAR' です.
すなわち標準的な:
use autobox;
は以下のデフォルトハンドラを(現在のレキシカルスコープに対して) 登録します:
{
SCALAR => 'SCALAR',
ARRAY => 'ARRAY',
HASH => 'HASH',
CODE => 'CODE'
}
これにより:
"hello, world"->upper()
は以下の呼び出しとなります:
SCALAR::upper("hello, world")
さらに:
[ 1 .. 10 ]->for_each(sub { ... })
は以下となります:
ARRAY::for_each([ 1 .. 10 ], sub { ... })
組み込み型からユーザ定義クラスへのマッピングは
use autobox 文へキー/値バインディングのリストを渡すことで
指定できます.
以下の例では有効な引数の範囲を示します:
use autobox SCALAR => 'MyScalar' # package name
ARRAY => 'MyNamespace::', # package prefix (ending in '::')
HASH => '', # use the default i.e. HASH
CODE => undef, # don't autobox this type
UNDEF => ..., # can take any of the 4 types above
DEFAULT => ..., # can take any of the 4 types above
DEBUG => ...; # boolean or coderef
SCALAR, ARRAY, HASH, CODE, UNDEF そして DEFAULT は4種類の値を取ることが 出来ます:
パッケージ名, 例えば:
use autobox SCALAR => 'MyScalar';
これはデフォルトのパッケージ - この場合には SCALAR を上書きします. リテラル若しくは組み込み型 'key' での全てのメソッド呼び出しは 'value' に対応して指定されたパッケージのメソッドとして配送されます.
もしパッケージ名が DEFAULT に対して提供されたのなら, 全ての処理されて いない部分のデフォルトのパッケージになります. すなわち:
use autobox ARRAY => 'MyArray',
DEFAULT => 'MyDefault';
は ARRAY メソッドを MyArray で呼び出し, それ以外を MyDefault で 呼び出します.
名前空間: これはこのタイプに対するデフォルトのハンドラ名が付与される パッケージのプレフィックスになります(末尾の '::' までを含みます):
すなわち:
use autobox ARRAY => 'Prelude::';
は ARRAY タイプを Prelude::ARRAY パッケージに束縛します.
パッケージ名と同時に, デフォルトの名前空間を指定することで, 例えば,
use autobox SCALAR => 'MyScalar',
DEFAULT => 'MyNamespace::';
は, MyNamespace::ARRAY, MyNamespace::HASH &c. を対応する組み込み型に 束縛します.
空の文字列: これは組み込み型の名前の短縮表現です, 例えば,
use autobox SCALAR => 'MyScalar',
ARRAY => '',
DEFAULT => 'MyDefault::';
は以下と等値です:
use autobox SCALAR => 'MyScalar'
ARRAY => 'ARRAY',
DEFAULT => 'MyDefault::';
そしてこれは以下と等値です:
use autobox SCALAR => 'MyScalar'
ARRAY => 'ARRAY',
HASH => 'MyDefault::HASH',
CODE => 'MyDefault::CODE';
もし DEFAULT に空の文字列が設定されると(それはデフォルトなので), 全ての処理されていない箇所をデフォルトの型で埋めます, 例えば,
use autobox SCALAR => 'MyScalar',
CODE => 'MyCode',
DEFAULT => '';
は以下と等価です:
use autobox SCALAR => 'MyScalar',
CODE => 'MyCode',
ARRAY => 'ARRAY',
HASH => 'HASH';
undef: これは指定した型, もしくは DEFAULT の時には全ての指定していない 型に対して autobox を無効にします.
これまでに述べた SCALAR, ARRAY, HASH, CODE そして DEFAULT の オプションに加えて2つのオプション, UNDEF 及び REPORT があります.
仮想型, UNDEF, は未定義値の autobox に利用されます. これはデフォルトでは autobox されません (すなわちデフォルトは undef です):
これは動作しません:
use autobox;
undef->foo() # runtime error
これなら動作します:
use autobox UNDEF => 'MyPackage';
undef->foo(); # ok
そしてこれも動作します:
use autobox UNDEF => 'MyNamespace::';
undef->foo(); # ok
DEBUG は現在のハンドラをコールバック若しくは静的なレポート関数 で露出させます.
これは手書きで算出された束縛を見たい人には便利です.
デバッグは DEBUG キーに対応する値が偽であれば無視されます.
値が CODE リファレンスであればその関数が現在のスコープに対して 算出されたハンドラを含んだハッシュへのリファレンスを伴って 呼び出されます.
そして最後に, DEBUG が真で且つ CODE リファレンスでなければ, ハンドラは 標準エラーにダンプされます.
すなわち:
use autobox DEBUG => 1, ...
若しくは
use autobox DEBUG => sub { ... }, ...
若しくは
sub my_callback ($) {
my $hashref = shift;
...
}
use autobox DEBUG => \&my_callback, ...
Perl の優先順位のために幾つかの autobox リテラルは括弧でくくる 必要があります:
例えばこれは動作しますが:
my $curried = sub { ... }->curry();
これは動作しません:
my $curried = \&foo->curry();
リファレンスを括弧でくくることで解決出来ます:
my $curried = (\&foo)->curry();
符号付きの整数及び浮動小数点数リテラルにも同様に適用できます:
# this works
# これは動作します
my $range = 10->to(1);
# this doesn't work
# これは動作しません
my $range = -10->to(10);
# this works
# これは動作します
my $range = (-10)->to(10);
Perl の print BLOCK 構文(perlsub参照)に関する特殊なケースでは
print { expression() } ... (ここで波括弧は無名ハッシュ
リファレンスを意味します)において幾つかの曖昧性の除去のために
幾分踏み込む必要があります.
# this works (
# これは動作します(
print { foo => 'bar' }->foo();
# and this
# そしてこれも
print { 'foo', 'bar' }->foo();
# and even this
# これもまた
print { 'foo', 'bar', @_ }->foo();
# but this doesn't
# でもこれはだめです
print { @_ }->foo() ? 1 : 0
後者のケースでは, これを解決するために print() の最初の引数に HASH リファレンス以外の何かを渡す必要があります:
# e.g.
# 例
print STDOUT { @_ }->foo() ? 1 : 0;
# or
# 若しくは
my $hashref = { @_ };
print $hashref->foo() ? 1 : 0;
# or
# 若しくは
print '', { @_ }->foo() ? 1 : 0;
# or
# 若しくは
print '' . { @_ }->foo() ? 1 : 0;
# or even
# さらに若しくは
{ @_ }->print_if_foo(1, 0);
can 及び isa は autobox された値では"上書き(overload)"されて
いますが, VERSION メソッドはされていません.
つまり, これらは動作しますが:
[ ... ]->can('pop')
3.1415->isa('MyScalar')
これは動作しません:
use MyScalar 1.23;
use autobox SCALAR => MyScalar;
print "Hello, World"->VERSION(), $/;
けれどももちろん:
print MyScalar->VERSION(), $/;
及び
print $MyScalar::VERSION, $/;
は従来通りに動作します.
これは perl の use 及び no の実装による制限です. 同じように
import 及び unimport は autobox プラグマからは影響を受けません.
'Foo'->import() # equivalent to Foo->import() rather than MyScalar->import('Foo')
# MyScalar->import('Foo') ではなくFoo->import() と等価
[]->import() # error: Can't call method "import" on unblessed reference
# エラー: ブレスされていないリファレンス上で "import" メソッドを呼び出せません
1.10
chocolateboy: <chocolate.boy@email.com>
Copyright (c) 2005, chocolateboy.
このモジュールはフリーソフトウェアです. Perl と同じライセンスの 元で利用, 再配布及び変更を行うことが出来ます.
山科 氷魚 (YAMASHINA Hio) <hio@hio.jp>
原典: autobox VERSION 1.10. 翻訳日: 2006-11-25.