Использование благословенных CodeRef с ограничениями типов Moose - PullRequest
5 голосов
/ 26 января 2012

Мы используем классы Moose, которые сериализуют итераторы в различные выходные форматы.Мы описываем итератор как атрибут:

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

До сих пор это работало нормально, но в последнее время мы использовали Iterator :: Simple для подготовки итераторов для последующего использования.Это означает, что мы можем написать:

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

и позволить нашим сериализаторам правильно принимать класс итератора.Однако, это кажется неполным решением.

Есть ли способ в Moose указать ограничение, что атрибут должен вызываться?Я подозреваю, что это возможно с Moose :: Util :: TypeConstraints и использованием overload :: Overloaded на &{}, чтобы проверить, но я хотел бы знать, если кто-то создалмодуль, чтобы сделать это уже, или если есть стандартный способ проверки Moose для этого.

Ответы [ 2 ]

4 голосов
/ 26 января 2012

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;
0 голосов
/ 26 января 2012

Знаете ли вы достаточно, чтобы получить от Scalar :: Util :: reftype ?

...