fixed readme
[gitmo/MooseX-Dependent.git] / README
diff --git a/README b/README
index fe771eb..7348c28 100644 (file)
--- a/README
+++ b/README
@@ -2,96 +2,118 @@ NAME
     MooseX::Types::Parameterizable - Create your own Parameterizable Types.
 
 SYNOPSIS
-    Within your MooseX::Types declared library module:
+    The follow is example usage.
 
+        package Test::MooseX::Types::Parameterizable::Synopsis;
+
+        use Moose;
         use MooseX::Types::Parameterizable qw(Parameterizable);
-        
-            subtype Set,
-                    as class_type("Set::Scalar");
+        use MooseX::Types::Moose qw(Str Int ArrayRef);
+        use MooseX::Types -declare=>[qw(Varchar)];
+
+        ## Create a type constraint that is a string but parameterizes an integer
+        ## that is used as a maximum length constraint on that string, similar to
+        ## a SQL Varchar database type.
+
+        subtype Varchar,
+          as Parameterizable[Str,Int],
+          where {
+            my($string, $int) = @_;
+            $int >= length($string) ? 1:0;
+          },
+          message { "'$_' is too long"  };
+
+        coerce Varchar,
+          from ArrayRef,
+          via { 
+            my ($arrayref, $int) = @_;
+            join('', @$arrayref);
+          };
+
+        has 'varchar_five' => (isa=>Varchar[5], is=>'ro', coerce=>1);
+        has 'varchar_ten' => (isa=>Varchar[10], is=>'ro');
+  
+        ## Object created since attributes are valid
+        my $object1 = __PACKAGE__->new(
+            varchar_five => '1234',
+            varchar_ten => '123456789',
+        );
+
+        ## Dies with an invalid constraint for 'varchar_five'
+        my $object2 = __PACKAGE__->new(
+            varchar_five => '12345678',  ## too long!
+            varchar_ten => '123456789',
+        );
+
+        ## varchar_five coerces as expected
+        my $object3 = __PACKAGE__->new(
+            varchar_five => [qw/aa bb/],  ## coerces to "aabb"
+            varchar_ten => '123456789',
+        );
+
+    See t/05-pod-examples.t for runnable versions of all POD code
 
-        subtype UniqueInt,
-            as Parameterizable[Int, Set],
+DESCRIPTION
+    A MooseX::Types library for creating parameterizable types. A
+    parameterizable type constraint for all intents and uses is a subclass
+    of a parent type, but adds additional type parameters which are
+    available to constraint callbacks (such as inside the 'where' clause of
+    a type constraint definition) or in the coercions.
+
+    If you have Moose experience, you probably are familiar with the builtin
+    parameterizable type constraints 'ArrayRef' and 'HashRef'. This type
+    constraint lets you generate your own versions of parameterized
+    constraints that work similarly. See Moose::Util::TypeConstraints for
+    more.
+
+    Using this type constraint, you can generate new type constraints that
+    have additional runtime advice, such as being able to specify maximum
+    and minimum values for an Int (integer) type constraint:
+
+        subtype Range,
+            as Dict[max=>Int, min=>Int],
             where {
-                my ($int, $set) = @_;
-                return !$set->has($int);
+                my ($range) = @_;
+                return $range->{max} > $range->{min};
             };
-                
-            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 RangedInt,
+            as Parameterizable[Int, Range],
+            where {
+                my ($value, $range) = @_;
+                return ($value >= $range->{min} &&
+                 $value <= $range->{max});
+            };
         
-            UniqueInt([$negative_set])->check(100);  ## Throws exception
+        RangedInt([{min=>10,max=>100}])->check(50); ## OK
+        RangedInt([{min=>50, max=>75}])->check(99); ## Not OK, 99 exceeds max
 
-DESCRIPTION
-    A MooseX::Types library for creating parameterizable types. A
-    parameterizable type constraint for all intents and uses is a subclass
-    of a parent type, but adds a secondary type parameter which is available
-    to constraint callbacks (such as inside the 'where' clause) or in the
-    coercions.
-
-    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
-
-    This throws a hard Moose exception. You'll need to capture it in an eval
-    or related exception catching system (see TryCatch).
-
-            RangedInt([{min=>99, max=>10}])->check(10); ## Not OK, not a valid Range!
+    The type parameter must be valid against the type constraint given. If
+    you pass an invalid value this throws a hard Moose exception. You'll
+    need to capture it in an eval or related exception catching system (see
+    TryCatch or <Try::Tiny>.) For example the following would throw a hard
+    error (and not just return false)
+
+        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 +122,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 +136,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 +181,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 +203,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 +247,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 - Need more tests.
 
 TYPE CONSTRAINTS
     This type library defines the following constraints.