使用具有Moose类型约束的祝福CodeRef

ang*_*ixd 5 perl moose moosex-types

我们使用Moose类将迭代器序列化为各种输出格式.我们将迭代器描述为一个属性:

has iterator => (
    is => 'ro',
    isa => 'CodeRef',
    required => 1,
);
Run Code Online (Sandbox Code Playgroud)

到目前为止,这个工作正常,但是我们最近一直在使用Iterator :: Simple来准备迭代器以供以后使用.这意味着我们可以写下这个:

has iterator => (
    is => 'ro',
    isa => 'CodeRef|Iterator::Simple::Iterator',
    required => 1,
);
Run Code Online (Sandbox Code Playgroud)

并允许我们的序列化程序正确接受迭代器类.但是,这似乎是一个不完整的解决方案.

在Moose中是否有一种方法可以指定属性必须可调用的约束?我怀疑这可能与驼鹿::的Util :: TypeConstraints和使用过载::重载&{}检查,但我想知道是否有人已经创建了一个模块,已经做到这一点,或者如果有一个木规范的方式测试这个.

ike*_*ami 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;
Run Code Online (Sandbox Code Playgroud)