We use Moose classes that serialize iterators into various output formats. We describe the iterator as an attribute:
has iterator => (
is => 'ro',
isa => 'CodeRef',
required => 1,
);
This has worked fine so far, but we have lately been using Iterator::Simple to prepare iterators for later consumption. This means that we can go about writing this:
has iterator => (
is => 'ro',
isa => 'CodeRef|Iterator::Simple::Iterator',
required => 1,
);
And allow our serializers to accept the iterator class correctly. However, that seems to be a incomplete solution.
Is there a way in Moose to specify the constraint that the attribute must be callable? I suspect it may be possible with Moose::Util::TypeConstraints and using overload::Overloaded on &{}
to check, but I'd like to know if anyone has created a module to do this already or if there is a Moose-standard way to test for this.
CodeRef
only allows unblessed code references. Fortunately, it's easy to make your own types.
Define Callable
as shown below, then use it instead of CodeRef
. It allows the following:
&{}
).
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;