From: John Napiorkowski Date: Wed, 23 Jun 2010 23:37:53 +0000 (-0400) Subject: tabs to spaces X-Git-Tag: 0.02~12 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMooseX-Dependent.git;a=commitdiff_plain;h=9be9bf16f41c9d2de3432ac82e7d27fa23701848 tabs to spaces --- diff --git a/lib/MooseX/Types/Parameterizable.pm b/lib/MooseX/Types/Parameterizable.pm index 1f257da..c28a086 100644 --- a/lib/MooseX/Types/Parameterizable.pm +++ b/lib/MooseX/Types/Parameterizable.pm @@ -18,9 +18,9 @@ MooseX::Types::Parameterizable - Create your own Parameterizable Types. Within your L declared library module: use MooseX::Types::Parameterizable qw(Parameterizable); - - subtype Set, - as class_type("Set::Scalar"); + + subtype Set, + as class_type("Set::Scalar"); subtype UniqueInt, as Parameterizable[Int, Set], @@ -28,31 +28,31 @@ Within your L declared library module: my ($int, $set) = @_; return !$set->has($int); }; - - subtype PositiveSet, - as Set, - where { - my ($set) = @_; - return !grep {$_ <0 } $set->members; - }; - + + subtype PositiveSet, + as Set, + where { + my ($set) = @_; + return !grep {$_ <0 } $set->members; + }; + subtype PositiveUniqueInt, as UniqueInt[PositiveSet]; - - my $set = Set::Scalar->new(1,2,3); - - UniqueInt([$set])->check(100); ## Okay, 100 isn't in (1,2,3) - UniqueInt([$set])->check(-99); ## Okay, -99 isn't in (1,2,3) - UniqueInt([$set])->check(2); ## Not OK, 2 is in (1,2,3) - - PositiveUniqueInt([$set])->check(100); ## Okay, 100 isn't in (1,2,3) - PositiveUniqueInt([$set])->check(-99); ## Not OK, -99 not Positive Int - PositiveUniqueInt([$set])->check(2); ## Not OK, 2 is in (1,2,3) - - my $negative_set = Set::Scalar->new(-1,-2,-3); - - UniqueInt([$negative_set])->check(100); ## Throws exception - + + my $set = Set::Scalar->new(1,2,3); + + UniqueInt([$set])->check(100); ## Okay, 100 isn't in (1,2,3) + UniqueInt([$set])->check(-99); ## Okay, -99 isn't in (1,2,3) + UniqueInt([$set])->check(2); ## Not OK, 2 is in (1,2,3) + + PositiveUniqueInt([$set])->check(100); ## Okay, 100 isn't in (1,2,3) + PositiveUniqueInt([$set])->check(-99); ## Not OK, -99 not Positive Int + PositiveUniqueInt([$set])->check(2); ## Not OK, 2 is in (1,2,3) + + my $negative_set = Set::Scalar->new(-1,-2,-3); + + UniqueInt([$negative_set])->check(100); ## Throws exception + =head1 DESCRIPTION A L library for creating parameterizable types. A parameterizable type @@ -64,46 +64,46 @@ This allows you to create a type that has additional runtime advice, such as a set of numbers within which another number must be unique, or allowable ranges for a integer, such as in: - subtype Range, - as Dict[max=>Int, min=>Int], - where { - my ($range) = @_; - return $range->{max} > $range->{min}; - }; - - subtype RangedInt, - as Parameterizable[Int, Range], - where { - my ($value, $range) = @_; - return ($value >= $range->{min} && - $value <= $range->{max}); - }; - - RangedInt([{min=>10,max=>100}])->check(50); ## OK - RangedInt([{min=>50, max=>75}])->check(99); ## Not OK, 99 exceeds max - + subtype Range, + as Dict[max=>Int, min=>Int], + where { + my ($range) = @_; + return $range->{max} > $range->{min}; + }; + + subtype RangedInt, + as Parameterizable[Int, Range], + where { + my ($value, $range) = @_; + return ($value >= $range->{min} && + $value <= $range->{max}); + }; + + RangedInt([{min=>10,max=>100}])->check(50); ## OK + RangedInt([{min=>50, max=>75}])->check(99); ## Not OK, 99 exceeds max + This throws a hard Moose exception. You'll need to capture it in an eval or -related exception catching system (see L). +related exception catching system (see L or .) - RangedInt([{min=>99, max=>10}])->check(10); ## Not OK, not a valid Range! + RangedInt([{min=>99, max=>10}])->check(10); ## Not OK, not a valid Range! If you can't accept a hard exception here, you'll need to test the constraining values first, as in: - my $range = {min=>99, max=>10}; - if(my $err = Range->validate($range)) { - ## Handle #$err - } else { - RangedInt($range)->check(99); - } - + my $range = {min=>99, max=>10}; + if(my $err = Range->validate($range)) { + ## Handle #$err + } else { + RangedInt($range)->check(99); + } + Please note that for ArrayRef or HashRef parameterizable type constraints, as in the example above, as a convenience we automatically ref the incoming type parameters, so that the above could also be written as: - RangedInt([min=>10,max=>100])->check(50); ## OK - RangedInt([min=>50, max=>75])->check(99); ## Not OK, 99 exceeds max - RangedInt([min=>99, max=>10])->check(10); ## Exception, not a valid Range! + RangedInt([min=>10,max=>100])->check(50); ## OK + RangedInt([min=>50, max=>75])->check(99); ## Not OK, 99 exceeds max + RangedInt([min=>99, max=>10])->check(10); ## Exception, not a valid Range! This is the preferred syntax, as it improve readability and adds to the conciseness of your type constraint declarations. An exception wil be thrown if @@ -111,8 +111,8 @@ your type parameters don't match the required reference type. Also not that if you 'chain' parameterization results with a method call like: - TypeConstraint([$ob])->method; - + TypeConstraint([$ob])->method; + You need to have the "(...)" around the ArrayRef in the Type Constraint parameters. This seems to have something to do with the precendent level of "->". Patches or thoughts welcomed. You only need to do this in the above @@ -124,39 +124,39 @@ When subclassing a parameterizable type you must be careful to match either the required type parameter type constraint, or if re-parameterizing, the new type constraints are a subtype of the parent. For example: - subtype RangedInt, - as Parameterizable[Int, Range], - where { - my ($value, $range) = @_; - return ($value >= $range->{min} && - $value =< $range->{max}); - }; + subtype RangedInt, + as Parameterizable[Int, Range], + where { + my ($value, $range) = @_; + return ($value >= $range->{min} && + $value =< $range->{max}); + }; Example subtype with additional constraints: - subtype PositiveRangedInt, - as RangedInt, - where { - shift >= 0; - }; - + subtype PositiveRangedInt, + as RangedInt, + where { + shift >= 0; + }; + Or you could have done the following instead: - ## Subtype of Int for positive numbers - subtype PositiveInt, - as Int, - where { - my ($value, $range) = @_; - return $value >= 0; - }; - - ## subtype Range to re-parameterize Range with subtypes - subtype PositiveRange, - as Range[max=>PositiveInt, min=>PositiveInt]; - - ## create subtype via reparameterizing - subtype PositiveRangedInt, - as RangedInt[PositiveRange]; + ## Subtype of Int for positive numbers + subtype PositiveInt, + as Int, + where { + my ($value, $range) = @_; + return $value >= 0; + }; + + ## subtype Range to re-parameterize Range with subtypes + subtype PositiveRange, + as Range[max=>PositiveInt, min=>PositiveInt]; + + ## create subtype via reparameterizing + subtype PositiveRangedInt, + as RangedInt[PositiveRange]; Notice how re-parameterizing the parameterizable type 'RangedInt' works slightly differently from re-parameterizing 'PositiveRange' Although it initially takes @@ -167,21 +167,21 @@ type for the parameterizable type. In other words, given the example above, a t constraint of 'RangedInt' would have a parent of 'Int', not 'Parameterizable' and for all intends and uses you could stick it wherever you'd need an Int. - subtype NameAge, - as Tuple[Str, Int]; - - ## re-parameterized subtypes of NameAge containing a Parameterizable Int - subtype NameBetween18and35Age, - as NameAge[ - Str, - PositiveRangedInt[min=>18,max=>35], - ]; + subtype NameAge, + as Tuple[Str, Int]; + + ## re-parameterized subtypes of NameAge containing a Parameterizable Int + subtype NameBetween18and35Age, + as NameAge[ + Str, + PositiveRangedInt[min=>18,max=>35], + ]; One caveat is that you can't stick an unparameterized parameterizable type inside a structure, such as L since that would require the ability to convert a 'containing' type constraint into a parameterizable type, which is a capacity we current don't have. - + =head2 Coercions Parameterizable types have some limited support for coercions. Several things must @@ -189,41 +189,41 @@ be kept in mind. The first is that the coercion targets the type constraint which is being made parameterizable, Not the parameterizable type. So for example if you create a Parameterizable type like: - subtype RequiredAgeInYears, - as Int; + subtype RequiredAgeInYears, + as Int; - subtype PersonOverAge, - as Parameterizable[Person, RequiredAgeInYears] - where { - my ($person, $required_years_old) = @_; - return $person->years_old > $required_years_old; - } + subtype PersonOverAge, + as Parameterizable[Person, RequiredAgeInYears] + where { + my ($person, $required_years_old) = @_; + return $person->years_old > $required_years_old; + } This would validate the following: - - my $person = Person->new(age=>35); - PersonOverAge([18])->check($person); - + + my $person = Person->new(age=>35); + PersonOverAge([18])->check($person); + You can then apply the following coercion - coerce PersonOverAge, - from Dict[age=>int], - via {Person->new(%$_)}, - from Int, - via {Person->new(age=>$_)}; - + coerce PersonOverAge, + from Dict[age=>int], + via {Person->new(%$_)}, + from Int, + via {Person->new(age=>$_)}; + This coercion would then apply to all the following: - PersonOverAge([18])->check(30); ## via the Int coercion - PersonOverAge([18])->check({age=>50}); ## via the Dict coercion + PersonOverAge([18])->check(30); ## via the Int coercion + PersonOverAge([18])->check({age=>50}); ## via the Dict coercion However, you are not allowed to place coercions on parameterizable types that have had their constraining value filled, nor subtypes of such. For example: - coerce PersonOverAge[18], - from DateTime, - via {$_->years}; - + coerce PersonOverAge[18], + from DateTime, + via {$_->years}; + That would generate a hard exception. This is a limitation for now until I can devise a smarter way to cache the generated type constraints. However, I doubt it will be a significant limitation, since the general use case is supported. @@ -231,24 +231,24 @@ it will be a significant limitation, since the general use case is supported. Lastly, the constraining value is available in the coercion in much the same way it is available to the constraint. - ## Create a type constraint where a Person must be in the set - subtype PersonInSet, - as Parameterizable[Person, PersonSet], - where { - my ($person, $person_set) = @_; - $person_set->find($person); - } - - coerce PersonInSet, - from HashRef, - via { - my ($hashref, $person_set) = @_; - return $person_set->create($hash_ref); - }; + ## Create a type constraint where a Person must be in the set + subtype PersonInSet, + as Parameterizable[Person, PersonSet], + where { + my ($person, $person_set) = @_; + $person_set->find($person); + } + + coerce PersonInSet, + from HashRef, + via { + my ($hashref, $person_set) = @_; + return $person_set->create($hash_ref); + }; =head2 Recursion - TBD + TBD =head1 TYPE CONSTRAINTS @@ -270,7 +270,7 @@ Moose::Util::TypeConstraints::get_type_constraint_registry->add_type_constraint( MooseX::Meta::TypeConstraint::Parameterizable->new( name => 'MooseX::Types::Parameterizable::Parameterizable', parent => find_type_constraint('Any'), - constraint => sub {1}, + constraint => sub {1}, ) );