/usr/lib/perl5/Data/Util/JA.pod is in libdata-util-perl 0.62-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 | =encoding utf-8
=head1 NAME
Data::Util::JA - データとデータ型のためのユーティリティ集
=head1 VERSION
This document describes Data::Util version 0.62
=for test_synopsis no warnings 'redefine';
=head1 SYNOPSIS
use Data::Util qw(:validate);
sub foo{
# they will die if invalid values are supplied
my $sref = scalar_ref(shift);
my $aref = array_ref(shift);
my $href = hash_ref(shift);
my $cref = code_ref(shift);
my $gref = glob_ref(shift);
my $rref = regex_ref(shift);
my $obj = instance(shift, 'Foo');
# ...
}
use Data::Util qw(:check);
sub bar{
my $x = shift;
if(is_scalar_ref $x){
# $x is an array reference
}
# ...
elsif(is_instance $x, 'Foo'){
# $x is an instance of Foo
}
# ...
}
# miscelaneous
use Data::Util qw(:all);
my $x = anon_scalar();
$x = anon_scalar($x); # OK
my $stash = get_stash('Foo');
install_subroutine('Foo',
hello => sub{ "Hello!\n" },
goodby => sub{ "Goodby!\n" },
);
print Foo::hello(); # Hello!
my($pkg, $name) = get_code_info(\&Foo::hello); # => ('Foo', 'hello')
my $fqn = get_code_info(\&Foo::hello); # => 'Foo::Hello'
my $code = get_code_ref($fqn); # => \&Foo::hello
uninstall_subroutine('Foo', qw(hello goodby));
print neat("Hello!\n"); # => "Hello!\n"
print neat(3.14); # => 3.14
print neat(undef); # => undef
=head1 DESCRIPTION
このモジュールはデータとデータ型のためのユーティリティ関数を提供します。
ユーティリティはチェック関数群と検証関数群とその他の関数群があります。
チェック関数群は値の型を調べ,真偽値を返す機能を提供します。
検証関数群は値の型を調べ,真であればその値自身を返し,
偽であれば致命的エラーとなる機能を提供します。
その他の関数群は,無名スカラーリファレンスの生成やシンボルテーブルの操作,
コードリファレンスの操作などの機能を提供します。
これらユーティリティはいずれもコードの繰り返しを避けるために設計されました。
このモジュールはXSとPure Perl双方で実装されており,Cコンパイラのある
環境ではXSバックエンドが,ない環境ではPure Perlバックエンドが使用されます。
なお,環境変数C<DATA_UTIL_PUREPERL>を真に設定することで,強制的にPure Perl
バックエンドを使用することができます。
XSバックエンドは注意深く実装されており,
Pure Perlバックエンドより2倍から10倍程度高速に動作します。
実際,XSバックエンドが提供するほぼ全ての関数は,等価のPure Perlコードを
インラインで展開したコードよりも更に高速です。
ディストリビューションのF<benchmark/>ディレクトリにベンチマークがあります。
=head1 INTERFACE
=head2 Check functions
チェック関数群はC<:check>インポートタグによって導入できます。これらはある値
の型が目的の型であれば真を,そうでなければ偽を返します。
また,これらの関数はオーバーロードマジックも調べます。たとえば,C<${}>が
オーバーロードされているオブジェクトは,スカラーリファレンスとして扱われます。
リファレンスの型チェックをする関数は,オブジェクトリファレンスに対しては,
オーバーロードされていない限り常に偽を返します。
これは,オブジェクトの実装に依存するコードを書かないようにするためです。
=over 4
=item is_scalar_ref(value)
スカラーリファレンスかどうかのチェックを行います。
=item is_array_ref(value)
配列リファレンスかどうかのチェックを行います。
=item is_hash_ref(value)
ハッシュリファレンスかどうかのチェックを行います。
=item is_code_ref(value)
コードリファレンスかどうかのチェックを行います。
=item is_glob_ref(value)
グロブリファレンスかどうかのチェックを行います。
=item is_regex_ref(value)
C<qr//>によって作られる正規表現かどうかのチェックを行います。
=item is_instance(value, class)
I<class>のインスタンスかどうかのチェックを行います。
C<< Scalar::Util::blessed($value) && $value->isa($class) >>というコードと
ほぼ等価です。
I<class>が未定義値またはリファレンスであれば致命的エラーとなります。
=item is_invocant(value)
I<value>に対してメソッドを起動できるかどうかをチェックします。
=item is_value(value)
I<value>がプリミティブ値かどうかをチェックします。すなわち,定義済みであり,
リファレンスではなく,型グロブでもなければ真を返します。
この関数(およびC<is_string>/C<is_number()>/C<is_integer()>)は,
オブジェクトリファレンスに対しては常に偽を返します。
たとえI<value>が文字列化/数値化/真偽値化オーバーロードメソッドを
持っていたとしても,それはプリミティブ値としては判断しません。
この関数には検証を行う対応関数がありません。
=item is_string(value)
I<value>がプリミティブ値であり,
かつ文字列化したときに1文字以上の内容を持つ値かどうかをチェックします。
C<< do{ is_value($value) && length($value) > 0 } >>と同じです。
この関数には検証を行う対応関数がありません。
=item is_number(value)
I<value>が数値かどうかをチェックします。
ここでB<数値>とは,数値コンテキスト(たとえばC<< sprintf '%g', $value >>)
で警告を出さずに数値に変換可能であり,
かつPerlプログラム中にリテラルとしておくことができる値という意味です。
すなわち,この関数はC<Scalar::Util::looks_like_number()>と異なり,
C<Infinity>やC<NaN>はリテラルとしてプログラム中に置くことはできないため,
数値として扱いません。また,数値化したときに警告を出さない例外である
C<"0 but true">も同じ理由で数値として扱いません。
この関数には検証を行う対応関数がありません。
=item is_integer(value)
I<value>が整数かどうかをチェックします。これはC<is_number()>の判定に加えて,
整数値かどうかをチェックします。
この関数には検証を行う対応関数がありません。
=back
=head2 Validating functions
検証関数はC<:validate>タグによって導入できます。これらはチェック関数と
同じ方法でチェックを行います。
ただし,その結果が真であれば第一引数をそのまま返し,
偽であれば致命的エラーとなります。
これらの関数もオーバーロードマジックを考慮します。
=over 4
=item scalar_ref(value)
スカラーリファレンスかどうかの検証を行います。
=item array_ref(value)
配列リファレンスかどうかの検証を行います。
=item hash_ref(value)
ハッシュリファレンスかどうかの検証を行います。
=item code_ref(value)
コードリファレンスかどうかの検証を行います。
=item glob_ref(value)
グロブリファレンスかどうかの検証を行います。
=item regex_ref(value)
C<qr//>によって作られる正規表現かどうかの検証を行います。
=item instance(value, class)
I<class>のインスタンスかどうかの検証を行います。
I<class>が未定義値またはリファレンスであれば致命的エラーとなります。
=item invocant(value)
I<value>に対してメソッドを起動できるかどうかの検証を行います。
I<value>がクラス名である場合,そのクラス名を正規化した文字列を返します。
すなわち,C<"::Foo">やC<"main::Foo">を与えるとC<"Foo">を返します。
=back
=head2 Micellaneous utilities
その他,個別にインポートできるいくつかのユーティリティ関数があります。
=over 4
=item anon_scalar()
C<undef>を参照する匿名スカラーリファレンスを生成します。
=item anon_scalar(value)
I<value>のコピーを参照する匿名スカラーリファレンスを生成します。
これはC<< do{ my $tmp = $value; \$value; } >>というコードと等価です。
=item neat(value)
I<value>を表示に適するよう整形した文字列を返します。
C<< do{ defined($value) ? qq{"$value"} : 'undef' } >>を置き換える機能
として提供されますが,より高機能です。
=item get_stash(invocant)
I<invodant>のスタッシュ B<stash>,つまりシンボルテーブルハッシュが
存在すれば,そのスタッシュを返します。
I<invocant>がオブジェクトリファレンスであれば,そのオブジェクトのパッケージの
スタッシュを返します。
I<invocant>がパッケージ名であり,そのパッケージが既に存在すれば,
そのパッケージのスタッシュを返します。
=item install_subroutine(package, name => subr [, ...])
サブルーチンI<subr>をI<package>にI<name>としてインストールします。
C<< do{ no strict 'refs'; *{$package.'::'.$name} = \&subr; } >>というコードと
ほぼ等価です。さらに,I<subr>が匿名サブルーチンであれば,I<package>に
名前付きサブルーチンI<&package::name>として命名します(ただし,Pure Perl版のコードでは匿名サブルーチンの命名は行いません)。
サブルーチンを再インストールするときは,C<< no warnings 'redefine' >>
ディレクティブを使ってください。
no warnings 'redefine';
install_subrouitne($package, $name => $subr);
I<package>かI<name>が未定義値またはリファレンスであれば致命的エラーとなります。
I<subr>がコードリファレンスでないときも致命的エラーとなりますが,
オーバーロードマジックは考慮されます。
この関数はC<< no strict 'refs' >>を必要としないため,B<strict無効化の誤謬>を犯す危険性がありません。strict無効化の誤謬とは,以下のような状況を指します。
my $property = ...;
# ...
no strict 'refs';
# simple read-only accessor
*{$pkg . '::' . $sub_name} = sub{
my($self) = @_;
return $self->{$property};
}
これはオブジェクトのプロパティを参照するアクセサを生成するコードです。このアクセサは,正しく使う限りでは問題はありません。
しかし,このアクセサをクラスメソッドとして呼び出すと,問題が顕在化します。
つまりそのときC<$self>に入っているのはクラスを表す文字列であり,
C<< $self->{$property} >>というコードはシンボリックリファレンスと解釈され,
このアクセサが定義されたパッケージのグローバル変数としてデリファレンスされます。
これは多くの場合,単にC<undef>を返すだけでしょう。
C<<use strict 'refs'>>はまさにこのような誤ったシンボリックリファレンスの
デリファレンスを検出するために用意されている機能なのですが,ここではその恩恵を
得ることができず,デバッグの難しいコードを生成してしまいます。
このケースでstrictの恩恵を得るためには,以下のように無名関数内で再度
C<use strict>を有効にする必要があります。
no strict 'refs';
*{$pkg . '::' . $sub_name} = sub{
use strict 'refs';
my($self) = @_;
return $self->{$property};
}
そこで,C<install_subroutine()>を使うともC<strict>を使用する必要がなくなります。
install_subroutine $pkg => (
$sub_name => sub{
my($self) = @_;
return $self->{$property};
},
);
このstrict無効化の誤謬については,L<"Perlベストプラクティス"/18.10>
I<「制約の無効化 - 制約または警告を無効にする場合は,明示的に,段階的に,最も狭いスコープで行う」> に解説があります。
=item uninstall_subroutine(package, name [=> code], ...)
サブルーチンI<name>をパッケージI<package>から削除します。
C<< undef &subr >>がC<&subr>を未定義にして型グロブのコードスロットを
そのままにするのに対して,C<uninstall_subroutine>は型グロブを
シンボルテーブルから削除し,コードスロットを以外の値をシンボルテーブルに
戻します。
この挙動はC<namespace::clean>やC<constant::lexical>を実現するためのものです。
I<name>に対してI<code>が与えられている場合は,C<&package::name>がI<code>である
場合のみ削除します。すなわち,以下の二つのコードは等価です。
uninstall_subroutine($pkg, $name) if \&{$pkg . '::' . $name} == $code;
uninstall_subroutine($pkg, $name => $code);
この関数はC<Sub::Delete::delete_sub()>と同じアルゴリズムに基づいていますが,
複数のサブルーチンを一度に削除できます。
=item get_code_info(subr)
サブルーチンI<subr>のパッケージと名前のペアを返します。
これはC<Sub::Identify::get_code_info()>とほぼ同じ機能です。
ただし,スカラーコンテキストでは完全修飾名を返します。
I<subr>の名前が不明なときは,リストコンテキストでは空リストを,
スカラーコンテキストではC<undef>を返します。
=item get_code_ref(package, name)
I<\&package::name>が存在すれば,それを返します。
これはC<< do{ no strict 'refs'; *{$package . '::' . $name}{CODE} } >>
に似ていますが,I<\&package::name>が存在しない場合でも
I<*package::name>を生成しません。
第三引数としてC<"-create">を与えると,I<\&package::name>が存在しなくても
スタブを生成してそれを返します。
これはC<< do{ no strict 'refs'; \&{$package . '::' . $name} } >>と同じです。
=item curry(subr, args and/or placeholders)
サブルーチンI<subr>のカリー化を行います。
つまり特定の引数を固定したクロージャを生成します。
I<args and/or placeholders>には,固定する引数か,カリー化サブルーチンの引数に
置き換えられるプレースホルダを渡します。プレースホルダには,添え字I<x>を参照
するC<\x>と,C<\x>で参照した最大の添え字の以降の引数リストを参照する
C<*_>があります。
たとえば,以下のC<$closure>とC<$curried>は同じ機能を持つサブルーチンとなります。
my $class = 'Foo';
$closure = sub{ is_instance($_[0], $class) };
$curried = curry \&is_instance, \0, $class;
$closure = sub{ install_subroutine($class, @_) };
$curried = curry \&install_subroutine, $class, *_;
なお,C<*_>はC<\x>で参照しなかった引数リストではないので注意してください。
たとえば,C<< curry(\&subr, *_, \1)->(0, 1, 2, 3) >>というカリー化では,
C<subr(2, 3, 1)>が呼び出され,カリー化されたサブルーチンに与えられた
C<$_[0]>(つまり0)が無視されます。
カリー化はクロージャよりも生成・呼び出しが高速です。
より詳しいサンプルコードがL<Data::Util::Curry>にあります。
=item modify_subroutine(subr, modifier_type => [subroutines], ...)
サブルーチンI<subr>をI<modifier_type>にしたがってI<subroutines>で修飾し,
無名関数I<modified_subr>として返します。
I<modifier_type>にはC<before>, C<around>, C<after>があり,C<before>は
I<subr>の呼び出し前に,C<after>はI<subr>の呼出し後に,I<modified_subr>に
与えられた引数で呼び出されます。C<before>とC<after>の戻り値は捨てられます。
C<around>はI<subr>の入出力をフィルタリングするための修飾子です。
その際,呼び出順は,C<before>とC<around>は後で定義されたものが先に呼び出され
(last-defined-first-called),C<after>は先に定義されたものが先に呼び出されます(first-defined-first-called)。この呼び出し順はC<subroutine_modifier()>でも同じ
です。
たとえば:
$modified = modify_subroutine(\&foo, around => [sub{
my $next = shift;
do_something();
goto &{$next}; # continuation
}]);
$modified->();
$modified = modify_subroutine(\&foo,
before => \@befores,
around => \@arounds,
after => \@afters,
);
$modified->();
XSによる実装では,サブルーチン修飾子のコストが非常に安くなっています。
このディストリビューションに付属しているF<example/lib/Method/Modifiers.pm>
(C<modify_subroutine()>/C<subroutine_modifier()>のデモ)のベンチマーク
F<benchmark/methext_bench.pl>によれば,メソッド修飾のコストはほぼ次のようになります:
with before modifier: 100% slower
with after modifier: 100% slower
with around modifier: 200% slower
特に,C<before>とC<after>はC<SUPER::>疑似クラスによってメソッドを拡張するよりも高速です。
各修飾子については,L<Class::MOP::Class/"Method Modifiers">に
詳しい解説があります。L<Class::Method::Modifiers>にも解説があります。
このモジュールが提供するAPIはこれらのモジュールより低水準ですが,
機能には互換性があります。
=item subroutine_modifier(modified, modifier_type => subroutines, ...)
C<modify_subroutine()>で生成したI<modified>を操作します。
引数をI<modified>のみ渡した場合は,そのI<modified>がC<modify_subroutine()>で
生成されたものかどうかを示す真偽値を返します。
if(subroutine_modifier $subr){
# $subrは修飾子つきサブルーチン
}
I<modified>とI<modifier_type>(C<before>, C<around>, C<after>)
を渡すと,そのI<modifier_type>に応じた修飾関数を返します。
@befores = subroutine_modifier $modified, 'before';
このほか,更に関数のリストを渡した場合には,I<modified>のI<modifier_type>に
その関数を追加します。
subroutine_modifier $modified, before => @befores;
=item mkopt(input, moniker, require_unique, must_be)
I<input>を元に名前と値のペア配列からなる配列リファレンスを作成します。
これはC<Data::OptList::mkopt()>に似ています。それに加えて,I<must_be>は
名前と型のペアからなるハッシュリファレンスでもかまいません。
For example:
$array_ref = mkopt([qw(foo bar), baz => [42]], 'moniker');
# $array_ref == [ [foo => undef], [bar => undef], baz => [42] ]
=item mkopt_hash(input, moniker, must_be)
I<input>を元にハッシュリファレンスを作成します。
これはC<Data::OptList::mkopt_hash()>に似ています。それに加えて,I<must_be>は
名前と型のペアからなるハッシュリファレンスでもかまいません。
For example:
$hash_ref = mkopt([qw(foo bar), baz => [42]], 'moniker');
# $hash_ref == { foo => undef, bar => undef, baz => [42] }
=back
=head2 Error handling
検証関数によって放出される致命的エラーは,C<Data::Util::Error>モジュールによって変更することができます。
package Foo;
use Data::Util::Error sub{ Foo::InvalidArgument->throw(@_) };
use Data::Util qw(:validate);
# ...
このエラーハンドラはパッケージ毎に設定され,そのパッケージ内でC<Data::Util>が発生させるエラーにはそのエラーハンドラが使われます。
=head1 DISCUSSIONS
=head1 What is a X-reference?
「Xのリファレンス」とは何を指すのでしょうか。ここではハッシュリファレンスを例にとって考えます。
まず,判断要素は以下の3つを想定します。
=over 4
=item 1
C<ref($x) eq 'HASH'>
=item 2
C<Scalar::Util::reftype($x) eq 'HASH'>
=item 3
C<overload::Method($x, '%{}')>
=back
C<ref()>は非常に高速なので,実用上はこれで事足りることが多いと思われます。しかし,これはオーバーロードマジックを考慮しません。
C<reftype()>を使うべきではありません。$xがオブジェクトである場合,オブジェクトの実装型を参照し,カプセル化を壊してしまうことになるからです。
そしてC<overload::Method>が捕捉するのは,オブジェクトをある型のリファレンスとみなしてよい特殊なケースです。
なお,直接$xをハッシュリファレンスとみなして参照すること(C<< $x->{$key} >>)は避けるべきです。これは$xがハッシュリファレンスでない場合に正しく致命的エラーを発生させますが,ブレスされたハッシュリファレンスのときにはアクセスが成功します。しかし,そのアクセスの成功はオブジェクトの実装に依存しています。
さて,それではC<is_hash_ref()>は何を調べればいいのでしょうか。回答の一つはC<Params::Util>が示しています。Version 0.35の時点では,C<P::U::_HASH>は(1)を,C<P::U::_HASHLIKE>は(2)と(3)をチェックします。しかし先に述べたように,(1)は高速ですがオーバーロードマジックを考慮しないので不完全であり,(2)はオブジェクトのカプセル化を壊すため使うべきではありません。このように考えると,C<is_hash_ref()>は(1)と(3)によるチェックを行うのが正しい実装ということになります。
したがって,C<is_hash_ref()>ではC<ref()>とC<overload::Method()>を使ってリファレンスの型を調べます。C<is_scalar_ref()>,C<is_array_ref()>,C<is_code_ref()>,C<is_glob_ref()>も同様です。
=head1 ENVIRONMENT VARIABLES
=head2 DATA_UTIL_PUREPERL
真であれば,Pure Perl版のバックエンドが使われます。
=head1 DEPENDENCIES
Perl 5.8.1 or later.
=head1 BUGS AND LIMITATIONS
No bugs have been reported.
Please report any bugs or feature requests to the author.
=head1 SEE ALSO
L<overload>.
L<Scalar::Util>.
L<Class::MOP>.
このモジュールのいくつかの機能は以下のモジュールの機能をXSに移植して
最適化したものであり,またいくつかはそれに加えて更に拡張を施したものです。
L<Params::Util>.
L<Sub::Install>.
L<Sub::Identify>.
L<Sub::Delete>.
L<Sub::Curry>.
L<Class::Method::Modifiers>.
L<Data::OptList>.
=head1 AUTHOR
Goro Fuji (gfx) E<lt>gfuji(at)cpan.orgE<gt>
=head1 LICENSE AND COPYRIGHT
Copyright (c) 2008-2009, Goro Fuji (gfx) E<lt>gfuji(at)cpan.orgE<gt>. Some rights reserved.
This module is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.
=cut
|