2012-01-26 14 views
5

イテレータをさまざまな出力形式にシリアル化するMooseクラスを使用します。私たちは、属性として、イテレータを説明します。ムーゼ型制約付きの祝福されたCodeRefの使用

has iterator => (
    is => 'ro', 
    isa => 'CodeRef', 
    required => 1, 
); 

これは、これまでうまく働いたが、我々は最近、後の消費のためのイテレータを準備するためにIterator::Simpleを使用してきました。

has iterator => (
    is => 'ro', 
    isa => 'CodeRef|Iterator::Simple::Iterator', 
    required => 1, 
); 

そして、我々のシリアライザが正しくイテレータクラスを受け入れることができ:これは私たちがこれを書いて行くことができます。しかし、それは不完全な解決策であるようです。

属性が呼び出し可能でなければならないという制約を指定する方法がありますか?私は可能性がありますMoose::Util::TypeConstraintsと可能性がありますoverload::Overloadedの上に&{}を使用してチェックするが、私は誰もがこれを行うためのモジュールを作成したかどうか、またはこれをテストするためのムース標準的な方法があるかどうかを知りたい。

答えて

4

CodeRefは、符号なしのコード参照のみを許可します。幸いにも、独自の型を作るのは簡単です。

Callableを次のように定義し、CodeRefの代わりに使用します。それは以下を可能にする:

  • 無呼吸コード参照。
  • ブレスコード参照。
  • コード参照にふさわしいオブジェクト(つまり、&{}をオーバーロードするオブジェクト)。

use Moose::Util::TypeConstraints; 
use overload  qw(); 
use Scalar::Util qw(); 

subtype 'Callable' 
    => as 'Ref' 
    => where { 
      Scalar::Util::reftype($_) eq 'CODE' 
      || 
      Scalar::Util::blessed($_) && overload::Method($_, "&{}") 
     } 

    # Written such that parent's inline_as needs not be prepended. 
    => inline_as {'(
      (Scalar::Util::reftype('.$_[1].') // "") eq 'CODE' 
      || 
      Scalar::Util::blessed('.$_[1].') && overload::Method('.$_[1].', "&{}") 
     )'}; 

no Moose::Util::TypeConstraints; 
関連する問題