2012-01-26 17 views
5

我們使用Moose類將迭代器序列化爲各種輸出格式。我們描述了迭代器作爲一個屬性:使用帶Moose類型約束的有福的CodeRefs

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

這在目前工作正常,但我們最近已經被使用Iterator::Simple爲以後的消費準備的迭代器。這意味着,我們可以去寫這樣的:

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

而且讓我們的串行正確接受iterator類。但是,這似乎是一個不完整的解決方案。

Moose中有一種方法可以指定屬性必須可調用的約束嗎?我懷疑它可能與Moose::Util::TypeConstraints和使用檢查,但我想知道是否有人已經創建了一個模塊來做到這一點,或者如果有一個駝鹿標準的方式來測試這個。

回答

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;