Author: larry
Date: Mon Feb 12 00:10:05 2007
New Revision: 13582

Modified:
   doc/trunk/design/syn/S02.pod
   doc/trunk/design/syn/S04.pod
   doc/trunk/design/syn/S06.pod

Log:
The kludge known as "leave" is now spelled "give".
The give() function always gives the final value of the innermost block.
The $context.give() method always gives the final value of the context.
Rather than repeating the context selector interface we now rely on object.
Loop labels are now considered sufficient OO to allow LABEL.give($retval)
within the *lexical* scope of the labeled statement.


Modified: doc/trunk/design/syn/S02.pod
==============================================================================
--- doc/trunk/design/syn/S02.pod        (original)
+++ doc/trunk/design/syn/S02.pod        Mon Feb 12 00:10:05 2007
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 10 Aug 2004
-  Last Modified: 8 Feb 2007
+  Last Modified: 11 Feb 2007
   Number: 2
-  Version: 85
+  Version: 86
 
 This document summarizes Apocalypse 2, which covers small-scale
 lexical items and typological issues.  (These Synopses also contain
@@ -2468,7 +2468,21 @@
 
 The lexical routine itself is C<&?ROUTINE>; you can get its name with
 C<&ROUTINE.name>.  The current block is C<&?BLOCK>.  If the block has a label,
-that shows up in C<&?BLOCK.label>.
+that shows up in C<&?BLOCK.label>.  Within the lexical scope of
+a statement with a label, the label is a pseudo-object representing
+the dynamic context of that statement.  (If inside multiple dynamic
+instances of that statement, the label represents the innermost one.)
+When you say:
+
+    next LINE;
+
+it is really a method on this pseudo-object, and
+
+    LINE.next;
+
+would work just as well.  You can exit any labeled block early by saying
+
+    MyLabel.give(@results);
 
 =item *
 

Modified: doc/trunk/design/syn/S04.pod
==============================================================================
--- doc/trunk/design/syn/S04.pod        (original)
+++ doc/trunk/design/syn/S04.pod        Mon Feb 12 00:10:05 2007
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 19 Aug 2004
-  Last Modified: 8 Feb 2007
+  Last Modified: 11 Feb 2007
   Number: 4
-  Version: 51
+  Version: 52
 
 This document summarizes Apocalypse 4, which covers the block and
 statement syntax of Perl.
@@ -204,7 +204,8 @@
 within the body of the loop.  See below.
 
 The value of a loop statement is the list of values from each
-iteration.  (This list is actually a multidimensional list (a "multislice")
+iteration that successfully completed without a C<next> or C<last>.
+(This list is actually a multidimensional list (a "multislice")
 with dimensional boundaries at each iteration.  Most list contexts
 ignore these boundaries and flatten the list.)  If you do not wish
 to accidentally return a list from the final loop statement in a
@@ -651,26 +652,49 @@
 with the C<sub>, C<method>, or C<submethod> keywords).  Pointy blocks
 and bare closures are transparent to C<return>.  If you pass a closure
 object outside of its official "sub" scope, it is illegal to
-return from it.  You may only leave the closure block itself with C<leave>
-or by falling off the end of it.
+return from it.  You may only leave the displaced closure block itself
+by falling off the end of it or by explicitly calling C<give>.
 
-To return a value from a pointy block or bare closure, you either
-just let the block return the value of its final expression, or you can
-use C<leave>.  A C<leave> by default exits from the innermost block.
-But you may change the behavior of C<leave> with a selector as the
-first argument:
+To return a value from any pointy block or bare closure, you either
+just let the block return the value of its final expression, or you
+can use C<give>, which comes in both function and method forms.
+The function (or listop) form always exits from the innermost block,
+returning its arguments as the final value of the block exactly as
+return does.  The method form will leave any block in the dynamic
+scope that can be named as an object and that responds to the C<.give>
+method.
 
-    leave Loop where { .label ~~ 'LINE' }, 1,2,3;
+Hence, the C<give> function:
 
-The innermost block matching the selection criteria will be exited.
-The return value, if any, must be passed as the second and subsequent 
arguments.
-To return pairs as part of the value, you can use a feed operator:
+    give(1,2,3)
 
-    leave <== :foo:bar:baz(1) if $leaving;
+is really just short for:
 
-or going the other way:
+    $?BLOCK.give(1,2,3)
 
-    $leaving and :foo:bar:baz(1) ==> leave;
+To return from your immediate caller, you can say:
+
+    caller.give(1,2,3)
+
+Further contexts up the caller stack may be located by the selector
+that is built into the C<caller> function itself:
+
+    caller({ .label eq 'LINE' }).give(1,2,3);
+
+By default the innermost dynamic scope matching the selection criteria
+will be exited.  This can be a bit cumbersome, so in the particular
+case of labels, the label that is already visible in the current lexical
+scope is considered a kind of pseudo object specifying a potential
+dynamic context.  If instead of the above you say:
+
+    LINE.give(1,2,3)
+
+it was always exit from your lexically scoped C<LINE> loop, even
+if some inner dynamic scope you can't see happens to also have that
+label.  If the C<LINE> label is visible but you aren't actually in
+a dynamic scope controlled by that label, an exception is thrown.
+(If the C<LINE> is not visible, it would have been caught earlier at
+compile time since C<LINE> would likely be a bareword.)
 
 In theory, any user-defined control construct can catch any control
 exception it likes.  However, there have to be some culturally enforced
@@ -680,8 +704,10 @@
 expects it to be caught by.  In particular, if the user labels a loop
 with a specific label, and calls a loop control from within the lexical
 scope of that loop, and if that call mentions the outer loop's label,
-then that outer loop is the one that must be controlled. (This search
-of lexical scopes is limited to the current "official" subroutine.)
+then that outer loop is the one that must be controlled.  In other words,
+it first tries this form:
+
+    LINE.give(1,2,3)
 
 If there is no such lexically scoped outer loop in the current subroutine,
 then a fallback search is made outward through the dynamic scopes in
@@ -690,7 +716,8 @@
 control structures, hence the sub's lexical scope was I<always>
 the innermost dynamic scope, so the preference to the lexical scope
 in the current sub was implicit.  For PerlĀ 6 we have to make this
-preference explicit.)
+preference explicit.)  So this fallback is more like the C<caller>
+form we saw earlier.
 
 Warnings are produced in PerlĀ 6 by throwing a resumable control
 exception to the outermost scope, which by default prints the

Modified: doc/trunk/design/syn/S06.pod
==============================================================================
--- doc/trunk/design/syn/S06.pod        (original)
+++ doc/trunk/design/syn/S06.pod        Mon Feb 12 00:10:05 2007
@@ -13,9 +13,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 21 Mar 2003
-  Last Modified: 29 Jan 2007
+  Last Modified: 11 Feb 2007
   Number: 6
-  Version: 68
+  Version: 69
 
 
 This document summarizes Apocalypse 6, which covers subroutines and the
@@ -826,8 +826,8 @@
 =head2 Feed operators
 
 The variadic list of a subroutine call can be passed in separately from
-the normal argument list, by using either of the I<feed> operators: C<<
-<== >> or C<< ==> >>.  Syntactically, feed operators expect to find a
+the normal argument list, by using either of the I<feed> operators:
+C<< <== >> or C<< ==> >>.  Syntactically, feed operators expect to find a
 statement on either end.  Any statement can occur on the source end;
 however not all statements are suitable for use on the sink end of a feed.
 
@@ -852,16 +852,39 @@
 but differ in interface.  Code which violates these promises is
 erroneous, and will produce undefined results when parallelized.)
 
-In particular, a chain of feeds may not begin and end with the same array.
-(You may, however, assign to an array that is used within a chain
-on the right side of the assignment, since list assignment will clear
-and copy as necessary to make it work.)  That is, this doesn't work:
+However, feeds go a bit further than ordinary lazy lists in enforcing
+the parallel discipline: they explicitly treat the blunt end as a
+cloned closure that starts a subthread.  The only variables shared
+by the inner scope with the outer scope are those lexical variables
+declared in the outer scope that are visible at the time the closure is
+cloned and the subthread spawned.  Use of such shared variables will
+automatically be subject to transactional protection (and associated
+overhead).  Package variables are not cloned unless predeclared
+as lexical names with C<our>.  Variables declared within the blunt
+end are not visible outside, and in fact it is illegal to declare a
+lexical on the blunt end that is not enclosed in curlies somehow.
+
+Because feeds are defined as lazy pipes, a chain of feeds may not begin
+and end with the same array without some kind of eager sequence point.
+That is, this doesn't work:
 
+    my @data = 1,2,3;
     @data <== grep { $_ % 2 } <== @data;
 
 but this does:
 
-    @data = grep { $_ % 2 } <== @data;
+    my @data = 1,2,3;
+    my @tmp = eager @data;
+    @data <== grep { $_ % 2 } <== @tmp;
+
+(But note: feed operators have push semantics when the receiver is an array.
+Use assignment to get clear-first semantics.)
+
+Conjecture: these are probably impossible:
+
+    @data <== grep { $_ % 2 } <== eager @data;
+    @data = do { grep { $_ % 2 } <== eager @data; }
+    @data := do { grep { $_ % 2 } <== eager @data; }
 
 Leftward feeds are a convenient way of explicitly indicating the typical
 right-to-left flow of data through a chain of operations:
@@ -875,8 +898,9 @@
 Rightward feeds are a convenient way of reversing the normal data flow in a
 chain of operations, to make it read left-to-right:
 
-    @oddsquares = do
-            @nums ==> grep { $_ % 2 } ==> sort ==> map { $_**2 };
+    @oddsquares = do {
+        @nums ==> grep { $_ % 2 } ==> sort ==> map { $_**2 };
+    }
 
 Note that the C<do> is necessary because feeds operate at the statement
 level.  (Parens would also work, since a "do" is assumed there.)
@@ -1587,7 +1611,7 @@
 blocks this can be optimized away to a "goto".  All C<Routine> declarations
 have an explicit declarator such as C<sub> or C<method>; bare blocks and
 "pointy" blocks are never considered to be routines in that sense.  To return
-from a block, use C<leave> instead--see below.
+from a block, use C<give> instead--see below.
 
 The C<return> function preserves its argument list as a C<Capture> object, and
 responds to the left-hand C<Signature> in a binding.  This allows named return
@@ -1650,7 +1674,8 @@
     $caller = caller Method;               # nearest caller that is method
     $caller = caller Bare;                 # nearest caller that is bare block
     $caller = caller Sub, :skip(2);        # caller three levels up
-    $caller = caller Block, :label<Foo>;   # caller whose label is 'Foo'
+    $caller = caller Block where { .label eq 'Foo' };
+                                           # caller whose label is 'Foo'
 
 =head2 The C<want> function
 
@@ -1688,38 +1713,48 @@
                         #            want.arity === 0
                         #            want.count === 2
 
-=head2 The C<leave> function
+=head2 The C<give> function
 
-As mentioned above, a C<return> call causes the innermost
-surrounding subroutine, method, rule, token, regex (as a keyword)
-or macro to return.  Only declarations with an explicit
-keyword such as "sub" may be returned from.  You may not return from
-a quotelike operator such as C<rx//>.
-
-To return from other types of code structures, the C<leave> function
-is used.  The first argument, if supplied, specifies a C<Selector>
-for the control structure to leave.  The C<Selector> will be
-smart-matched against the dynamic scope objects from inner to outer.
-The first that matches is the scope that is left.
+As mentioned above, a C<return> call causes the innermost surrounding
+subroutine, method, rule, token, regex (as a keyword) or macro to
+return.  Only declarations with an explicit keyword such as "sub"
+may be returned from.  You may not use C<return> to return from loops,
+bare blocks, pointy blocks, or quotelike operators such as C<rx//>.
+
+To return from these types of code structures, the C<give> method
+is used instead.  (It can be taken to mean either "give up" or
+"bequeath" as appropriate.)  The object specifies the scope to exit,
+and the method's arguments specify the return value.  If the object
+is omitted (by use of the function or listop forms), the innermost
+block is exited.  Otherwise you must use something like C<caller>
+or C<$?BLOCK> or a contextual variable to specify the scope you
+want to exit.  A label (such as a loop label) previously seen in
+the lexical scope also works as a kind of singleton context object:
+it names a statement that is serving both as an outer lexical scope
+and as a context in the current dynamic scope.
 
-The remainder of the arguments are taken to be a C<Capture> holding the
+As with C<return>, the arguments are taken to be a C<Capture> holding the
 return values.
 
-    leave;                      # return from innermost block of any kind
-    leave *;                    # same thing
-    leave Method;               # return from innermost calling method
-    leave &?ROUTINE, 1,2,3;     # Return from current sub. Same as: return 
1,2,3
-    leave &?ROUTINE <== 1,2,3;  # same thing, force return as feed
-    leave &foo, 1,2,3;          # Return from innermost surrounding call to 
&foo
+    give;                      # return from innermost block of any kind
+    caller(Method).give;       # return from innermost calling method
+    &?ROUTINE.give(1,2,3);     # Return from current sub. Same as: return 1,2,3
+    &?ROUTINE.give <== 1,2,3;  # same thing, force return as feed
+    OUTER.give;                # Return from OUTER label in lexical scope
+    &foo.give: 1,2,3;          # Return from innermost surrounding call to &foo
 
-Note that these are equivalent:
+Note that these are equivalent in terms of control flow:
 
-    leave Loop where { .label eq 'COUNT' };
+    COUNT.give;
     last COUNT;
 
-and, in fact, you can return a final loop value that way:
+However, the first form explicitly gives the return value for the
+entire loop, while the second implicitly returns all the previous
+successful loop iteration values as a list comprehension.  A C<give>
+from the inner loop block, however, merely specifies the return value for
+that iteration:
 
-    last COUNT, 42;
+    for 1..10 { give $_ * 2 }   # 2..20
 
 =head2 Temporization
 

Reply via email to