From: Fuji, Goro Date: Sat, 13 Nov 2010 14:13:16 +0000 (+0900) Subject: Lazy initialization of coercions X-Git-Tag: 0.87~2 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=568f88f209d3a7d30ed799f3434dd865842d1aa3;p=gitmo%2FMouse.git Lazy initialization of coercions --- diff --git a/lib/Mouse/Meta/TypeConstraint.pm b/lib/Mouse/Meta/TypeConstraint.pm index c73fa89..15fe6e9 100644 --- a/lib/Mouse/Meta/TypeConstraint.pm +++ b/lib/Mouse/Meta/TypeConstraint.pm @@ -67,9 +67,16 @@ sub new { $self->compile_type_constraint() if !$args{hand_optimized_type_constraint}; - if($args{type_constraints}) { - $self->_compile_union_type_coercion(); + if($args{type_constraints}) { # union types + foreach my $type(@{$self->{type_constraints}}){ + if($type->has_coercion){ + # set undef for has_coercion() + $self->{_compiled_type_coercion} = undef; + last; + } + } } + return $self; } @@ -120,60 +127,62 @@ sub _add_type_coercions { # ($self, @pairs) push @{$coercion_map}, [ $type => $action ]; } - $self->_compile_type_coercion(); + $self->{_compiled_type_coercion} = undef; return; } -sub _compile_type_coercion { +sub _compiled_type_coercion { my($self) = @_; - my @coercions; - - foreach my $pair(@{$self->{coercion_map}}) { - push @coercions, [ $pair->[0]->_compiled_type_constraint, $pair->[1] ]; - } - - $self->{_compiled_type_coercion} = sub { - my($thing) = @_; - foreach my $pair (@coercions) { - #my ($constraint, $converter) = @$pair; - if ($pair->[0]->($thing)) { - local $_ = $thing; - return $pair->[1]->($thing); - } - } - return $thing; - }; - return; -} + my $coercion = $self->{_compiled_type_coercion}; + return $coercion if defined $coercion; -sub _compile_union_type_coercion { - my($self) = @_; - - my @coercions; - foreach my $type(@{$self->{type_constraints}}){ - if($type->has_coercion){ - push @coercions, $type; + if(!$self->{type_constraints}) { + my @coercions; + foreach my $pair(@{$self->{coercion_map}}) { + push @coercions, + [ $pair->[0]->_compiled_type_constraint, $pair->[1] ]; } + + $coercion = sub { + my($thing) = @_; + foreach my $pair (@coercions) { + #my ($constraint, $converter) = @$pair; + if ($pair->[0]->($thing)) { + local $_ = $thing; + return $pair->[1]->($thing); + } + } + return $thing; + }; } - if(@coercions){ - $self->{_compiled_type_coercion} = sub { - my($thing) = @_; - foreach my $type(@coercions){ - my $value = $type->coerce($thing); - return $value if $self->check($value); + else { # for union type + my @coercions; + foreach my $type(@{$self->{type_constraints}}){ + if($type->has_coercion){ + push @coercions, $type; } - return $thing; - }; + } + if(@coercions){ + $coercion = sub { + my($thing) = @_; + foreach my $type(@coercions){ + my $value = $type->coerce($thing); + return $value if $self->check($value); + } + return $thing; + }; + } } - return; + + return( $self->{_compiled_type_coercion} = $coercion ); } sub coerce { my $self = shift; return $_[0] if $self->check(@_); - my $coercion = $self->{_compiled_type_coercion} + my $coercion = $self->_compiled_type_coercion or $self->throw_error("Cannot coerce without a type coercion"); return $coercion->(@_); } diff --git a/lib/Mouse/PurePerl.pm b/lib/Mouse/PurePerl.pm index 174f4a9..0e5ed43 100644 --- a/lib/Mouse/PurePerl.pm +++ b/lib/Mouse/PurePerl.pm @@ -613,7 +613,6 @@ sub _identity { Scalar::Util::refaddr($_[0]) } # overload 0+ sub type_parameter { $_[0]->{type_parameter} } sub _compiled_type_constraint{ $_[0]->{compiled_type_constraint} } -sub _compiled_type_coercion { $_[0]->{_compiled_type_coercion} } sub __is_parameterized { exists $_[0]->{type_parameter} } sub has_coercion { exists $_[0]->{_compiled_type_coercion} } diff --git a/t/001_mouse/043-parameterized-type.t b/t/001_mouse/043-parameterized-type.t index 24dbac4..e3e4cda 100644 --- a/t/001_mouse/043-parameterized-type.t +++ b/t/001_mouse/043-parameterized-type.t @@ -122,7 +122,8 @@ use Tie::Array; my $bar = Bar->new(list => [ qw(a b c) ]); is_deeply( $bar->list, \@list, "list is as expected"); - } "coercion works"; + } "coercion works" + or diag( Mouse::Util::TypeConstraints::find_type_constraint("Bar::List")->dump ); throws_ok { Bar->new(list => [ { 1 => 2 }, 2, 3 ]); diff --git a/xs-src/MouseTypeConstraints.xs b/xs-src/MouseTypeConstraints.xs index e1670f0..f22a869 100644 --- a/xs-src/MouseTypeConstraints.xs +++ b/xs-src/MouseTypeConstraints.xs @@ -670,7 +670,6 @@ BOOT: INSTALL_SIMPLE_READER(TypeConstraint, type_parameter); INSTALL_SIMPLE_READER_WITH_KEY(TypeConstraint, _compiled_type_constraint, compiled_type_constraint); - INSTALL_SIMPLE_READER(TypeConstraint, _compiled_type_coercion); /* Mouse specific */ INSTALL_SIMPLE_PREDICATE_WITH_KEY(TypeConstraint, has_coercion, _compiled_type_coercion); INSTALL_SIMPLE_PREDICATE_WITH_KEY(TypeConstraint, __is_parameterized, type_parameter); /* Mouse specific */