X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=README;h=3c233a2730418feb3cc370df7e9e6baf32f839c6;hb=6c0e3459abf23be46753e90396936be6d748adc9;hp=fe771eb950fc83c30968a27ac35bd2e921541b49;hpb=d1cfb0438ab08c82be373f613ecaf6c2d175d4e8;p=gitmo%2FMooseX-Dependent.git diff --git a/README b/README index fe771eb..3c233a2 100644 --- a/README +++ b/README @@ -5,9 +5,9 @@ SYNOPSIS Within your MooseX::Types 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], @@ -15,30 +15,30 @@ SYNOPSIS my ($int, $set) = @_; return !$set->has($int); }; - - 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); + subtype PositiveSet, + as Set, + where { + my ($set) = @_; + return !grep {$_ <0 } $set->members; + }; - UniqueInt([$negative_set])->check(100); ## Throws exception + 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 DESCRIPTION A MooseX::Types library for creating parameterizable types. A @@ -51,47 +51,47 @@ DESCRIPTION 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 TryCatch). + or related exception catching system (see TryCatch 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 @@ -100,7 +100,7 @@ DESCRIPTION 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 @@ -114,39 +114,39 @@ DESCRIPTION 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 @@ -159,15 +159,15 @@ DESCRIPTION '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 MooseX::Types::Structured since that @@ -181,41 +181,41 @@ DESCRIPTION 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. @@ -225,23 +225,23 @@ DESCRIPTION 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); + }; Recursion - TBD + TBD TYPE CONSTRAINTS This type library defines the following constraints.