A note about ClassName type
以前 id:Craftworks さんとMooseのClassName型について話した件*1で思うところがあったのでメモしておく。
まず,現在のClassName型の定義は以下のようになっている。
sub ClassName { return Class::MOP::is_class_loaded($_); }
これは確かにおかしい。クラスがロード済みかどうかへの関心は,アプリケーション毎に違うはずだ。実際,CMOP/Mooseの内部ではクラス名をとるアトリビュートを大量に定義しているが,それらのアトリビュートを使う場合はほとんどのケースでクラスのロードを自前で行っている。つまり,それらアトリビュートの論理的な制約*2は現在のClassNameとは異なる。
したがって,ClassNameの定義は以下のほうが使いやすいのではないかと考えられる。
sub ClassName { return defined($_) && /\A \w+ (?: ::\w+) \z/xms; }
必要であれば,これに加えて ClassName.loaded などのサブタイプを提供するほうがいいように思われる。
ところが,Type as State, Coercion as Hookを応用して,現在の定義をうまく利用することができることに気付いた。
#!perl package A; use Any::Moose; use Any::Moose '::Util::TypeConstraints'; subtype 'ClassName.autoload', as 'ClassName'; coerce 'ClassName.autoload', from 'Str', via { Any::Moose::load_class($_); $_ }; # demo my $ClassName = find_type_constraint('ClassName.autoload'); print Any::Moose::is_class_loaded('File::Spec'), "\n"; print $ClassName->coerce('File::Spec'), "\n"; print Any::Moose::is_class_loaded('File::Spec'), "\n"; __END__ 結果: # 偽(空文字列) File::Spec # クラス名 1 # 真
だから現在の定義もそれなりに使えるのかもしれない。