Author: wayland
Date: 2009-02-24 00:33:42 +0100 (Tue, 24 Feb 2009)
New Revision: 25503

Added:
   docs/Perl6/Spec/S14-roles-and-parametric-types.pod
Modified:
   docs/Perl6/Spec/S12-objects.pod
   docs/Perl6/Spec/S29-functions.pod
Log:
S29: s/Container.pod/Containers.pod/
S14/S12: Extracted S14 from S12, added Jonathan's blog entry, a bit from S02, 
and a bit 
from the spectests


Modified: docs/Perl6/Spec/S12-objects.pod
===================================================================
--- docs/Perl6/Spec/S12-objects.pod     2009-02-23 21:06:52 UTC (rev 25502)
+++ docs/Perl6/Spec/S12-objects.pod     2009-02-23 23:33:42 UTC (rev 25503)
@@ -1105,378 +1105,6 @@
 A C<proto> declaration may not occur after a C<multi> declaration in the
 same scope.
 
-=head1 Roles
-
-Classes are primarily in charge of object management, and only
-secondarily in charge of software reuse.  In PerlĀ 6, roles take over
-the job of managing software reuse.  Depending on how you care to look
-at it, a role is like a partial class, or an interface with default
-implementation, or a set of generic methods and their associated data,
-or a class closed at compile time.
-
-Roles may be composed into a class at compile time, in which case
-you get automatic detection of conflicting methods.  A role may also
-be mixed into a class or object at run time to produce an anonymous
-derived class with extra capabilities, but in this case conflicting
-methods are overridden by the new role silently.  In either case,
-a class is necessary for instantiation--a role may not be directly
-instantiated.
-
-A role is declared like a class, but with a C<role> keyword:
-
-    role Pet {
-        method feed ($food) {
-            $food.open_can;
-            $food.put_in_bowl;
-            self.eat($food);
-        }
-    }
-
-A role may not inherit from a class, but may be composed of other
-roles.  However, this "crony" composition is not evaluated until
-class composition time.  This means that if two roles bring in the
-same crony, there's no conflict--it's just as if the class pulled in
-the crony role itself and the respective roles didn't.  A role may
-never conflict with itself regardless of its method of incorporation.
-A role that brings in two conflicting crony roles I<may> resolve them
-as if it were a class.  This solution is accepted by the class unless
-the class supplies its own solution.  If two different roles resolve
-the same crony conflict two different ways, those roles are themselves
-in conflict and must be resolved by a "more derived" role or the class.
-
-A role doesn't know its own type until it is composed into a class.
-Any mention of its main type (such as C<::?CLASS>) is generic, as is
-any reference to C<self> or the type of the invocant.  You can use
-a role name as a type, but only for constraints, not for declaring
-actual objects.  (However, if you use a role as if it were a class,
-an anonymous class is generated that composes the role, which provides
-a way to force a role to test its crony composition for infelicities.)
-
-A role's main type is generic by default, but you can also parameterize
-other types explicitly using type parameters:
-
-    role Pet[::Petfood = TableScraps] {
-        method feed (Petfood $food) {...}
-    }
-
-(Note that in this case you must not use ::Petfood in the inner declaration,
-or it would rebind the type to type of the actual food parameter.)
-
-If a role merely declares methods without defining them, it degenerates
-to an interface:
-
-    role Pet {
-        method feed ($food) {...}
-        method groom () {...}
-        method scratch (:$where) {...}
-    }
-
-Note that, while these methods must become available at class
-composition time, they might be supplied by any of: another role,
-the class itself, or some superclass.  We know the methods that are
-coming from the other roles or the class, but we don't necessarily know
-the complete set of methods supplied by our super classes if they are
-open or rely on wildcard delegation.  However, the class composer is
-allowed to assume that only currently declared superclass methods or
-non-wildcard methods are going to be available.  A stub can always
-be installed somewhere to "supply" a missing method's declaration.
-
-Roles may have attributes:
-
-    role Pet {
-        has $.collar = Collar.new(Tag.new);
-        method id () { return $.collar.tag }
-        method lose_collar () { undefine $.collar }
-    }
-
-If you want to parameterize the initial value of a role attribute,
-be sure to put a double semicolon if you don't want the parameter to
-be considered part of the long name:
-
-    role Pet[::ID;; $tag] {
-        has ID $.collar .= new($tag);
-    }
-
-Within a role the C<has> declarator always indicates the declaration
-from the viewpoint of the class.  Therefore a private attribute declared
-using C<has> is private to the class, not to the role.  You may wish to 
declare an attribute
-that is hidden even from the class; a completely private role
-attribute may be declared like this:
-
-    my $!spleen;
-
-The name of such a private attribute is always considered lexically scoped.
-If a role declares private lexical items, those items are private to
-the role due to the nature of lexical scoping.  Accessors to such
-items may be exported to the class, but this is not the default.
-In particular, a role may say
-
-    trusts ::?Class;
-
-to allow C<self!attr()> access to the role's C<$!attr> variables with the
-class or from other roles composed into the class.  Conflicts between
-private accessors are also caught at composition time, but of course
-need not consider super classes, since no-one outside the current
-class (or a trusted class) can call a private accessor at all.
-(Private accessors are never virtual, and must be package qualified
-if called from a trusted scope other than our own.  That is, it's
-either C<self!attr()> or C<$obj!TrustsMe::attr().>)
-
-A role may also distinguish a shared method
-
-    has method foo ...
-    method foo ...      # same
-
-from a nonshared private method:
-
-    my method !foo ...
-    my method foo ...   # same, but &foo is aliased to &!foo
-
-Generally you'd just use a lexically scoped sub, though.
-
-    my sub foo ...
-
-[Conjectural: To put a private sub into the class, say
-
-    our sub !foo ...
-
-]
-
-A role can abstract the decision to delegate:
-
-    role Pet {
-        has $groomer handles <bathe groom trim> = hire_groomer();
-    }
-
-Note that this puts the three methods into the class as well as
-C<$groomer>.  In contrast, "C<my $!groomer>" would only put the
-three methods; the attribute itself is private to the role.
-
-A role is allowed to declare an additional inheritance for its class when
-that is considered an implementation detail:
-
-    role Pet {
-        is Friend;
-    }
-
-A class incorporates a role with the verb "does", like this:
-
-    class Dog is Mammal does Pet does Sentry {...}
-
-or equivalently, within the body of the class closure:
-
-    class Dog {
-        is Mammal;
-        does Pet;
-        does Sentry;
-        ...
-    }
-
-There is no ordering dependency among the roles.
-
-A class's explicit method definition hides any role definition of
-the same name.  A role method in turn hides any methods inherited
-from other classes.
-
-If there are no method name conflicts between roles (or with the
-class), then each role's methods can be installed in the class.  If,
-however, two roles try to introduce a method of the same name the
-composition of the class fails.  (Two C<has> attributes of the same
-name, whether public or private, are simply merged into one slot,
-provided the types are the same; otherwise, the composition fails.
-Role-private attributes are not merged, and from the viewpoint of
-the composition, don't even exist, except to allocate a slot for each
-such attribute.)
-
-There are several ways to solve method conflicts.  The first is simply to
-write a class method that overrides the conflicting role methods, perhaps
-figuring out which role method to call.
-
-Alternately, if the role's methods are declared C<multi>, they can be
-disambiguated based on their long name.  If the roles forget to declare
-them as multi, you can force a multi on the roles' methods by installing
-a proto stub in the class being constructed:
-
-    proto method shake {...}
-
-(This declaration need not precede the C<does> clause textually, since
-roles are not actually composed until the end of the class definition,
-at which point we know which roles are to be composed together
-in a single logical operation, as well as how the class intends to
-override the roles.)
-
-The proto method will be called if the multi fails:
-
-    proto method shake { warn "They couldn't decide" }
-
-Run-time mixins are done with C<does> and C<but>.  The C<does> binary
-operator is a mutator that derives a new anonymous class (if necessary)
-and binds the object to it:
-
-    $fido does Sentry
-
-The C<does> infix operator is non-associative, so this is a syntax error:
-
-    $fido does Sentry does Tricks does TailChasing does Scratch;
-
-You can, however, say
-
-    $fido does Sentry;
-    $fido does Tricks;
-    $fido does TailChasing;
-    $fido does Scratch;
-
-And since it returns the left side, you can also say:
-
-    ((($fido does Sentry) does Tricks) does TailChasing) does Scratch;
-
-Unlike the compile-time role composition, each of these layers on a new
-mixin with a new level of inheritance, creating a new anonymous class
-for dear old Fido, so that a C<.chase> method from C<TailChasing> hides a
-C<.chase> method from C<Sentry>.
-
-You can also mixin a precomposed set of roles:
-
-    $fido does (Sentry, Tricks, TailChasing, Scratch);
-
-This will level the playing field for collisions among the new
-set of roles, and guarantees the creation of no more than one more
-anonymous class.  Such a role still can't conflict with itself, but it
-can hide its previous methods in the parent class, and the calculation
-of what conflicts is done again for the set of roles being mixed in.
-If you can't do compile-time composition, we strongly recommend this
-approach for run-time mixins since it approximates a compile-time
-composition at least for the new roles involved.
-
-A role applied with C<does> may be parameterized with an initializer
-in parentheses, but only if the role supplies exactly one attribute
-to the mixin class:
-
-    $fido does Wag($tail);
-    $line does taint($istainted);
-
-The supplied initializer will be coerced to type of the attribute.
-Note that this initializer is in addition to any parametric type
-supplied in square brackets, which is considered part of the actual
-type name:
-
-    $myobj does Array[:of(Int)](@initial)
-
-The C<but> operator creates a copy and works on that.  It also knows
-how to generalize a particular enumerated value to its role.  So
-
-    0 but True
-
-is short for something like:
-
-    0 but Bool::True
-
-A property is defined by a role like this:
-
-    role SomeRole {
-        has SomeType $.prop is rw = 1;
-    }
-
-You can declare a property with
-
-    my int property answer;
-
-and that declares a role whose name is the same as the accessor:
-
-    my role answer {
-        has int $.answer is rw;
-    }
-
-Then you can say
-
-    $a = 0 but answer(42)
-
-Note that the parenthesized form is I<not> a subroutine or method call.
-It's just special initializing syntax for roles that contain a single
-property.  The above really means something like:
-
-    $a = ($anonymous = 0) does answer(42);
-
-which really means:
-
-    (($anonymous = 0) does answer).answer = 42;
-    $a = $anonymous;
-
-Which is why there's a C<but> operator.
-
-=head1 Traits
-
-Traits are just properties (roles) applied to declared items like
-containers or classes.  It's the declaration of the item itself that
-makes traits seem more permanent than ordinary properties.  In addition
-to adding the property, a trait can also have side effects.
-
-Traits are generally applied with the "is" keyword, though not always.
-To define a trait handler for an "is xxx" trait, define one or
-more multisubs into a property role like this:
-
-    role xxx {
-        has Int $.xxx;
-        multi trait_auxiliary:is(xxx $trait, Class $container; $arg?) {...}
-        multi trait_auxiliary:is(xxx $trait, Any $container; $arg?) {...}
-    }
-
-Then it can function as a trait.  A well-behaved trait handler will say
-
-    $container does xxx($arg);
-
-somewhere inside to set the metadata on the container correctly.
-Since a class can function as a role when it comes to parameter type
-matching, you can also say:
-
-    class MyBase {
-        multi trait_auxiliary:is(MyBase $base, Class $class; $arg?) {...}
-        multi trait_auxiliary:is(MyBase $tied, Any $container; $arg?) {...}
-    }
-
-These capture control if C<MyBase> wants to capture control of how it gets
-used by any class or container.  But usually you can just let it call
-the generic defaults:
-
-    multi trait_auxiliary:is(Class $base, Class $class; $arg?) {...}
-
-which adds C<$base> to the "isa" list of C<$class>, or
-
-    multi trait_auxiliary:is(Class $tied, Any $container; $arg?) {...}
-
-which sets the "tie" type of the container to the implementation type
-in C<$tied>.
-
-Most traits are introduced by use of a "helping verb", which could
-be something like "C<is>", or "C<will>", or "C<can>", or "C<might>",
-or "C<should>", or "C<does>".  We call these helping verbs "trait
-auxiliaries". Here's "C<will>", which (being syntactic sugar) merely
-delegates to back to "is":
-
-    multi sub trait_auxiliary:will($trait, $container; &arg) {
-        trait_auxiliary:is($trait, $container, &arg);
-    }
-
-Other traits are applied with a single word, and we call one of those a
-"trait verb".  For instance, the "C<as>" trait
-is defined something like this:
-
-    role as {
-        has ReturnType $.as;
-        multi sub trait_verb:as($container; ReturnType $arg) {
-            $container does as($arg);
-        }
-        ...
-    }
-
-Unlike compile-time roles, which all flatten out in the same class,
-compile-time traits are applied one at a time, like mixin roles.
-You can, in fact, apply a trait to a container at run time, but
-if you do, it's just an ordinary mixin role. You have to call the
-appropriate C<trait_auxiliary:is()> routine yourself if you want it to
-do any extra shenanigans.  The compiler won't call it for you at run
-time like it would at compile time.
-
 =head1 Delegation
 
 Delegation lets you pretend that some other object's methods are your own.

Added: docs/Perl6/Spec/S14-roles-and-parametric-types.pod
===================================================================
--- docs/Perl6/Spec/S14-roles-and-parametric-types.pod                          
(rev 0)
+++ docs/Perl6/Spec/S14-roles-and-parametric-types.pod  2009-02-23 23:33:42 UTC 
(rev 25503)
@@ -0,0 +1,490 @@
+=encoding utf8
+
+=head1 TITLE
+
+Synopsis 12: Roles and Parametric Types
+
+=head1 AUTHOR
+
+Larry Wall <la...@wall.org>
+
+=head1 VERSION
+
+  Maintainer: Larry Wall <la...@wall.org>
+  Date: 24 Feb 2009, extracted from S12-objects.pod
+  Last Modified: 24 Feb 2009
+  Number: 14
+  Version: 1
+
+=head1 Overview
+
+This synopsis summarizes Apocalypse 14, which discusses roles and parametric 
types.  
+
+=head1 Roles
+
+Classes are primarily in charge of object management, and only
+secondarily in charge of software reuse.  In PerlĀ 6, roles take over
+the job of managing software reuse.  Depending on how you care to look
+at it, a role is like a partial class, or an interface with default
+implementation, or a set of generic methods and their associated data,
+or a class closed at compile time.
+
+Roles may be composed into a class at compile time, in which case
+you get automatic detection of conflicting methods.  A role may also
+be mixed into a class or object at run time to produce an anonymous
+derived class with extra capabilities, but in this case conflicting
+methods are overridden by the new role silently.  In either case,
+a class is necessary for instantiation--a role may not be directly
+instantiated.
+
+A role is declared like a class, but with a C<role> keyword:
+
+    role Pet {
+        method feed ($food) {
+            $food.open_can;
+            $food.put_in_bowl;
+            self.eat($food);
+        }
+    }
+
+A role may not inherit from a class, but may be composed of other
+roles.  However, this "crony" composition is not evaluated until
+class composition time.  This means that if two roles bring in the
+same crony, there's no conflict--it's just as if the class pulled in
+the crony role itself and the respective roles didn't.  A role may
+never conflict with itself regardless of its method of incorporation.
+A role that brings in two conflicting crony roles I<may> resolve them
+as if it were a class.  This solution is accepted by the class unless
+the class supplies its own solution.  If two different roles resolve
+the same crony conflict two different ways, those roles are themselves
+in conflict and must be resolved by a "more derived" role or the class.
+
+A role doesn't know its own type until it is composed into a class.
+Any mention of its main type (such as C<::?CLASS>) is generic, as is
+any reference to C<self> or the type of the invocant.  You can use
+a role name as a type, but only for constraints, not for declaring
+actual objects.  (However, if you use a role as if it were a class,
+an anonymous class is generated that composes the role, which provides
+a way to force a role to test its crony composition for infelicities.)
+
+A role's main type is generic by default, but you can also parameterize
+other types explicitly using type parameters:
+
+    role Pet[::Petfood = TableScraps] {
+        method feed (Petfood $food) {...}
+    }
+
+(Note that in this case you must not use ::Petfood in the inner declaration,
+or it would rebind the type to type of the actual food parameter.)
+
+If a role merely declares methods without defining them, it degenerates
+to an interface:
+
+    role Pet {
+        method feed ($food) {...}
+        method groom () {...}
+        method scratch (:$where) {...}
+    }
+
+Note that, while these methods must become available at class
+composition time, they might be supplied by any of: another role,
+the class itself, or some superclass.  We know the methods that are
+coming from the other roles or the class, but we don't necessarily know
+the complete set of methods supplied by our super classes if they are
+open or rely on wildcard delegation.  However, the class composer is
+allowed to assume that only currently declared superclass methods or
+non-wildcard methods are going to be available.  A stub can always
+be installed somewhere to "supply" a missing method's declaration.
+
+Roles may have attributes:
+
+    role Pet {
+        has $.collar = Collar.new(Tag.new);
+        method id () { return $.collar.tag }
+        method lose_collar () { undefine $.collar }
+    }
+
+If you want to parameterize the initial value of a role attribute,
+be sure to put a double semicolon if you don't want the parameter to
+be considered part of the long name:
+
+    role Pet[::ID;; $tag] {
+        has ID $.collar .= new($tag);
+    }
+
+Within a role the C<has> declarator always indicates the declaration
+from the viewpoint of the class.  Therefore a private attribute declared
+using C<has> is private to the class, not to the role.  You may wish to 
declare an attribute
+that is hidden even from the class; a completely private role
+attribute may be declared like this:
+
+    my $!spleen;
+
+The name of such a private attribute is always considered lexically scoped.
+If a role declares private lexical items, those items are private to
+the role due to the nature of lexical scoping.  Accessors to such
+items may be exported to the class, but this is not the default.
+In particular, a role may say
+
+    trusts ::?Class;
+
+to allow C<self!attr()> access to the role's C<$!attr> variables with the
+class or from other roles composed into the class.  Conflicts between
+private accessors are also caught at composition time, but of course
+need not consider super classes, since no-one outside the current
+class (or a trusted class) can call a private accessor at all.
+(Private accessors are never virtual, and must be package qualified
+if called from a trusted scope other than our own.  That is, it's
+either C<self!attr()> or C<$obj!TrustsMe::attr().>)
+
+A role may also distinguish a shared method
+
+    has method foo ...
+    method foo ...      # same
+
+from a nonshared private method:
+
+    my method !foo ...
+    my method foo ...   # same, but &foo is aliased to &!foo
+
+Generally you'd just use a lexically scoped sub, though.
+
+    my sub foo ...
+
+[Conjectural: To put a private sub into the class, say
+
+    our sub !foo ...
+
+]
+
+A role can abstract the decision to delegate:
+
+    role Pet {
+        has $groomer handles <bathe groom trim> = hire_groomer();
+    }
+
+Note that this puts the three methods into the class as well as
+C<$groomer>.  In contrast, "C<my $!groomer>" would only put the
+three methods; the attribute itself is private to the role.
+
+A role is allowed to declare an additional inheritance for its class when
+that is considered an implementation detail:
+
+    role Pet {
+        is Friend;
+    }
+
+A class incorporates a role with the verb "does", like this:
+
+    class Dog is Mammal does Pet does Sentry {...}
+
+or equivalently, within the body of the class closure:
+
+    class Dog {
+        is Mammal;
+        does Pet;
+        does Sentry;
+        ...
+    }
+
+There is no ordering dependency among the roles.
+
+A class's explicit method definition hides any role definition of
+the same name.  A role method in turn hides any methods inherited
+from other classes.
+
+If there are no method name conflicts between roles (or with the
+class), then each role's methods can be installed in the class.  If,
+however, two roles try to introduce a method of the same name the
+composition of the class fails.  (Two C<has> attributes of the same
+name, whether public or private, are simply merged into one slot,
+provided the types are the same; otherwise, the composition fails.
+Role-private attributes are not merged, and from the viewpoint of
+the composition, don't even exist, except to allocate a slot for each
+such attribute.)
+
+There are several ways to solve method conflicts.  The first is simply to
+write a class method that overrides the conflicting role methods, perhaps
+figuring out which role method to call.
+
+Alternately, if the role's methods are declared C<multi>, they can be
+disambiguated based on their long name.  If the roles forget to declare
+them as multi, you can force a multi on the roles' methods by installing
+a proto stub in the class being constructed:
+
+    proto method shake {...}
+
+(This declaration need not precede the C<does> clause textually, since
+roles are not actually composed until the end of the class definition,
+at which point we know which roles are to be composed together
+in a single logical operation, as well as how the class intends to
+override the roles.)
+
+The proto method will be called if the multi fails:
+
+    proto method shake { warn "They couldn't decide" }
+
+Run-time mixins are done with C<does> and C<but>.  The C<does> binary
+operator is a mutator that derives a new anonymous class (if necessary)
+and binds the object to it:
+
+    $fido does Sentry
+
+The C<does> infix operator is non-associative, so this is a syntax error:
+
+    $fido does Sentry does Tricks does TailChasing does Scratch;
+
+You can, however, say
+
+    $fido does Sentry;
+    $fido does Tricks;
+    $fido does TailChasing;
+    $fido does Scratch;
+
+And since it returns the left side, you can also say:
+
+    ((($fido does Sentry) does Tricks) does TailChasing) does Scratch;
+
+Unlike the compile-time role composition, each of these layers on a new
+mixin with a new level of inheritance, creating a new anonymous class
+for dear old Fido, so that a C<.chase> method from C<TailChasing> hides a
+C<.chase> method from C<Sentry>.
+
+You can also mixin a precomposed set of roles:
+
+    $fido does (Sentry, Tricks, TailChasing, Scratch);
+
+This will level the playing field for collisions among the new
+set of roles, and guarantees the creation of no more than one more
+anonymous class.  Such a role still can't conflict with itself, but it
+can hide its previous methods in the parent class, and the calculation
+of what conflicts is done again for the set of roles being mixed in.
+If you can't do compile-time composition, we strongly recommend this
+approach for run-time mixins since it approximates a compile-time
+composition at least for the new roles involved.
+
+A role applied with C<does> may be parameterized with an initializer
+in parentheses, but only if the role supplies exactly one attribute
+to the mixin class:
+
+    $fido does Wag($tail);
+    $line does taint($istainted);
+
+The supplied initializer will be coerced to type of the attribute.
+Note that this initializer is in addition to any parametric type
+supplied in square brackets, which is considered part of the actual
+type name:
+
+    $myobj does Array[:of(Int)](@initial)
+
+The C<but> operator creates a copy and works on that.  It also knows
+how to generalize a particular enumerated value to its role.  So
+
+    0 but True
+
+is short for something like:
+
+    0 but Bool::True
+
+A property is defined by a role like this:
+
+    role SomeRole {
+        has SomeType $.prop is rw = 1;
+    }
+
+You can declare a property with
+
+    my int property answer;
+
+and that declares a role whose name is the same as the accessor:
+
+    my role answer {
+        has int $.answer is rw;
+    }
+
+Then you can say
+
+    $a = 0 but answer(42)
+
+Note that the parenthesized form is I<not> a subroutine or method call.
+It's just special initializing syntax for roles that contain a single
+property.  The above really means something like:
+
+    $a = ($anonymous = 0) does answer(42);
+
+which really means:
+
+    (($anonymous = 0) does answer).answer = 42;
+    $a = $anonymous;
+
+Which is why there's a C<but> operator.
+
+=head1 Traits
+
+Traits are just properties (roles) applied to declared items like
+containers or classes.  It's the declaration of the item itself that
+makes traits seem more permanent than ordinary properties.  In addition
+to adding the property, a trait can also have side effects.
+
+Traits are generally applied with the "is" keyword, though not always.
+To define a trait handler for an "is xxx" trait, define one or
+more multisubs into a property role like this:
+
+    role xxx {
+        has Int $.xxx;
+        multi trait_auxiliary:is(xxx $trait, Class $container; $arg?) {...}
+        multi trait_auxiliary:is(xxx $trait, Any $container; $arg?) {...}
+    }
+
+Then it can function as a trait.  A well-behaved trait handler will say
+
+    $container does xxx($arg);
+
+somewhere inside to set the metadata on the container correctly.
+Since a class can function as a role when it comes to parameter type
+matching, you can also say:
+
+    class MyBase {
+        multi trait_auxiliary:is(MyBase $base, Class $class; $arg?) {...}
+        multi trait_auxiliary:is(MyBase $tied, Any $container; $arg?) {...}
+    }
+
+These capture control if C<MyBase> wants to capture control of how it gets
+used by any class or container.  But usually you can just let it call
+the generic defaults:
+
+    multi trait_auxiliary:is(Class $base, Class $class; $arg?) {...}
+
+which adds C<$base> to the "isa" list of C<$class>, or
+
+    multi trait_auxiliary:is(Class $tied, Any $container; $arg?) {...}
+
+which sets the "tie" type of the container to the implementation type
+in C<$tied>.
+
+Most traits are introduced by use of a "helping verb", which could
+be something like "C<is>", or "C<will>", or "C<can>", or "C<might>",
+or "C<should>", or "C<does>".  We call these helping verbs "trait
+auxiliaries". Here's "C<will>", which (being syntactic sugar) merely
+delegates to back to "is":
+
+    multi sub trait_auxiliary:will($trait, $container; &arg) {
+        trait_auxiliary:is($trait, $container, &arg);
+    }
+
+Other traits are applied with a single word, and we call one of those a
+"trait verb".  For instance, the "C<as>" trait
+is defined something like this:
+
+    role as {
+        has ReturnType $.as;
+        multi sub trait_verb:as($container; ReturnType $arg) {
+            $container does as($arg);
+        }
+        ...
+    }
+
+Unlike compile-time roles, which all flatten out in the same class,
+compile-time traits are applied one at a time, like mixin roles.
+You can, in fact, apply a trait to a container at run time, but
+if you do, it's just an ordinary mixin role. You have to call the
+appropriate C<trait_auxiliary:is()> routine yourself if you want it to
+do any extra shenanigans.  The compiler won't call it for you at run
+time like it would at compile time.
+
+=head1 Parametric Types
+
+Types can take parameters.  Parametric types are named using square brackets, 
so:
+
+    my Hash of Array of Recipe %book;
+
+actually means:
+
+    my Hash[of => Array[of => Recipe]] %book;
+
+=head2 Parametric Roles
+
+In Perl 6, roles can also take parameters. Roles exist to enable greater 
re-use of code 
+than we could get through having plain old classes, and by allowing them to be 
+parameterized we open the door to even more re-use. Taking a simple example, 
imagine we 
+wanted to factor out a "greet" method into a role, which takes somebody's name 
and greets 
+them. We want to parameterize it on the greeting.
+
+role Greet[Str $greeting] {
+    method greet() { say "$greeting!"; }
+}
+class EnglishMan does Greet["Hello"] { }
+class Slovak does Greet["Ahoj"] { }
+class Lolcat does Greet["OH HAI"] { }
+EnglishMan.new.greet(); # Hello
+Slovak.new.greet(); # Ahoj
+Lolcat.new.greet(); # OH HAI
+
+Similarly, we could do a role for requests.
+
+role Request[Str $statement] {
+    method request($object) { say "$statement $object?"; }
+}
+class EnglishMan does Request["Please can I have a"] { }
+class Slovak does Request["Prosim si"] { }
+class Lolcat does Request["I CAN HAZ"] { }
+EnglishMan.new.request("yorkshire pudding");
+Slovak.new.request("borovicka");
+Lolcat.new.request("CHEEZEBURGER");
+
+Sadly, the Slovak output sucks here. Borovicka is the nominative form of the 
word, and we 
+need to decline it into the accusative case. But some languages don't care 
about that, and 
+we don't want to have to make them all supply a transform. Thankfully, you can 
write many 
+roles with the same short name, and a different signature, and multi-dispatch 
will pick 
+the right one for you. So we write something to produce the accusative case in 
Slovak and 
+pass it in. Here's the new code.
+
+role Request[Str $statement] {
+    method request($object) { say "$statement $object?"; }
+}
+role Request[Str $statement, &transform] {
+    method request($object) {
+        say "$statement " ~ transform($object) ~ "?";
+    }
+}
+module Language::Slovak {
+    sub accusative($nom) {
+        # ...and before some smartass points it out, I know
+        # I'm missing some of the masculine animate declension...
+        return $nom.subst(/a$/, 'u');
+    }
+}
+class EnglishMan does Request["Please can I have a"] { }
+class Slovak does Request["Prosim si", &Language::Slovak::accusative] { }
+class Lolcat does Request["I CAN HAZ"] { }
+EnglishMan.new.request("yorkshire pudding");
+Slovak.new.request("borovicka");
+Lolcat.new.request("CHEEZEBURGER");
+
+Which means we can now properly order our borovicka in Slovakia, which is 
awesome. Until 
+you do it in a loop and find the Headache['very bad'] role got mixed into 
yourself 
+overnight, anyway...
+
+Role attributes can also be used to initialise attributes:
+
+ role AttrParams[$a, $b] {
+     has $.x = $a;
+     has $.y = $b;
+ }
+
+...and to constrain types.  
+
+ role TypeParams[::T] {
+    method x(T $x) { return "got a " ~ T ~ " it was $x" }
+ }
+
+ class IntShower does TypeParams[Int] { } # Shows Ints
+ class StrShower does TypeParams[Str] { } # Shows Strs
+
+ print IntShower.new.x(42); # Prints 'got a Int it was 42'
+ print StrShower.new.x("OH HAI"); # Prints 'got a Str it was OH HAI'
+ print IntShower.new.x("OH HAI"); # Dies
+
+
+
+=for vim:set expandtab sw=4:

Modified: docs/Perl6/Spec/S29-functions.pod
===================================================================
--- docs/Perl6/Spec/S29-functions.pod   2009-02-23 21:06:52 UTC (rev 25502)
+++ docs/Perl6/Spec/S29-functions.pod   2009-02-23 23:33:42 UTC (rev 25503)
@@ -684,67 +684,67 @@
 
 =over
 
-=item all -- see S32-setting-library/Container.pod
+=item all -- see S32-setting-library/Containers.pod
 
-=item any -- see S32-setting-library/Container.pod
+=item any -- see S32-setting-library/Containers.pod
 
-=item cat -- see S32-setting-library/Container.pod
+=item cat -- see S32-setting-library/Containers.pod
 
-=item classify -- see S32-setting-library/Container.pod
+=item classify -- see S32-setting-library/Containers.pod
 
 =item defined -- see S32-setting-library/Scalars.pod
 
-=item grep -- see S32-setting-library/Container.pod
+=item grep -- see S32-setting-library/Containers.pod
 
-=item first -- see S32-setting-library/Container.pod
+=item first -- see S32-setting-library/Containers.pod
 
-=item keys -- see S32-setting-library/Container.pod
+=item keys -- see S32-setting-library/Containers.pod
 
-=item kv -- see S32-setting-library/Container.pod
+=item kv -- see S32-setting-library/Containers.pod
 
-=item join -- see S32-setting-library/Container.pod
+=item join -- see S32-setting-library/Containers.pod
 
-=item map -- see S32-setting-library/Container.pod
+=item map -- see S32-setting-library/Containers.pod
 
-=item max -- see S32-setting-library/Container.pod
+=item max -- see S32-setting-library/Containers.pod
 
-=item min -- see S32-setting-library/Container.pod
+=item min -- see S32-setting-library/Containers.pod
 
-=item none -- see S32-setting-library/Container.pod
+=item none -- see S32-setting-library/Containers.pod
 
-=item one -- see S32-setting-library/Container.pod
+=item one -- see S32-setting-library/Containers.pod
 
-=item pairs -- see S32-setting-library/Container.pod
+=item pairs -- see S32-setting-library/Containers.pod
 
 =item print -- see S32-setting-library/IO.pod
 
 =item printf -- see S32-setting-library/IO.pod
 
-=item roundrobin -- see S32-setting-library/Container.pod
+=item roundrobin -- see S32-setting-library/Containers.pod
 
-=item pick -- see S32-setting-library/Container.pod
+=item pick -- see S32-setting-library/Containers.pod
 
-=item reduce -- see S32-setting-library/Container.pod
+=item reduce -- see S32-setting-library/Containers.pod
 
-=item reverse -- see S32-setting-library/Container.pod
+=item reverse -- see S32-setting-library/Containers.pod
 
 =item say -- see S32-setting-library/IO.pod
 
-=item shape -- see S32-setting-library/Container.pod
+=item shape -- see S32-setting-library/Containers.pod
 
-=item sort -- see S32-setting-library/Container.pod
+=item sort -- see S32-setting-library/Containers.pod
 
-=item srand -- see S32-setting-library/Container.pod
+=item srand -- see S32-setting-library/Numeric.pod
 
 =item undefine -- see S32-setting-library/Scalar.pod
 
 =item uri -- see S32-setting-library/IO.pod
 
-=item values -- see S32-setting-library/Container.pod
+=item values -- see S32-setting-library/Containers.pod
 
 =item warn -- see S32-setting-library/Any.pod
 
-=item zip -- see S32-setting-library/Container.pod
+=item zip -- see S32-setting-library/Containers.pod
 
 =back
 

Reply via email to