autobox - 組み込み型をファーストクラスオブジェクトとして利用

目次


名前

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種類の値を取ることが 出来ます:

これまでに述べた SCALAR, ARRAY, HASH, CODE そして DEFAULT の オプションに加えて2つのオプション, UNDEF 及び REPORT があります.

UNDEF

仮想型, 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 は現在のハンドラをコールバック若しくは静的なレポート関数 で露出させます.

これは手書きで算出された束縛を見たい人には便利です.

デバッグは 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


関連項目

* Moose::Autobox
* autobox::Core
* Perl6::Contexts
* Shell::Autobox
* Scalar::Properties
* Set::Array

著者

chocolateboy: <chocolate.boy@email.com>


著作権

Copyright (c) 2005, chocolateboy.

このモジュールはフリーソフトウェアです. Perl と同じライセンスの 元で利用, 再配布及び変更を行うことが出来ます.


和訳

 山科 氷魚 (YAMASHINA Hio) <hio@hio.jp>

原典: autobox VERSION 1.10. 翻訳日: 2006-11-25.

autobox - 組み込み型をファーストクラスオブジェクトとして利用

索引

autobox - 組み込み型をファーストクラスオブジェクトとして利用