Checking in changes prior to tagging of version 0.45. Changelog diff is:
[gitmo/Mouse.git] / lib / Mouse / Util / TypeConstraints.pm
index df0b56a..34f64cd 100644 (file)
@@ -11,7 +11,11 @@ Mouse::Exporter->setup_import_methods(
     as_is => [qw(
         as where message optimize_as
         from via
-        type subtype coerce class_type role_type enum
+
+        type subtype class_type role_type duck_type
+        enum
+        coerce
+
         find_type_constraint
     )],
 );
@@ -95,9 +99,7 @@ sub _create_type{
     }
 
     if(!defined $name){
-        if(!defined($name = $args{name})){
-            $name = '__ANON__';
-        }
+        $name = $args{name};
     }
 
     $args{name} = $name;
@@ -106,16 +108,20 @@ sub _create_type{
         $parent = delete $args{as};
         if(!$parent){
             $parent = delete $args{name};
-            $name   = '__ANON__';
+            $name   = undef;
         }
     }
 
-    my $package_defined_in = $args{package_defined_in} ||= caller(1);
-
-    my $existing = $TYPE{$name};
-    if($existing && $existing->{package_defined_in} ne $package_defined_in){
-        confess("The type constraint '$name' has already been created in "
-              . "$existing->{package_defined_in} and cannot be created again in $package_defined_in");
+    if(defined $name){
+        my $package_defined_in = $args{package_defined_in} ||= caller(1);
+        my $existing = $TYPE{$name};
+        if($existing && $existing->{package_defined_in} ne $package_defined_in){
+            confess("The type constraint '$name' has already been created in "
+                  . "$existing->{package_defined_in} and cannot be created again in $package_defined_in");
+        }
+    }
+    else{
+        $args{name} = '__ANON__';
     }
 
     $args{constraint} = delete $args{where}        if exists $args{where};
@@ -129,7 +135,12 @@ sub _create_type{
         $constraint = Mouse::Meta::TypeConstraint->new(%args);
     }
 
-    return $TYPE{$name} = $constraint;
+    if(defined $name){
+        return $TYPE{$name} = $constraint;
+    }
+    else{
+        return $constraint;
+    }
 }
 
 sub type {
@@ -172,6 +183,22 @@ sub role_type {
     );
 }
 
+sub duck_type {
+    my($name, @methods);
+
+    if(!(@_ == 1 && ref($_[0]) eq 'ARRAY')){
+        $name = shift;
+    }
+
+    @methods = (@_ == 1 && ref($_[0]) eq 'ARRAY') ? @{$_[0]} : @_;
+
+    return _create_type 'type', $name => (
+        optimized_as => Mouse::Util::generate_can_predicate_for(\@methods),
+
+        type => 'DuckType',
+    );
+}
+
 sub typecast_constraints { # DEPRECATED
     my($class, $pkg, $type, $value) = @_;
     Carp::croak("wrong arguments count") unless @_ == 4;
@@ -184,16 +211,12 @@ sub typecast_constraints { # DEPRECATED
 sub enum {
     my($name, %valid);
 
-    # enum ['small', 'medium', 'large']
-    if (ref($_[0]) eq 'ARRAY') {
-        %valid = map{ $_ => undef } @{ $_[0] };
-        $name  = sprintf '(%s)', join '|', sort @{$_[0]};
-    }
-    # enum size => 'small', 'medium', 'large'
-    else{
-        $name  = shift;
-        %valid = map{ $_ => undef } @_;
+    if(!(@_ == 1 && ref($_[0]) eq 'ARRAY')){
+        $name = shift;
     }
+
+    %valid = map{ $_ => undef } (@_ == 1 && ref($_[0]) eq 'ARRAY' ? @{$_[0]} : @_);
+
     return _create_type 'type', $name => (
         optimized_as  => sub{ defined($_[0]) && !ref($_[0]) && exists $valid{$_[0]} },
 
@@ -342,7 +365,6 @@ sub find_or_create_isa_type_constraint {
 }
 
 1;
-
 __END__
 
 =head1 NAME
@@ -351,7 +373,7 @@ Mouse::Util::TypeConstraints - Type constraint system for Mouse
 
 =head1 VERSION
 
-This document describes Mouse version 0.40_05
+This document describes Mouse version 0.45
 
 =head2 SYNOPSIS
 
@@ -419,18 +441,18 @@ yet to have been created, is to quote the type name:
 This module also provides a simple hierarchy for Perl 5 types, here is
 that hierarchy represented visually.
 
-  Any
+ Any
   Item
       Bool
       Maybe[`a]
       Undef
       Defined
           Value
-              Num
-                Int
               Str
-                ClassName
-                RoleName
+                  Num
+                      Int
+                  ClassName
+                  RoleName
           Ref
               ScalarRef
               ArrayRef[`a]
@@ -438,7 +460,7 @@ that hierarchy represented visually.
               CodeRef
               RegexpRef
               GlobRef
-                FileHandle
+                  FileHandle
               Object
 
 B<NOTE:> Any type followed by a type parameter C<[`a]> can be
@@ -524,16 +546,26 @@ Returns the names of all the type constraints.
 
 =over 4
 
-=item C<< subtype 'Name' => as 'Parent' => where { } ... -> Mouse::Meta::TypeConstraint >>
+=item C<< type $name => where { } ... -> Mouse::Meta::TypeConstraint >>
 
-=item C<< subtype as 'Parent' => where { } ...  -> Mouse::Meta::TypeConstraint >>
+=item C<< subtype $name => as $parent => where { } ... -> Mouse::Meta::TypeConstraint >>
+
+=item C<< subtype as $parent => where { } ...  -> Mouse::Meta::TypeConstraint >>
 
 =item C<< class_type ($class, ?$options) -> Mouse::Meta::TypeConstraint >>
 
 =item C<< role_type ($role, ?$options) -> Mouse::Meta::TypeConstraint >>
 
+=item C<< duck_type($name, @methods | \@methods) -> Mouse::Meta::TypeConstraint >>
+
+=item C<< duck_type(\@methods) -> Mouse::Meta::TypeConstraint >>
+
+=item C<< enum($name, @values | \@values) -> Mouse::Meta::TypeConstraint >>
+
 =item C<< enum (\@values) -> Mouse::Meta::TypeConstraint >>
 
+=item C<< coerce $type => from $another_type, via { }, ... >>
+
 =back
 
 =over 4