Class::Enumemon の中身をちょっとのぞいてみる
使う機会があってRailsのActive Recordっぽくて便利だと思ったけど、中身があまり想像できなかったのでちょっとだけ調べてみた。
package IdolType; use Class::Enumemon ( values => 1, getter => 1, indexer => { by_id => 'id', from_type => 'type', }, { id => 1, type => 'cute', }, { id => 2, type => 'cool', }, { id => 3, type => 'passion', }, ); 1; package My::Pkg; use IdolType; # `values`: defines a method for getting all values IdolType->values; #=> [ bless({ id => 1, type => 'cute' }, 'IdolType'), ... ]
これはcpanに載っていたサンプルコードで、とりあえず IdolType->values
でなぜ [ bless({ id => 1, type => 'cute' }, 'IdolType'), ... ]
が返ってくるのかを調べてみる。
コードを見ると、100行程度でそこまで長くはなかった。
p5-Class-Enumemon/Enumemon.pm at master · pokutuna/p5-Class-Enumemon · GitHub
values
に注目すると、36行目で作られていた。
p5-Class-Enumemon/Enumemon.pm at 0b7f39e89379c4be478fb88a607aca4db9480eeb · pokutuna/p5-Class-Enumemon · GitHub
$data->{values} = [ map { bless $_, $pkg } @$defs ];
bless
が何をしているのかパッと説明できなかったので
Hatena-Textbook/foundation-of-programming-perl.md at master · hatena/Hatena-Textbook · GitHub
あたりを見直す必要があると痛感。
IdolType->values
で呼び出される処理は52行目から書かれている。
sub _mk_values { my ($pkg, $data) = @_; no strict 'refs'; *{"$pkg\::values"} = sub { my $values = $data->{values}; wantarray ? @$values : [ @$values ]; }; }
*{"$pkg\::values"}
が、「IdolType->values
でなぜ [ bless({ id => 1, type => 'cute' }, 'IdolType'), ... ]
が返ってくるのか」の核となっていそう。
「*」について『初めてのPerl』で引いてみても正規表現についてしか出てこない。
『続・初めてのPerl』で調べると、p91に以下の文言があった。
ここでは型グロブの説明はしませんが、*プリフィックスを使って、リファレンスを見て文字列内でどの変数型を使うべきかを判断せよとData::Dumperに指示するという意味になっています。
型グロブについて調べてみると、以下のブログに次のような説明があった。
型グロブでシンボルテーブルにアクセス出来ます。シンボルテーブルでは、各データ型ごとに1つのスロットがあって、各スロットは各データ型のリファレンスを参照しています。
とりあえず型グロブっていう概念を使ってやっているんだなー、という感じで今日は終わっておく。
Perlむずかしい。