X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FUtil%2FTypeConstraints.pm;h=b0ecf5cc8aa40960210685f42255b7c8a4a0a73f;hb=refs%2Ftags%2F0.91;hp=b792f5929bc40f205167837c8bfa33007cd87df8;hpb=21e1632721979ae5fb66e40843be052a0cc4b97d;p=gitmo%2FMoose.git diff --git a/lib/Moose/Util/TypeConstraints.pm b/lib/Moose/Util/TypeConstraints.pm index b792f59..b0ecf5c 100644 --- a/lib/Moose/Util/TypeConstraints.pm +++ b/lib/Moose/Util/TypeConstraints.pm @@ -1,15 +1,12 @@ 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.91'; $VERSION = eval $VERSION; our $AUTHORITY = 'cpan:STEVAN'; @@ -35,6 +32,7 @@ use Moose::Meta::TypeConstraint::Parameterizable; 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; @@ -369,20 +367,9 @@ sub duck_type { } 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, ) ); } @@ -446,6 +433,15 @@ sub create_enum_type_constraint { ); } +sub create_duck_type_constraint { + my ( $type_name, $methods ) = @_; + + Moose::Meta::TypeConstraint::DuckType->new( + name => $type_name || '__ANON__', + methods => $methods, + ); +} + ## -------------------------------------------------------- ## desugaring functions ... ## -------------------------------------------------------- @@ -509,7 +505,7 @@ sub _install_type_coercions ($$) { 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); } @@ -598,7 +594,7 @@ $_->make_immutable( # these are Class::MOP accessors, so they need inlining inline_accessors => 1 ) for grep { $_->is_mutable } - map { $_->meta } + map { Class::MOP::class_of($_) } qw( Moose::Meta::TypeConstraint Moose::Meta::TypeConstraint::Union @@ -607,11 +603,12 @@ $_->make_immutable( 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($_) }; @@ -628,7 +625,7 @@ subtype 'Ref' => as 'Defined' => where { ref($_) } => 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; @@ -660,6 +657,7 @@ subtype 'Object' => as 'Ref' => 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; @@ -670,8 +668,7 @@ subtype 'ClassName' => as 'Str' => \&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; @@ -852,10 +849,10 @@ that hierarchy represented visually. Defined Value Num - Int + Int Str - ClassName - RoleName + ClassName + RoleName Ref ScalarRef ArrayRef[`a] @@ -863,9 +860,8 @@ that hierarchy represented visually. CodeRef RegexpRef GlobRef - FileHandle + FileHandle Object - Role B Any type followed by a type parameter C<[`a]> can be parameterized, this means you can say: @@ -891,8 +887,7 @@ existence check. This means that your class B be loaded for this type constraint to pass. B The C constraint checks a string is a I which is a role, like C<'MyApp::Role::Comparable'>. The C -constraint checks that an I the named role. +name> which is a role, like C<'MyApp::Role::Comparable'>. =head2 Type Constraint Naming @@ -954,7 +949,7 @@ See the L for an example of how to use these. =over 4 -=item B as 'Parent' => where { } ...> +=item B<< subtype 'Name' => as 'Parent' => where { } ... >> This creates a named subtype. @@ -970,7 +965,7 @@ name and a hashref of parameters: The valid hashref keys are C (the parent), C, C, and C. -=item B 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 @@ -1010,7 +1005,7 @@ recommend that you use a C-only Role instead. 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', @@ -1072,7 +1067,7 @@ B You should only use this if you know what you are doing, all the built in types use this, so your subtypes (assuming they are shallow) will not likely need to use this. -=item B where { } ... > +=item B<< type 'Name' => where { } ... >> This creates a base type, which has no parent. @@ -1182,6 +1177,11 @@ L constructor (as a hash). Given a enum name this function will create a new L object for that enum name. +=item B + +Given a duck type name this function will create a new +L object for that enum name. + =item B Given a type name, this first attempts to find a matching constraint