package Moose::Util::TypeConstraints;
-use strict;
-use warnings;
-
use Carp ();
use List::MoreUtils qw( all any );
use Scalar::Util qw( blessed reftype );
use Moose::Exporter;
-our $VERSION = '0.73';
+our $VERSION = '0.84';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::TypeConstraint::Class;
use Moose::Meta::TypeConstraint::Role;
use Moose::Meta::TypeConstraint::Enum;
+use Moose::Meta::TypeConstraint::DuckType;
use Moose::Meta::TypeCoercion;
use Moose::Meta::TypeCoercion::Union;
use Moose::Meta::TypeConstraint::Registry;
}
register_type_constraint(
- _create_type_constraint(
+ create_duck_type_constraint(
$type_name,
- 'Object',
- sub {
- my $obj = $_;
- return 0 unless all { $obj->can($_) } @methods;
- return 1;
- },
- sub {
- my $obj = $_;
- my @missing_methods = grep { !$obj->can($_) } @methods;
- return
- "${\blessed($obj)} is missing methods '@missing_methods'";
- },
+ \@methods,
)
);
}
);
}
+sub create_duck_type_constraint {
+ my ( $type_name, $methods ) = @_;
+
+ Moose::Meta::TypeConstraint::DuckType->new(
+ name => $type_name || '__ANON__',
+ methods => $methods,
+ );
+}
+
## --------------------------------------------------------
## desugaring functions ...
## --------------------------------------------------------
my $type = find_type_constraint($type_name);
( defined $type )
|| __PACKAGE__->_throw_error(
- "Cannot find type '$type_name', perhaps you forgot to load it.");
+ "Cannot find type '$type_name', perhaps you forgot to load it");
if ( $type->has_coercion ) {
$type->coercion->add_type_coercions(@$coercion_map);
}
Moose::Meta::TypeConstraint::Class
Moose::Meta::TypeConstraint::Role
Moose::Meta::TypeConstraint::Enum
+ Moose::Meta::TypeConstraint::DuckType
Moose::Meta::TypeConstraint::Registry
);
type 'Any' => where {1}; # meta-type including all
-type 'Item' => where {1}; # base-type
+subtype 'Item' => as 'Any'; # base-type
subtype 'Undef' => as 'Item' => where { !defined($_) };
subtype 'Defined' => as 'Item' => where { defined($_) };
subtype 'Str' => as 'Value' => where {1} =>
optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Str;
-subtype 'Num' => as 'Value' =>
+subtype 'Num' => as 'Str' =>
where { Scalar::Util::looks_like_number($_) } =>
optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Num;
where { blessed($_) && blessed($_) ne 'Regexp' } =>
optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Object;
+# This type is deprecated.
subtype 'Role' => as 'Object' => where { $_->can('does') } =>
optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Role;
\&Moose::Util::TypeConstraints::OptimizedConstraints::ClassName;
subtype 'RoleName' => as 'ClassName' => where {
- ( ( $_->can('meta') || return )->($_) || return )
- ->isa('Moose::Meta::Role');
+ (Class::MOP::class_of($_) || return)->isa('Moose::Meta::Role');
} => optimize_as
\&Moose::Util::TypeConstraints::OptimizedConstraints::RoleName;
Defined
Value
Num
- Int
+ Int
Str
- ClassName
- RoleName
+ ClassName
+ RoleName
Ref
ScalarRef
ArrayRef[`a]
CodeRef
RegexpRef
GlobRef
- FileHandle
+ FileHandle
Object
- Role
B<NOTE:> Any type followed by a type parameter C<[`a]> can be
parameterized, this means you can say:
type constraint to pass.
B<NOTE:> The C<RoleName> constraint checks a string is a I<package
-name> which is a role, like C<'MyApp::Role::Comparable'>. The C<Role>
-constraint checks that an I<object does> the named role.
+name> which is a role, like C<'MyApp::Role::Comparable'>.
=head2 Type Constraint Naming
=over 4
-=item B<subtype 'Name' => as 'Parent' => where { } ...>
+=item B<< subtype 'Name' => as 'Parent' => where { } ... >>
This creates a named subtype.
The valid hashref keys are C<as> (the parent), C<where>, C<message>,
and C<optimize_as>.
-=item B<subtype as 'Parent' => where { } ...>
+=item B<< subtype as 'Parent' => where { } ... >>
This creates an unnamed subtype and will return the type
constraint meta-object, which will be an instance of
If passed an ARRAY reference instead of the C<$name>, C<@methods>
pair, this will create an unnamed duck type. This can be used in an
-attribute definiton like so:
+attribute definition like so:
has 'cache' => (
is => 'ro',
Given a enum name this function will create a new
L<Moose::Meta::TypeConstraint::Enum> object for that enum name.
+=item B<create_duck_type_constraint($name, $methods)>
+
+Given a duck type name this function will create a new
+L<Moose::Meta::TypeConstraint::DuckType> object for that enum name.
+
=item B<find_or_parse_type_constraint($type_name)>
Given a type name, this first attempts to find a matching constraint