Author: larry
Date: Fri Apr 27 17:08:44 2007
New Revision: 14386

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

Log:
more cleanup from TheDamian++
the ugly ::Animal initializers to .bless are gone; named args only bind params
sub-blesses are now just initialized using our new autovivifiable protoobjects
(.bless now allows those as positionals, in addition to the named args)
autovivifiable protoobjects now specified with Animal{ :foo<bar> } notation


Modified: doc/trunk/design/syn/S02.pod
==============================================================================
--- doc/trunk/design/syn/S02.pod        (original)
+++ doc/trunk/design/syn/S02.pod        Fri Apr 27 17:08:44 2007
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 10 Aug 2004
-  Last Modified: 12 Apr 2007
+  Last Modified: 27 Apr 2007
   Number: 2
-  Version: 101
+  Version: 102
 
 This document summarizes Apocalypse 2, which covers small-scale
 lexical items and typological issues.  (These Synopses also contain
@@ -1457,6 +1457,10 @@
     GLOBAL::<$IN>       # Same as $*IN
     Foo::<::Bar><::Baz> # same as Foo::Bar::Baz
 
+The final C<::> is required here, because the C<Foo::Bar{...}> syntax
+is reserved for defining an autovivifiable protoobject along with
+it's initialization closure (see S12).
+
 Unlike C<::()> symbolic references, this does not parse the argument
 for C<::>, nor does it initiate a namespace scan from that initial
 point.  In addition, for constant subscripts, it is guaranteed to

Modified: doc/trunk/design/syn/S12.pod
==============================================================================
--- doc/trunk/design/syn/S12.pod        (original)
+++ doc/trunk/design/syn/S12.pod        Fri Apr 27 17:08:44 2007
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 27 Oct 2004
-  Last Modified: 24 Apr 2007
+  Last Modified: 27 Apr 2007
   Number: 12
-  Version: 47
+  Version: 48
 
 =head1 Overview
 
@@ -121,16 +121,17 @@
 Every object (including any class object) delegates to an instance of
 its metaclass.  You can get at the metaclass of any object via the
 C<HOW> method.  A "class" object is just considered an "empty"
-instance in Perl 6, more properly called a "prototype" object.
+instance in Perl 6, more properly called a "prototype" object, or just
+"protoobject".
 The actual class object is the metaclass object pointed to by the
-C<HOW> syntax.  So when you say "Dog", you're referring to both a
-package and a prototype object, that latter of which points to the
-actual object representing the class via C<HOW>.  The prototype
-object differs from an instance object not by having a different
+C<HOW> syntax.  So when you say "C<Dog>", you're referring to both a
+package and a protoobject, that latter of which points to the
+actual object representing the class via C<HOW>.  The protoobject
+differs from an instance object not by having a different
 type but rather in the extent to which it is defined.  Some objects
 may tell you that they are defined, while others may tell you that
 they are undefined.  That's up to the object, and depends on how the
-metaclass chooses to dispatch the .defined method.
+metaclass chooses to dispatch the C<.defined> method.
 
 The notation C<^Dog> is syntactic sugar for C<Dog.HOW>, so C<^> can be
 considered the "class" sigil when you want to talk about the current
@@ -358,7 +359,7 @@
 Other OO languages give you the ability to declare "class" methods that either 
don't
 need or actively prohibit calls on instances.  Perl 6 gives you a choice.
 If you declare an ordinary method, it can function as a "class" method when you
-pass it a prototype object such as "Dog" regardless of how defined the 
prototype
+pass it a protoobject such as "C<Dog>" regardless of how defined the prototype
 object is, as long as the method body doesn't try to access any information 
that
 is undefined in the current instance.
 
@@ -394,8 +395,9 @@
 
 Conjecture: in order to catch spelling errors it is a compile-time
 warning to define a submethod in any class that does not inherit the
-corresponding method name from some base class.  (But note that the
-standard C<Object> class supplies a default C<BUILD> and C<new>.)
+corresponding method name from some base class.  More importantly, this
+would help safeguard Liskov substitutability. (But note that the
+standard C<Object> class already supplies a default C<BUILD> and C<new>.)
 
 =head1 Attributes
 
@@ -538,8 +540,14 @@
 
 (The default C<CREATE> makes an opaque object.)
 
-All arguments to this form of C<bless> must be named arguments, not
-positional.
+In addition to the candidate position argument, C<bless> also
+allows one or more positional arguments representing autovivifying
+protoobjects.  Such an object looks like a prototype followed by a
+hash subscript (see "Autovivifying objects" below).  These are used
+to initialize superclasses.
+
+Other than the candidate object and any autovivifying protoobjects,
+all arguments to C<bless> must be named arguments, not positional.
 Hence, the main purpose of custom constructors is to turn positional
 arguments into named arguments for C<bless>.  The C<bless> method
 allows an object to be used for its class invocant.  (Your constructor
@@ -563,19 +571,24 @@
 which initializes the object in least-derived to most-derived order.
 C<DESTROY> and C<DESTROYALL> work the same way, only in reverse.
 
-The default C<BUILD> and C<BUILDALL> are inherited from C<Object>, so
-you need to write initialization routines only if you wish to modify
-the default behavior.  If the name of a named argument begins with a
-C<::> and corresponds to a (super)class or role being built, the list value
-of that argument is passed as a list of named arguments to that class
-or role's C<BUILD>.  (If the value of that argument is a closure
-instead of a list, that closure will be called to return a list.
-The argument to that closure will be the name of the class currently
-being initialized.)  In the absence of a class-labeled pair, all
-the arguments to C<bless> are passed to the C<BUILD>.
+The default C<BUILD> and C<BUILDALL> are inherited from C<Object>,
+so you need to write initialization routines only if you wish to
+modify the default behavior.  The C<bless> function automatically
+passes the appropriate argument list to the C<BUILD> of its various
+parent classes.  If the type of the parent class corresponds to one
+of the protoobjects passed to bless, that protoobject's argument
+list is used.  Otherwise all the arguments to bless are passed to
+the parent class's C<BUILD>.  For the final C<BUILD> of the current
+object, all the arguments to C<bless> are passed to the C<BUILD>, so
+it can deal with any protoobjects that need special handling.  (It is
+allowed to pass protoobjects that don't correspond to any parent class.)
 
     class Dog is Animal {...}
-    my $pet = Dog.new( :name<Fido>, Animal => [:blood<warm> :legs(4)] );
+    my $pet = Dog.new( :name<Fido>, Animal{ :blood<warm>, :legs(4) } );
+
+Here we are using an autovivifying C<Animal> protoobject to specify what
+the arguments to C<Animal>'s C<BUILD> routine should look like.  (It does
+not actually autovivify an C<Animal> apart from the one being created.)
 
 You can clone an object, changing some of the attributes:
 
@@ -1154,27 +1167,6 @@
 
     proto method shake { warn "They couldn't decide" }
 
-Conjectural: If the original invocant is in a variable that is
-constrained to be of one role or another, then that type could be used
-to dispatch to the correct role's method in cases where they can't
-be distinguished by differences in the actual argument types:
-
-    class DogTree {
-        does DogBark;
-        does TreeBark;
-        proto method bark {...}
-        ...
-    }
-
-    my DogBark $dog = new DogTree;
-    my TreeBark $tree = new DogTree;
-
-    $dog.bark();        # picks Dog role's bark method
-    $tree.bark();       # picks Tree role's bark method
-
-If there is such a mechanism, it may only be used as a tie-breaker.
-Otherwise we break the normal polymorphism expectations.
-
 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:
@@ -1886,16 +1878,48 @@
 a method of a particular name if it's required and hasn't been supplied
 by the class or one of its roles.
 
-Conjecture: The C<WHENCE> property of an object is its autovivifying
-closure.  Any undefined prototype object may carry such a closure that
-can lazily create an object of the appropriate type.  For instance,
+=head1 Autovivifying objects
+
+The C<WHENCE> property of an object is its autovivifying closure.
+Any undefined prototype object may carry such a closure that can
+lazily create an object of the appropriate type.  When the closure
+is eventually evaluated it is expected to return an argument list
+corresponding to the arguments to a C<.bless> call.  For instance,
 a C<CANDO> routine, instead of creating a C<Dog> object directly,
 could instead return something like:
 
-    Dog but WHENCE({ .new(:name<Fido>) })
+    Dog but WHENCE({ :name<Fido> })
 
 which runs the closure if the object ever needs to be autovivified.
 The closure can capture whatever initializers were available in the
 original lexical scope.
 
+The short form of the above is simply:
+
+    Dog{ :name<Fido> }
+
+This is still lazily evaluated:
+
+    my $dog = Dog{ :name<Fido> };
+    defined $dog or say "doesn't exist";  # Fido doesn't exist
+    $dog.wag()                            # Fido wags his tail
+
+Note that when used as an argument to a method like C<bless>, the
+protoobject is sufficiently lazy that autovivifying is done only by
+the appropriate C<BUILD> routine.  It does not waste energy creating
+a C<Dog> object when that object's attributes would later have to be
+copied into the actual object.
+
+The object autovivification syntax works only for literal named types,
+so any indirection must be written more explicitly:
+
+    ::($dogproto){ :name<Fido> }
+    $dogproto but WHENCE({ :name<Fido> })
+    $dogproto.WHAT{ :name<Fido> }
+
+Note that in contrast to this syntax, a lookup of a symbol in the C<Dog>
+package requires a final C<::> before the subscript:
+
+    Dog::{$varname}
+
 =for vim:set expandtab sw=4:

Reply via email to