.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Data::Util::JA 3pm" .TH Data::Util::JA 3pm 2024-03-07 "perl v5.38.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME Data::Util::JA \- データとデータ型のためのユーティリティ集 .SH VERSION .IX Header "VERSION" This document describes Data::Util version 0.63 .SH SYNOPSIS .IX Header "SYNOPSIS" .Vb 1 \& 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, \*(AqFoo\*(Aq); \& # ... \& } \& \& use Data::Util qw(:check); \& \& sub bar{ \& my $x = shift; \& if(is_scalar_ref $x){ \& # $x is an array reference \& } \& # ... \& elsif(is_instance $x, \*(AqFoo\*(Aq){ \& # $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(\*(AqFoo\*(Aq); \& \& install_subroutine(\*(AqFoo\*(Aq, \& hello => sub{ "Hello!\en" }, \& goodby => sub{ "Goodby!\en" }, \& ); \& \& print Foo::hello(); # Hello! \& \& my($pkg, $name) = get_code_info(\e&Foo::hello); # => (\*(AqFoo\*(Aq, \*(Aqhello\*(Aq) \& my $fqn = get_code_info(\e&Foo::hello); # => \*(AqFoo::Hello\*(Aq \& my $code = get_code_ref($fqn); # => \e&Foo::hello \& \& uninstall_subroutine(\*(AqFoo\*(Aq, qw(hello goodby)); \& \& print neat("Hello!\en"); # => "Hello!\en" \& print neat(3.14); # => 3.14 \& print neat(undef); # => undef .Ve .SH DESCRIPTION .IX Header "DESCRIPTION" このモジュールはデータとデータ型のためのユーティリティ関数を提供します。 .PP ユーティリティはチェック関数群と検証関数群とその他の関数群があります。 チェック関数群は値の型を調べ,真偽値を返す機能を提供します。 検証関数群は値の型を調べ,真であればその値自身を返し, 偽であれば致命的エラーとなる機能を提供します。 その他の関数群は,無名スカラーリファレンスの生成やシンボルテーブルの操作, コードリファレンスの操作などの機能を提供します。 これらユーティリティはいずれもコードの繰り返しを避けるために設計されました。 .PP このモジュールはXSとPure Perl双方で実装されており,Cコンパイラのある 環境ではXSバックエンドが,ない環境ではPure Perlバックエンドが使用されます。 なお,環境変数\f(CW\*(C`DATA_UTIL_PUREPERL\*(C'\fRを真に設定することで,強制的にPure Perl バックエンドを使用することができます。 .PP XSバックエンドは注意深く実装されており, Pure Perlバックエンドより2倍から10倍程度高速に動作します。 実際,XSバックエンドが提供するほぼ全ての関数は,等価のPure Perlコードを インラインで展開したコードよりも更に高速です。 .PP ディストリビューションの\fIbenchmark/\fRディレクトリにベンチマークがあります。 .SH INTERFACE .IX Header "INTERFACE" .SS "Check functions" .IX Subsection "Check functions" チェック関数群は\f(CW\*(C`:check\*(C'\fRインポートタグによって導入できます。これらはある値 の型が目的の型であれば真を,そうでなければ偽を返します。 .PP また,これらの関数はオーバーロードマジックも調べます。たとえば,\f(CW\*(C`${}\*(C'\fRが オーバーロードされているオブジェクトは,スカラーリファレンスとして扱われます。 .PP リファレンスの型チェックをする関数は,オブジェクトリファレンスに対しては, オーバーロードされていない限り常に偽を返します。 これは,オブジェクトの実装に依存するコードを書かないようにするためです。 .IP is_scalar_ref(value) 4 .IX Item "is_scalar_ref(value)" スカラーリファレンスかどうかのチェックを行います。 .IP is_array_ref(value) 4 .IX Item "is_array_ref(value)" 配列リファレンスかどうかのチェックを行います。 .IP is_hash_ref(value) 4 .IX Item "is_hash_ref(value)" ハッシュリファレンスかどうかのチェックを行います。 .IP is_code_ref(value) 4 .IX Item "is_code_ref(value)" コードリファレンスかどうかのチェックを行います。 .IP is_glob_ref(value) 4 .IX Item "is_glob_ref(value)" グロブリファレンスかどうかのチェックを行います。 .IP is_regex_ref(value) 4 .IX Item "is_regex_ref(value)" \&\f(CW\*(C`qr//\*(C'\fRによって作られる正規表現かどうかのチェックを行います。 .IP "is_instance(value, class)" 4 .IX Item "is_instance(value, class)" \&\fIclass\fRのインスタンスかどうかのチェックを行います。 .Sp \&\f(CW\*(C`Scalar::Util::blessed($value) && $value\->isa($class)\*(C'\fRというコードと ほぼ等価です。 .Sp \&\fIclass\fRが未定義値またはリファレンスであれば致命的エラーとなります。 .IP is_invocant(value) 4 .IX Item "is_invocant(value)" \&\fIvalue\fRに対してメソッドを起動できるかどうかをチェックします。 .IP is_value(value) 4 .IX Item "is_value(value)" \&\fIvalue\fRがプリミティブ値かどうかをチェックします。すなわち,定義済みであり, リファレンスではなく,型グロブでもなければ真を返します。 .Sp この関数(および\f(CW\*(C`is_string\*(C'\fR/\f(CWis_number()\fR/\f(CWis_integer()\fR)は, オブジェクトリファレンスに対しては常に偽を返します。 たとえ\fIvalue\fRが文字列化/数値化/真偽値化オーバーロードメソッドを 持っていたとしても,それはプリミティブ値としては判断しません。 .Sp この関数には検証を行う対応関数がありません。 .IP is_string(value) 4 .IX Item "is_string(value)" \&\fIvalue\fRがプリミティブ値であり, かつ文字列化したときに1文字以上の内容を持つ値かどうかをチェックします。 .Sp \&\f(CW\*(C`do{ is_value($value) && length($value) > 0 }\*(C'\fRと同じです。 .Sp この関数には検証を行う対応関数がありません。 .IP is_number(value) 4 .IX Item "is_number(value)" \&\fIvalue\fRが数値かどうかをチェックします。 ここで\fB数値\fRとは,数値コンテキスト(たとえば\f(CW\*(C`sprintf \*(Aq%g\*(Aq, $value\*(C'\fR) で警告を出さずに数値に変換可能であり, かつPerlプログラム中にリテラルとしておくことができる値という意味です。 .Sp すなわち,この関数は\f(CWScalar::Util::looks_like_number()\fRと異なり, \&\f(CW\*(C`Infinity\*(C'\fRや\f(CW\*(C`NaN\*(C'\fRはリテラルとしてプログラム中に置くことはできないため, 数値として扱いません。また,数値化したときに警告を出さない例外である \&\f(CW"0 but true"\fRも同じ理由で数値として扱いません。 .Sp この関数には検証を行う対応関数がありません。 .IP is_integer(value) 4 .IX Item "is_integer(value)" \&\fIvalue\fRが整数かどうかをチェックします。これは\f(CWis_number()\fRの判定に加えて, 整数値かどうかをチェックします。 .Sp この関数には検証を行う対応関数がありません。 .SS "Validating functions" .IX Subsection "Validating functions" 検証関数は\f(CW\*(C`:validate\*(C'\fRタグによって導入できます。これらはチェック関数と 同じ方法でチェックを行います。 ただし,その結果が真であれば第一引数をそのまま返し, 偽であれば致命的エラーとなります。 .PP これらの関数もオーバーロードマジックを考慮します。 .IP scalar_ref(value) 4 .IX Item "scalar_ref(value)" スカラーリファレンスかどうかの検証を行います。 .IP array_ref(value) 4 .IX Item "array_ref(value)" 配列リファレンスかどうかの検証を行います。 .IP hash_ref(value) 4 .IX Item "hash_ref(value)" ハッシュリファレンスかどうかの検証を行います。 .IP code_ref(value) 4 .IX Item "code_ref(value)" コードリファレンスかどうかの検証を行います。 .IP glob_ref(value) 4 .IX Item "glob_ref(value)" グロブリファレンスかどうかの検証を行います。 .IP regex_ref(value) 4 .IX Item "regex_ref(value)" \&\f(CW\*(C`qr//\*(C'\fRによって作られる正規表現かどうかの検証を行います。 .IP "instance(value, class)" 4 .IX Item "instance(value, class)" \&\fIclass\fRのインスタンスかどうかの検証を行います。 .Sp \&\fIclass\fRが未定義値またはリファレンスであれば致命的エラーとなります。 .IP invocant(value) 4 .IX Item "invocant(value)" \&\fIvalue\fRに対してメソッドを起動できるかどうかの検証を行います。 .Sp \&\fIvalue\fRがクラス名である場合,そのクラス名を正規化した文字列を返します。 すなわち,\f(CW"::Foo"\fRや\f(CW"main::Foo"\fRを与えると\f(CW"Foo"\fRを返します。 .SS "Micellaneous utilities" .IX Subsection "Micellaneous utilities" その他,個別にインポートできるいくつかのユーティリティ関数があります。 .IP \fBanon_scalar()\fR 4 .IX Item "anon_scalar()" \&\f(CW\*(C`undef\*(C'\fRを参照する匿名スカラーリファレンスを生成します。 .IP anon_scalar(value) 4 .IX Item "anon_scalar(value)" \&\fIvalue\fRのコピーを参照する匿名スカラーリファレンスを生成します。 .Sp これは\f(CW\*(C`do{ my $tmp = $value; \e$value; }\*(C'\fRというコードと等価です。 .IP neat(value) 4 .IX Item "neat(value)" \&\fIvalue\fRを表示に適するよう整形した文字列を返します。 \&\f(CW\*(C`do{ defined($value) ? qq{"$value"} : \*(Aqundef\*(Aq }\*(C'\fRを置き換える機能 として提供されますが,より高機能です。 .IP get_stash(invocant) 4 .IX Item "get_stash(invocant)" \&\fIinvocant\fRのスタッシュ \fBstash\fR,つまりシンボルテーブルハッシュが 存在すれば,そのスタッシュを返します。 .Sp \&\fIinvocant\fRがオブジェクトリファレンスであれば,そのオブジェクトのパッケージの スタッシュを返します。 .Sp \&\fIinvocant\fRがパッケージ名であり,そのパッケージが既に存在すれば, そのパッケージのスタッシュを返します。 .IP "install_subroutine(package, name => subr [, ...])" 4 .IX Item "install_subroutine(package, name => subr [, ...])" サブルーチン\fIsubr\fRを\fIpackage\fRに\fIname\fRとしてインストールします。 .Sp \&\f(CW\*(C`do{ no strict \*(Aqrefs\*(Aq; *{$package.\*(Aq::\*(Aq.$name} = \e&subr; }\*(C'\fRというコードと ほぼ等価です。さらに,\fIsubr\fRが匿名サブルーチンであれば,\fIpackage\fRに 名前付きサブルーチン\fI&package::name\fRとして命名します(ただし,Pure Perl版のコードでは匿名サブルーチンの命名は行いません)。 .Sp サブルーチンを再インストールするときは,\f(CW\*(C`no warnings \*(Aqredefine\*(Aq\*(C'\fR ディレクティブを使ってください。 .Sp .Vb 2 \& no warnings \*(Aqredefine\*(Aq; \& install_subrouitne($package, $name => $subr); .Ve .Sp \&\fIpackage\fRか\fIname\fRが未定義値またはリファレンスであれば致命的エラーとなります。 \&\fIsubr\fRがコードリファレンスでないときも致命的エラーとなりますが, オーバーロードマジックは考慮されます。 .Sp この関数は\f(CW\*(C`no strict \*(Aqrefs\*(Aq\*(C'\fRを必要としないため,\fBstrict無効化の誤謬\fRを犯す危険性がありません。strict無効化の誤謬とは,以下のような状況を指します。 .Sp .Vb 2 \& my $property = ...; \& # ... \& \& no strict \*(Aqrefs\*(Aq; \& # simple read\-only accessor \& *{$pkg . \*(Aq::\*(Aq . $sub_name} = sub{ \& my($self) = @_; \& return $self\->{$property}; \& } .Ve .Sp これはオブジェクトのプロパティを参照するアクセサを生成するコードです。このアクセサは,正しく使う限りでは問題はありません。 しかし,このアクセサをクラスメソッドとして呼び出すと,問題が顕在化します。 つまりそのとき\f(CW$self\fRに入っているのはクラスを表す文字列であり, \&\f(CW\*(C`$self\->{$property}\*(C'\fRというコードはシンボリックリファレンスと解釈され, このアクセサが定義されたパッケージのグローバル変数としてデリファレンスされます。 これは多くの場合,単に\f(CW\*(C`undef\*(C'\fRを返すだけでしょう。 \&\f(CW\*(C`はまさにこのような誤ったシンボリックリファレンスの デリファレンスを検出するために用意されている機能なのですが,ここではその恩恵を 得ることができず,デバッグの難しいコードを生成してしまいます。 .Sp このケースでstrictの恩恵を得るためには,以下のように無名関数内で再度 \&\f(CW\*(C`use strict\*(C'\fRを有効にする必要があります。 .Sp .Vb 6 \& no strict \*(Aqrefs\*(Aq; \& *{$pkg . \*(Aq::\*(Aq . $sub_name} = sub{ \& use strict \*(Aqrefs\*(Aq; \& my($self) = @_; \& return $self\->{$property}; \& } .Ve .Sp そこで,\f(CWinstall_subroutine()\fRを使うとも\f(CW\*(C`strict\*(C'\fRを使用する必要がなくなります。 .Sp .Vb 6 \& install_subroutine $pkg => ( \& $sub_name => sub{ \& my($self) = @_; \& return $self\->{$property}; \& }, \& ); .Ve .Sp このstrict無効化の誤謬については,"18.10" in "Perlベストプラクティス" \&\fI「制約の無効化 \- 制約または警告を無効にする場合は,明示的に,段階的に,最も狭いスコープで行う」\fR に解説があります。 .IP "uninstall_subroutine(package, name [=> code], ...)" 4 .IX Item "uninstall_subroutine(package, name [=> code], ...)" サブルーチン\fIname\fRをパッケージ\fIpackage\fRから削除します。 .Sp \&\f(CW\*(C`undef &subr\*(C'\fRが\f(CW&subr\fRを未定義にして型グロブのコードスロットを そのままにするのに対して,\f(CW\*(C`uninstall_subroutine\*(C'\fRは型グロブを シンボルテーブルから削除し,コードスロットを以外の値をシンボルテーブルに 戻します。 この挙動は\f(CW\*(C`namespace::clean\*(C'\fRや\f(CW\*(C`constant::lexical\*(C'\fRを実現するためのものです。 .Sp \&\fIname\fRに対して\fIcode\fRが与えられている場合は,\f(CW&package::name\fRが\fIcode\fRである 場合のみ削除します。すなわち,以下の二つのコードは等価です。 .Sp .Vb 2 \& uninstall_subroutine($pkg, $name) if \e&{$pkg . \*(Aq::\*(Aq . $name} == $code; \& uninstall_subroutine($pkg, $name => $code); .Ve .Sp この関数は\f(CWSub::Delete::delete_sub()\fRと同じアルゴリズムに基づいていますが, 複数のサブルーチンを一度に削除できます。 .IP get_code_info(subr) 4 .IX Item "get_code_info(subr)" サブルーチン\fIsubr\fRのパッケージと名前のペアを返します。 これは\f(CWSub::Identify::get_code_info()\fRとほぼ同じ機能です。 ただし,スカラーコンテキストでは完全修飾名を返します。 .Sp \&\fIsubr\fRの名前が不明なときは,リストコンテキストでは空リストを, スカラーコンテキストでは\f(CW\*(C`undef\*(C'\fRを返します。 .IP "get_code_ref(package, name)" 4 .IX Item "get_code_ref(package, name)" \&\fI\e&package::name\fRが存在すれば,それを返します。 これは\f(CW\*(C`do{ no strict \*(Aqrefs\*(Aq; *{$package . \*(Aq::\*(Aq . $name}{CODE} }\*(C'\fR に似ていますが,\fI\e&package::name\fRが存在しない場合でも \&\fI*package::name\fRを生成しません。 .Sp 第三引数として\f(CW"\-create"\fRを与えると,\fI\e&package::name\fRが存在しなくても スタブを生成してそれを返します。 これは\f(CW\*(C`do{ no strict \*(Aqrefs\*(Aq; \e&{$package . \*(Aq::\*(Aq . $name} }\*(C'\fRと同じです。 .IP "curry(subr, args and/or placeholders)" 4 .IX Item "curry(subr, args and/or placeholders)" サブルーチン\fIsubr\fRのカリー化を行います。 つまり特定の引数を固定したクロージャを生成します。 .Sp \&\fIargs and/or placeholders\fRには,固定する引数か,カリー化サブルーチンの引数に 置き換えられるプレースホルダを渡します。プレースホルダには,添え字\fIx\fRを参照 する\f(CW\*(C`\ex\*(C'\fRと,\f(CW\*(C`\ex\*(C'\fRで参照した最大の添え字の以降の引数リストを参照する \&\f(CW*_\fRがあります。 .Sp たとえば,以下の\f(CW$closure\fRと\f(CW$curried\fRは同じ機能を持つサブルーチンとなります。 .Sp .Vb 3 \& my $class = \*(AqFoo\*(Aq; \& $closure = sub{ is_instance($_[0], $class) }; \& $curried = curry \e&is_instance, \e0, $class; \& \& $closure = sub{ install_subroutine($class, @_) }; \& $curried = curry \e&install_subroutine, $class, *_; .Ve .Sp なお,\f(CW*_\fRは\f(CW\*(C`\ex\*(C'\fRで参照しなかった引数リストではないので注意してください。 たとえば,\f(CW\*(C`curry(\e&subr, *_, \e1)\->(0, 1, 2, 3)\*(C'\fRというカリー化では, \&\f(CW\*(C`subr(2, 3, 1)\*(C'\fRが呼び出され,カリー化されたサブルーチンに与えられた \&\f(CW$_[0]\fR(つまり0)が無視されます。 .Sp カリー化はクロージャよりも生成・呼び出しが高速です。 .Sp より詳しいサンプルコードがData::Util::Curryにあります。 .IP "modify_subroutine(subr, modifier_type => [subroutines], ...)" 4 .IX Item "modify_subroutine(subr, modifier_type => [subroutines], ...)" サブルーチン\fIsubr\fRを\fImodifier_type\fRにしたがって\fIsubroutines\fRで修飾し, 無名関数\fImodified_subr\fRとして返します。 .Sp \&\fImodifier_type\fRには\f(CW\*(C`before\*(C'\fR, \f(CW\*(C`around\*(C'\fR, \f(CW\*(C`after\*(C'\fRがあり,\f(CW\*(C`before\*(C'\fRは \&\fIsubr\fRの呼び出し前に,\f(CW\*(C`after\*(C'\fRは\fIsubr\fRの呼出し後に,\fImodified_subr\fRに 与えられた引数で呼び出されます。\f(CW\*(C`before\*(C'\fRと\f(CW\*(C`after\*(C'\fRの戻り値は捨てられます。 \&\f(CW\*(C`around\*(C'\fRは\fIsubr\fRの入出力をフィルタリングするための修飾子です。 .Sp その際,呼び出順は,\f(CW\*(C`before\*(C'\fRと\f(CW\*(C`around\*(C'\fRは後で定義されたものが先に呼び出され (last\-defined\-first\-called),\f(CW\*(C`after\*(C'\fRは先に定義されたものが先に呼び出されます(first\-defined\-first\-called)。この呼び出し順は\f(CWsubroutine_modifier()\fRでも同じ です。 .Sp たとえば: .Sp .Vb 6 \& $modified = modify_subroutine(\e&foo, around => [sub{ \& my $next = shift; \& do_something(); \& goto &{$next}; # continuation \& }]); \& $modified\->(); \& \& $modified = modify_subroutine(\e&foo, \& before => \e@befores, \& around => \e@arounds, \& after => \e@afters, \& ); \& $modified\->(); .Ve .Sp XSによる実装では,サブルーチン修飾子のコストが非常に安くなっています。 .Sp このディストリビューションに付属している\fIexample/lib/Method/Modifiers.pm\fR (\f(CWmodify_subroutine()\fR/\f(CWsubroutine_modifier()\fRのデモ)のベンチマーク \&\fIbenchmark/methext_bench.pl\fRによれば,メソッド修飾のコストはほぼ次のようになります: .Sp .Vb 3 \& with before modifier: 100% slower \& with after modifier: 100% slower \& with around modifier: 200% slower .Ve .Sp 特に,\f(CW\*(C`before\*(C'\fRと\f(CW\*(C`after\*(C'\fRは\f(CW\*(C`SUPER::\*(C'\fR疑似クラスによってメソッドを拡張するよりも高速です。 .Sp 各修飾子については,"Method Modifiers" in Class::MOP::Classに 詳しい解説があります。Class::Method::Modifiersにも解説があります。 このモジュールが提供するAPIはこれらのモジュールより低水準ですが, 機能には互換性があります。 .IP "subroutine_modifier(modified, modifier_type => subroutines, ...)" 4 .IX Item "subroutine_modifier(modified, modifier_type => subroutines, ...)" \&\f(CWmodify_subroutine()\fRで生成した\fImodified\fRを操作します。 .Sp 引数を\fImodified\fRのみ渡した場合は,その\fImodified\fRが\f(CWmodify_subroutine()\fRで 生成されたものかどうかを示す真偽値を返します。 .Sp .Vb 3 \& if(subroutine_modifier $subr){ \& # $subrは修飾子つきサブルーチン \& } .Ve .Sp \&\fImodified\fRと\fImodifier_type\fR(\f(CW\*(C`before\*(C'\fR, \f(CW\*(C`around\*(C'\fR, \f(CW\*(C`after\*(C'\fR) を渡すと,その\fImodifier_type\fRに応じた修飾関数を返します。 .Sp .Vb 1 \& @befores = subroutine_modifier $modified, \*(Aqbefore\*(Aq; .Ve .Sp このほか,更に関数のリストを渡した場合には,\fImodified\fRの\fImodifier_type\fRに その関数を追加します。 .Sp .Vb 1 \& subroutine_modifier $modified, before => @befores; .Ve .IP "mkopt(input, moniker, require_unique, must_be)" 4 .IX Item "mkopt(input, moniker, require_unique, must_be)" \&\fIinput\fRを元に名前と値のペア配列からなる配列リファレンスを作成します。 .Sp これは\f(CWData::OptList::mkopt()\fRに似ています。それに加えて,\fImust_be\fRは 名前と型のペアからなるハッシュリファレンスでもかまいません。 .Sp For example: .Sp .Vb 2 \& $array_ref = mkopt([qw(foo bar), baz => [42]], \*(Aqmoniker\*(Aq); \& # $array_ref == [ [foo => undef], [bar => undef], baz => [42] ] .Ve .IP "mkopt_hash(input, moniker, must_be)" 4 .IX Item "mkopt_hash(input, moniker, must_be)" \&\fIinput\fRを元にハッシュリファレンスを作成します。 .Sp これは\f(CWData::OptList::mkopt_hash()\fRに似ています。それに加えて,\fImust_be\fRは 名前と型のペアからなるハッシュリファレンスでもかまいません。 .Sp For example: .Sp .Vb 2 \& $hash_ref = mkopt([qw(foo bar), baz => [42]], \*(Aqmoniker\*(Aq); \& # $hash_ref == { foo => undef, bar => undef, baz => [42] } .Ve .SS "Error handling" .IX Subsection "Error handling" 検証関数によって放出される致命的エラーは,\f(CW\*(C`Data::Util::Error\*(C'\fRモジュールによって変更することができます。 .PP .Vb 3 \& package Foo; \& use Data::Util::Error sub{ Foo::InvalidArgument\->throw(@_) }; \& use Data::Util qw(:validate); \& \& # ... .Ve .PP このエラーハンドラはパッケージ毎に設定され,そのパッケージ内で\f(CW\*(C`Data::Util\*(C'\fRが発生させるエラーにはそのエラーハンドラが使われます。 .SH DISCUSSIONS .IX Header "DISCUSSIONS" .SH "What is a X\-reference?" .IX Header "What is a X-reference?" 「Xのリファレンス」とは何を指すのでしょうか。ここではハッシュリファレンスを例にとって考えます。 まず,判断要素は以下の3つを想定します。 .IP 1. 4 \&\f(CW\*(C`ref($x) eq \*(AqHASH\*(Aq\*(C'\fR .IP 2. 4 \&\f(CW\*(C`Scalar::Util::reftype($x) eq \*(AqHASH\*(Aq\*(C'\fR .IP 3. 4 \&\f(CW\*(C`overload::Method($x, \*(Aq%{}\*(Aq)\*(C'\fR .PP \&\f(CWref()\fRは非常に高速なので,実用上はこれで事足りることが多いと思われます。しかし,これはオーバーロードマジックを考慮しません。 .PP \&\f(CWreftype()\fRを使うべきではありません。$xがオブジェクトである場合,オブジェクトの実装型を参照し,カプセル化を壊してしまうことになるからです。 .PP そして\f(CW\*(C`overload::Method\*(C'\fRが捕捉するのは,オブジェクトをある型のリファレンスとみなしてよい特殊なケースです。 .PP なお,直接$xをハッシュリファレンスとみなして参照すること(\f(CW\*(C`$x\->{$key}\*(C'\fR)は避けるべきです。これは$xがハッシュリファレンスでない場合に正しく致命的エラーを発生させますが,ブレスされたハッシュリファレンスのときにはアクセスが成功します。しかし,そのアクセスの成功はオブジェクトの実装に依存しています。 .PP さて,それでは\f(CWis_hash_ref()\fRは何を調べればいいのでしょうか。回答の一つは\f(CW\*(C`Params::Util\*(C'\fRが示しています。Version 0.35の時点では,\f(CW\*(C`P::U::_HASH\*(C'\fRは(1)を,\f(CW\*(C`P::U::_HASHLIKE\*(C'\fRは(2)と(3)をチェックします。しかし先に述べたように,(1)は高速ですがオーバーロードマジックを考慮しないので不完全であり,(2)はオブジェクトのカプセル化を壊すため使うべきではありません。このように考えると,\f(CWis_hash_ref()\fRは(1)と(3)によるチェックを行うのが正しい実装ということになります。 .PP したがって,\f(CWis_hash_ref()\fRでは\f(CWref()\fRと\f(CWoverload::Method()\fRを使ってリファレンスの型を調べます。\f(CWis_scalar_ref()\fR,\f(CWis_array_ref()\fR,\f(CWis_code_ref()\fR,\f(CWis_glob_ref()\fRも同様です。 .SH "ENVIRONMENT VARIABLES" .IX Header "ENVIRONMENT VARIABLES" .SS DATA_UTIL_PUREPERL .IX Subsection "DATA_UTIL_PUREPERL" 真であれば,Pure Perl版のバックエンドが使われます。 .SH DEPENDENCIES .IX Header "DEPENDENCIES" Perl 5.10 or later. .SH "BUGS AND LIMITATIONS" .IX Header "BUGS AND LIMITATIONS" No bugs have been reported. .PP Please report any bugs or feature requests to the author. .SH "SEE ALSO" .IX Header "SEE ALSO" overload. .PP Scalar::Util. .PP Class::MOP. .PP このモジュールのいくつかの機能は以下のモジュールの機能をXSに移植して 最適化したものであり,またいくつかはそれに加えて更に拡張を施したものです。 .PP Params::Util. .PP Sub::Install. .PP Sub::Identify. .PP Sub::Delete. .PP Sub::Curry. .PP Class::Method::Modifiers. .PP Data::OptList. .SH AUTHOR .IX Header "AUTHOR" Goro Fuji (gfx) .SH "LICENSE AND COPYRIGHT" .IX Header "LICENSE AND COPYRIGHT" Copyright (c) 2008\-2009, Goro Fuji (gfx) . Some rights reserved. .PP This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.