Author: larry
Date: Tue Apr 24 22:06:33 2007
New Revision: 14382
Modified:
doc/trunk/design/syn/S06.pod
doc/trunk/design/syn/S12.pod
Log:
Clarifications suggested by TheDamian++
Killed "next METHOD", now just use nextsame etc.
Defined "lastcall" to allow return from final candidate.
Set up WHENCE mechanism for undefined prototype objects to autovivify lazily.
Modified: doc/trunk/design/syn/S06.pod
==============================================================================
--- doc/trunk/design/syn/S06.pod (original)
+++ doc/trunk/design/syn/S06.pod Tue Apr 24 22:06:33 2007
@@ -2100,7 +2100,15 @@
C<callsame> and C<callwith>, but a tail call is explicitly enforced;
any code following the call will be unreached, as if a return had
been executed there before calling into the destination routine.
-Within a method C<nextsame> is equivalent to C<next METHOD>.
+
+Within an ordinary method dispatch these functions treat the rest
+of the dispatcher's candidate list as the wrapped function, which
+generally works out to calling the same method in one of our parent
+(or older sibling) classes. Likewise within a multiple dispatch the
+current routine may defer to candidates further down the candidate
+list. Although not necessarily related by a class hierarchy, such
+later candidates are considered more generic and hence likelier
+to be able to handle various unforeseen conditions (perhaps).
=head2 The C<&?ROUTINE> object
Modified: doc/trunk/design/syn/S12.pod
==============================================================================
--- doc/trunk/design/syn/S12.pod (original)
+++ doc/trunk/design/syn/S12.pod Tue Apr 24 22:06:33 2007
@@ -12,9 +12,9 @@
Maintainer: Larry Wall <[EMAIL PROTECTED]>
Date: 27 Oct 2004
- Last Modified: 13 Apr 2007
+ Last Modified: 24 Apr 2007
Number: 12
- Version: 46
+ Version: 47
=head1 Overview
@@ -199,14 +199,14 @@
Indirect object notation now requires a colon after the invocant,
even if there are no arguments after the colon:
- $handle.close
- close $handle:
+ $handle.close;
+ close $handle:;
To reject method call and only consider subs, simply omit the colon
from the invocation line:
- close($handle)
- close $handle
+ close($handle);
+ close $handle;
However, here the built-in B<IO> class defines C<method close is export ()>,
which puts a C<multi sub close (IO)> in scope by default. Thus if the
@@ -233,7 +233,7 @@
.'+' # same as +$_
And in fact, if there is a choice between a unary prefix and a postfix
-operator, the indirect forms will choose the prefix operator. See S03.
+operator, the quoted forms will choose the prefix operator. See S03.
Likewise, presuming that C<$op> does not name an ordinary method on
C<$left>, this calls any arbitrary infix operator:
@@ -392,8 +392,10 @@
visible to derived classes via inheritance. A submethod is called
only when a method call is dispatched directly to the current class.
-[Conjecture: there is some relationship between "submethod BUILD" and
-"method ^BUILD" that possibly rises to the level of a unifiable identity...]
+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>.)
=head1 Attributes
@@ -564,7 +566,7 @@
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 class or role being built, the list value
+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.
@@ -572,6 +574,9 @@
being initialized.) In the absence of a class-labeled pair, all
the arguments to C<bless> are passed to the C<BUILD>.
+ class Dog is Animal {...}
+ my $pet = Dog.new( :name<Fido>, Animal => [:blood<warm> :legs(4)] );
+
You can clone an object, changing some of the attributes:
$newdog = $olddog.clone(:trick<RollOver>);
@@ -661,9 +666,7 @@
$object."+meth"(@args)
$object.'VAR'(@args)
-Any method can defer to the next candidate method in the list by
-saying C<next METHOD>. Any method can stop the progression by saying
-C<last METHOD>. The order and selection of the candidates may be
+The order and selection of the candidates may be
specified by arguments to a pseudo-class known as C<WALK>:
$object.*WALK[:breadth:omit($?CLASS)]::meth(@args);
@@ -681,10 +684,15 @@
:omit(Selector) # only classes that don't match selector
:include(Selector) # only classes that match selector
-In addition to C<next METHOD>, the special functions C<callsame>,
-C<callwith>, C<nextsame>, and C<nextwith> dispatch to the next
-candidate, possibly with a new argument list, and if the "next"
-variant is used, without returning:
+Any method can defer to the next candidate method in the list by
+the special functions C<callsame>, C<callwith>, C<nextsame>, and
+C<nextwith>. The "same" variants reuse the original argument list
+passed to the current method, whereas the "with" variants allow a
+new argument list to be substituted for the rest of the candidates.
+The "call" variants dispatch to the rest of the candidates and return
+their values to the current method for subsequent processing, whereas
+while the "next" variants don't return, but merely defer to the rest
+of the candidate list:
callsame; # call with the original arguments (return here)
callwith(); # call with no arguments (return here)
@@ -693,6 +701,21 @@
nextwith(); # redispatch with no arguments (no return)
nextwith(1,2,3); # redispatch with a new set of arguments (no return)
+For dispatches using C<.> and C<.?>, the return value is the
+C<Capture> returned by the first method completed without deferring.
+(Such a return value may in fact be failure, but it still counts as a
+successful call from the standpoint of the dispatcher.) Likewise the
+return value of C<.*> and C<.+> is a list of C<Captures> returned by
+those methods that ran to completion without deferring to next method.
+
+It is also possible to trim the candidate list so that the current
+call is considered the final candidate. (This is implicitly the case
+already for the dispatch variants that want a single successful call.)
+For the multiple call variants, C<lastcall> will cause the dispatcher
+to throw away the rest of the candidate list, and the subsequent
+return from the current method will produce the final C<Capture>
+in the returned list.
+
=head1 Parallel dispatch
Any of the method call forms may be turned into a hyperoperator by
@@ -705,6 +728,10 @@
@object».=meth(@args) # calls mutator method on each
@object»!meth(@args) # calls private method on each
+The return value is a list with exactly the same number of elements
+as C<@object>. Each such return value is a Capture or List of Captures
+as specified above for the non-hyper "dot" variants.
+
Hyperoperators treat a junction as a scalar value, so saying:
$junction».meth(@args);
@@ -756,10 +783,14 @@
in a grammar by declaring a C<proto> C<token> or C<proto> C<rule>. (Perl 6's
grammar does this, for instance.)
-You can have multiple C<multi> variables in the same scope, and they
-all share the same storage location and type. Usually these are
-declared by one C<proto> declaration at the top, and leaving the
-C<multi> implicit on the rest of the declarations.
+You can have multiple C<multi> variables of the same name in the
+same scope, and they all share the same storage location and type.
+Usually these are declared by one C<proto> declaration at the top,
+and leaving the C<multi> implicit on the rest of the declarations.
+You might do this when you suspect you'll have multiple declarations
+of the same variable name (such code might be produced by a macro
+or by a code generator, for instance) and you wish to suppress any
+possible warnings about redefinition.
In contrast, C<multi> routines can have only one instance of the long
name in any namespace, and that instance hides any outer (or less-derived)
@@ -896,9 +927,9 @@
only on positional parameters. Note that most builtins will map known
named parameters to positional via a C<proto> declaration.
-Within a multiple dispatch, C<next METHOD> means to try the next best
+Within a multiple dispatch, C<nextsame> means to try the next best
match, or next best default in case of tie, or the proto sub if there
-is one. The C<nextsame> function has the same effect.
+is one.
Attributes are tied to a particular class definition, so a multi method
can only directly access the attributes of a class it's defined within
@@ -943,7 +974,7 @@
method feed ($food) {
$food.open_can;
$food.put_in_bowl;
- self.some_other_method;
+ self.eat($food);
}
}
@@ -999,7 +1030,7 @@
Roles may have attributes:
role Pet {
- has $.collar = { Collar.new(Tag.new) };
+ has $.collar = Collar.new(Tag.new);
method id () { return $.collar.tag }
method lose_collar () { undefine $.collar }
}
@@ -1113,6 +1144,12 @@
proto method shake {...}
+(This declaration need not preceed the C<does> clause textually, since
+roles are not actually composed until the end of the class definition,
+at which point we know how 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" }
@@ -1135,13 +1172,16 @@
$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:
$fido does Sentry
-The C<does> operator is non-associative, so this is a syntax error:
+The C<does> infix operator is non-associative, so this is a syntax error:
$fido does Sentry does Tricks does TailChasing does Scratch;
@@ -1152,6 +1192,10 @@
$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
@@ -1161,12 +1205,14 @@
$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.
-
-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.
+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
@@ -1175,6 +1221,13 @@
$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
@@ -1306,13 +1359,13 @@
You can specify multiple method names:
- has $.legs handles <walk run lope shake pee>;
+ has $.legs handles <walk run lope shake lift>;
It's illegal to call the outer method unless the attribute
has been initialized to an object of a type supporting the method,
such as by:
- has Tail $.tail handles 'wag' = { .new(|%_) };
+ has Tail $.tail handles 'wag' .= new(|%_);
Note that putting a C<Tail> type on the attribute does not necessarily
mean that the method is always delegated to the C<Tail> class.
@@ -1383,9 +1436,8 @@
StBernard => $woof,
* => $ruff,
);
- method prefix:<~>( return "$.breed" )
-If the current object matches no Selector, a "C<next METHOD>" is
+If the current object matches no Selector, a "C<nextsame>" is
automatically performed.
=head1 Types and Subtypes
@@ -1658,11 +1710,11 @@
By default, all methods and submethods that do not declare an explicit
C<*%> parameter will get an implicit C<*%_> parameter declared for
them whether they like it or not. In other words, all methods allow
-unexpected named arguments, so that C<next METHOD> semantics work
+unexpected named arguments, so that C<nextsame> semantics work
consistently.
If you mark a class "C<is hidden>", it hides the current class
-from "C<next METHOD>" semantics, and incidentally suppresses the
+from "C<nextsame>" semantics, and incidentally suppresses the
autogeneration of C<*%_> parameters. Hidden classes may be visited
as C<SUPER::>, but not via "C<next>".
@@ -1680,6 +1732,7 @@
HOW the metaclass object: "Higher Order Workings"
WHEN (reserved for events?)
WHY (reserved for documentation?)
+ WHENCE autovivification closure
These may be used either as methods or as unary operators:
@@ -1738,7 +1791,7 @@
Class traits may include:
- identifier Dog-1.2.1-http://www.some.com/~jrandom
+ identifier { :name<Dog> :ver<1.2.1> :auth<http://www.some.com/~jrandom> }
name Dog
version 1.2.1
authority http://www.some.com/~jrandom
@@ -1833,4 +1886,16 @@
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,
+a C<CANDO> routine, instead of creating a C<Dog> object directly,
+could instead return something like:
+
+ Dog but WHENCE({ .new(: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.
+
=for vim:set expandtab sw=4: