Author: larry
Date: Fri Feb 15 09:45:52 2008
New Revision: 14508

Modified:
   doc/trunk/design/syn/S12.pod

Log:
Some clarifications requested by jonathan++
Changed role-private attributes to be declared with my $!foo
The "has" declarator now explicitly always participates in composition


Modified: doc/trunk/design/syn/S12.pod
==============================================================================
--- doc/trunk/design/syn/S12.pod        (original)
+++ doc/trunk/design/syn/S12.pod        Fri Feb 15 09:45:52 2008
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 27 Oct 2004
-  Last Modified: 27 Jun 2007
+  Last Modified: 15 Feb 2008
   Number: 12
-  Version: 56
+  Version: 57
 
 =head1 Overview
 
@@ -234,6 +234,11 @@
 
     .doit(1,2,3)
 
+Note that there is no corresponding notation for private methods.
+
+    !doit(1,2,3)        # WRONG, would be parsed as not(doit(1,2,3))
+    self!doit(1,2,3)    # okay
+
 There are several forms of indirection for the method name.  You can
 replace the identifier with a quoted string, and it will be evaluated
 as a quote and then the result of that is used as the method name.
@@ -241,6 +246,8 @@
     $obj."$methodname"(1,2,3)   # use contents of $methodname as method name
     $obj.'$methodname'(1,2,3)   # no interpolation; call method with $ in name!
 
+    $obj!"$methodname"          # indirect call to private method name
+
 [Note: to help catch the mistaken use of C<< infix:<.> >> as a string
 concatenation operator, PerlĀ 6 will warn you about "useless use of
 quotes" at compile time if the string inside quotes is an identifier.
@@ -263,11 +270,12 @@
 
 The variable must contain a Code object, that is, a closure of some
 sort.  Regardless of whether the closure was defined as a method or
-a sub or a block, the closure is called as a method, with the object
-as its first argument, and the rest of the arguments second, third,
-and so on.   For instance, such a closure may be used to abstract a
-"navigational" path through a data structure without specifying the
-root of the path till later:
+a sub or a block, the closure is called directly without any class
+dispatch; from the closure's point of view, however, it is always
+called as a method, with the object as its first argument, and the
+rest of the arguments second, third, and so on.   For instance, such
+a closure may be used to abstract a "navigational" path through a
+data structure without specifying the root of the path till later:
 
     $locator = -> $root, $x, $y { $root.<foo>[$x]<bar>{$y}[3] }
     $obj.$locator(42,"baz")  # $obj<foo>[42]<bar><baz>[3]
@@ -302,7 +310,13 @@
     [EMAIL PROTECTED](1,2,3)
 
 As with the scalar variant, each array element must be a Code object,
-but the list is treated as a list of candidates to call.
+but the list is treated as a list of candidates to call.  Note also that
+the 
+
+    $obj.$candidates(1,2,3)
+
+form may dispatch to a list of candidates if $candidates is a special
+C<Code> object representing a partial dispatch to a list of candidates.
 
 Another form of indirection relies on the fact that operators are named
 using a variant on hash subscript notation, which gives you these forms:
@@ -334,17 +348,23 @@
 You must use a special syntax to call a private method:
 
     $mybrain!think($pinky)
+    self!think($pinky)
+
+For a call on your own private method, you may also use the attribute-ish form:
 
-Parentheses (or a colon) are required on the dot notation if there
+    $!think($pinky)     # short for $(self!think($pinky))
+
+Parentheses (or a colon) are required on the dot/bang notations if there
 are any arguments (not counting adverbial arguments).  There may be
 no space between the method name and the left parenthesis unless you
-use the dot form of parentheses:
+use the dot form of parentheses or otherwise make use of "unspace":
 
     .doit       # okay, no arguments
     .doit()     # okay, no arguments
     .doit ()    # ILLEGAL (two terms in a row)
     .doit.()    # okay, no arguments, same as .doit()
-    .doit\ .()  # okay, no arguments, same as .doit() (unspace form)
+    .doit\ ()   # okay, no arguments, same as .doit() (unspace form)
+    .doit\ .()  # okay, no arguments, same as .doit.() (unspace form)
 
 However, you can turn any of the legal forms above into a list
 operator by appending a colon:
@@ -510,6 +530,8 @@
 
         has $brain;     # also declares $!brain;
 
+As with the C<!> declaration, no accessor is generated.
+
 And any later references to the private variable within the same block
 may either use or omit the exclamation, as you wish to emphasize or
 ignore the privacy of the variable.  Outside the block, you must use
@@ -1152,16 +1174,13 @@
         has ID $.collar .= new($tag);
     }
 
-Unlike in a class, within a role the C<has> declarator distinguishes
-private attribute declared with exclamation from those without.
-To declare a private attribute that is shared by the class, use the
-exclamationless notation in the declaration:
-
-    has Nose $sniffer .= new();
+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:
 
-A completely private role attribute may be declared like this:
-
-    has $!spleen;
+    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
@@ -1173,23 +1192,22 @@
 
 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 accessor are also caught at composition time, but of course
+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().>)
 
-Outside of the C<has> declaration, the exclamation mark is again optional,
-as with an ordinary private attribute in the class.
-
 A role may also distinguish a shared method
 
-    method foo ...
+    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.
 
@@ -1208,8 +1226,8 @@
     }
 
 Note that this puts the three methods into the class as well as
-C<$groomer>.  In contrast, "C<has $!groomer>" would only put the
-three methods.
+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:
@@ -1240,7 +1258,12 @@
 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.
+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

Reply via email to