Allow overloading on arguments to native trait methods
Dave Rolsky [Mon, 27 Sep 2010 00:09:21 +0000 (19:09 -0500)]
15 files changed:
Makefile.PL
lib/Moose/Meta/Method/Accessor/Native/Array/first.pm
lib/Moose/Meta/Method/Accessor/Native/Array/grep.pm
lib/Moose/Meta/Method/Accessor/Native/Array/join.pm
lib/Moose/Meta/Method/Accessor/Native/Array/map.pm
lib/Moose/Meta/Method/Accessor/Native/Array/natatime.pm
lib/Moose/Meta/Method/Accessor/Native/Array/reduce.pm
lib/Moose/Meta/Method/Accessor/Native/Array/sort.pm
lib/Moose/Meta/Method/Accessor/Native/Array/sort_in_place.pm
lib/Moose/Meta/Method/Accessor/Native/String/match.pm
lib/Moose/Meta/Method/Accessor/Native/String/replace.pm
lib/Moose/Meta/Method/Accessor/Native/String/substr.pm
lib/Moose/Util.pm
t/070_native_traits/010_trait_array.t
t/070_native_traits/070_trait_string.t

index 228f9fe..06d21e5 100644 (file)
@@ -18,6 +18,7 @@ requires 'Class::MOP'                  => '1.05';
 requires 'Data::OptList'               => '0';
 requires 'List::MoreUtils'             => '0.12';
 requires 'Package::DeprecationManager' => '0.04';
+requires 'Params::Util'                => '0';
 requires 'Scalar::Util'                => '1.19';
 requires 'Sub::Exporter'               => '0.980';
 requires 'Sub::Name'                   => '0';
index 7323bb7..88c1f44 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 
 use List::Util ();
+use Params::Util ();
 
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
@@ -30,7 +31,7 @@ sub _inline_check_arguments {
 
     return $self->_inline_throw_error(
         q{'The argument passed to first must be a code reference'})
-        . q{if $_[0] && ( ref $_[0] || q{} ) ne 'CODE';};
+        . q{ unless Params::Util::_CODELIKE( $_[0] );};
 }
 
 sub _return_value {
index e6ac60d..dd7c7db 100644 (file)
@@ -3,6 +3,8 @@ package Moose::Meta::Method::Accessor::Native::Array::grep;
 use strict;
 use warnings;
 
+use Params::Util ();
+
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
@@ -28,7 +30,7 @@ sub _inline_check_arguments {
 
     return $self->_inline_throw_error(
         q{'The argument passed to grep must be a code reference'})
-        . q{if $_[0] && ( ref $_[0] || q{} ) ne 'CODE';};
+        . q{ unless Params::Util::_CODELIKE( $_[0] );};
 }
 
 sub _return_value {
index bbaad84..26d488f 100644 (file)
@@ -3,6 +3,8 @@ package Moose::Meta::Method::Accessor::Native::Array::join;
 use strict;
 use warnings;
 
+use Moose::Util ();
+
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
@@ -28,7 +30,7 @@ sub _inline_check_arguments {
 
     return $self->_inline_throw_error(
         q{'The argument passed to join must be a string'})
-        . ' unless defined $_[0] && ! ref $_[0];';
+        . ' unless Moose::Util::_STRINGLIKE( $_[0] );';
 }
 
 sub _return_value {
index 3013fe0..ad25551 100644 (file)
@@ -3,6 +3,8 @@ package Moose::Meta::Method::Accessor::Native::Array::map;
 use strict;
 use warnings;
 
+use Params::Util ();
+
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
@@ -28,7 +30,7 @@ sub _inline_check_arguments {
 
     return $self->_inline_throw_error(
         q{'The argument passed to map must be a code reference'})
-        . q{if $_[0] && ( ref $_[0] || q{} ) ne 'CODE';};
+        . q{ unless Params::Util::_CODELIKE( $_[0] );};
 }
 
 sub _return_value {
index b905564..f5cea6d 100644 (file)
@@ -3,7 +3,8 @@ package Moose::Meta::Method::Accessor::Native::Array::natatime;
 use strict;
 use warnings;
 
-use List::MoreUtils;
+use List::MoreUtils ();
+use Params::Util ();
 
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
@@ -34,7 +35,7 @@ sub _inline_check_arguments {
         . ' unless defined $_[0] && $_[0] =~ /^\\d+$/;' . "\n"
         . $self->_inline_throw_error(
         q{'The second argument passed to natatime must be a code reference'})
-        . q{ if defined $_[1] && ( ref $_[1] || q{} ) ne 'CODE';};
+        . q{ if @_ == 2 && ! Params::Util::_CODELIKE( $_[1] );};
 }
 
 sub _inline_return_value {
index 8b5e72a..797b6b6 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 
 use List::Util ();
+use Params::Util ();
 
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
@@ -30,7 +31,7 @@ sub _inline_check_arguments {
 
     return $self->_inline_throw_error(
         q{'The argument passed to reduce must be a code reference'})
-        . q{if $_[0] && ( ref $_[0] || q{} ) ne 'CODE';};
+        . q{ unless Params::Util::_CODELIKE( $_[0] );};
 }
 
 sub _return_value {
index 57da995..9f18cb7 100644 (file)
@@ -3,6 +3,8 @@ package Moose::Meta::Method::Accessor::Native::Array::sort;
 use strict;
 use warnings;
 
+use Params::Util ();
+
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
@@ -25,7 +27,7 @@ sub _inline_check_arguments {
 
     return $self->_inline_throw_error(
         q{'The argument passed to sort must be a code reference'})
-        . q{if $_[0] && ( ref $_[0] || q{} ) ne 'CODE';};
+        . q{ if @_ && ! Params::Util::_CODELIKE( $_[0] );};
 }
 
 sub _return_value {
index 41a895f..7c8c40e 100644 (file)
@@ -3,6 +3,8 @@ package Moose::Meta::Method::Accessor::Native::Array::sort_in_place;
 use strict;
 use warnings;
 
+use Params::Util ();
+
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
@@ -25,7 +27,7 @@ sub _inline_check_arguments {
 
     return $self->_inline_throw_error(
         q{'The argument passed to sort_in_place must be a code reference'})
-        . q{if $_[0] && ( ref $_[0] || q{} ) ne 'CODE';};
+        . q{ if @_ && ! Params::Util::_CODELIKE( $_[0] );};
 }
 
 sub _adds_members { 0 }
index 23492e7..4dc64bb 100644 (file)
@@ -3,6 +3,9 @@ package Moose::Meta::Method::Accessor::Native::String::match;
 use strict;
 use warnings;
 
+use Moose::Util ();
+use Params::Util ();
+
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
@@ -28,7 +31,7 @@ sub _inline_check_arguments {
 
     return $self->_inline_throw_error(
         q{'The argument passed to match must be a string or regexp reference'}
-    ) . q{ unless ! ref $_[0] || ref $_[0] eq 'Regexp';};
+    ) . q{ unless Moose::Util::_STRINGLIKE( $_[0] ) || Params::Util::_REGEX( $_[0] );};
 }
 
 sub _return_value {
index 5650fc0..f360080 100644 (file)
@@ -3,6 +3,9 @@ package Moose::Meta::Method::Accessor::Native::String::replace;
 use strict;
 use warnings;
 
+use Moose::Util ();
+use Params::Util ();
+
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
@@ -30,10 +33,10 @@ sub _inline_check_arguments {
     return $self->_inline_throw_error(
         q{'The first argument passed to replace must be a string or regexp reference'}
         )
-        . q{ unless ! ref $_[0] || ref $_[0] eq 'Regexp';} . "\n"
+        . q{ unless Moose::Util::_STRINGLIKE( $_[0] ) || Params::Util::_REGEX( $_[0] );}
         . $self->_inline_throw_error(
         q{'The second argument passed to replace must be a string or code reference'}
-        ) . q{ unless ! ref $_[1] || ref $_[1] eq 'CODE';};
+        ) . q{ unless Moose::Util::_STRINGLIKE( $_[1] ) || Params::Util::_CODELIKE( $_[1] );};
 }
 
 sub _potential_value {
index 9f5d8c8..4a48f1f 100644 (file)
@@ -3,6 +3,8 @@ package Moose::Meta::Method::Accessor::Native::String::substr;
 use strict;
 use warnings;
 
+use Moose::Util ();
+
 our $VERSION = '1.14';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
@@ -86,17 +88,17 @@ sub _inline_check_arguments {
     my $code
         = $self->_inline_throw_error(
         q{'The first argument passed to substr must be an integer'})
-        . q{ if ref $offset || $offset !~ /^-?\\d+$/;} . "\n"
+        . q{ unless $offset =~ /^-?\\d+$/;} . "\n"
         . $self->_inline_throw_error(
-        q{'The second argument passed to substr must be a positive integer'})
-        . q{ if ref $length || $offset !~ /^-?\\d+$/;};
+        q{'The second argument passed to substr must be an integer'})
+        . q{ unless $length =~ /^-?\\d+$/;};
 
     if ($for_writer) {
         $code
             .= "\n"
             . $self->_inline_throw_error(
             q{'The third argument passed to substr must be a string'})
-            . q{ unless defined $replacement && ! ref $replacement;};
+            . q{ unless Moose::Util::_STRINGLIKE($replacement);};
     }
 
     return $code;
index 638e40e..5896f41 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 
 use Data::OptList;
+use Params::Util qw( _STRING );
 use Sub::Exporter;
 use Scalar::Util 'blessed';
 use Class::MOP   0.60;
@@ -285,6 +286,14 @@ sub meta_class_alias {
     _create_alias('Class', $to, $trait, $from);
 }
 
+# XXX - this should be added to Params::Util
+sub _STRINGLIKE ($) {
+    return _STRING( $_[0] )
+        || ( blessed $_[0]
+        && overload::Method( $_[0], q{""} )
+        && length "$_[0]" );
+}
+
 1;
 
 __END__
index 58df448..33cd4e5 100644 (file)
@@ -95,6 +95,18 @@ use Test::Moose;
 }
 
 {
+    package Overloader;
+
+    use overload
+        '&{}' => sub { ${ $_[0] } },
+        bool  => sub {1};
+
+    sub new {
+        bless \$_[1], $_[0];
+    }
+}
+
+{
     run_tests(build_class);
     run_tests( build_class( lazy => 1, default => sub { [ 42, 84 ] } ) );
     run_tests( build_class( trigger => sub { } ) );
@@ -493,6 +505,13 @@ sub run_tests {
         qr/The argument passed to grep must be a code reference/,
             'throws an error when passing a non coderef to grep';
 
+        my $overloader = Overloader->new( sub { $_ < 5 } );
+        is_deeply(
+            [ $obj->grep($overloader) ],
+            [ 2 .. 4 ],
+            'grep works with obj that overload code dereferencing'
+        );
+
         is_deeply(
             [ $obj->grep_curried ],
             [ 2 .. 4 ],
index f5d4ab7..d3029b7 100644 (file)
@@ -234,8 +234,8 @@ sub run_tests {
             'substr throws an error when first argument is not an integer';
 
         throws_ok { $obj->substr( 1, {} ) }
-        qr/The second argument passed to substr must be a positive integer/,
-            'substr throws an error when second argument is not a positive integer';
+        qr/The second argument passed to substr must be an integer/,
+            'substr throws an error when second argument is not an integer';
 
         throws_ok { $obj->substr( 1, 2, {} ) }
         qr/The third argument passed to substr must be a string/,