Author: larry
Date: Sun Jan 28 16:04:21 2007
New Revision: 13542

Modified:
   doc/trunk/design/syn/S03.pod
   doc/trunk/design/syn/S06.pod

Log:
Typos from (Joe and Mark)++
Rethink of low-precedence priority to unify listops with contextualizers.
Comma precedence now separate to avoid former sophistry.
Precedence is now: comma << list infix << list prefix
Can now parse "chunky" contextualizer as listop:
    @@('a','b' XX 1,2)  # returns ['a',1],['a',2],['b',1],['b',2]
    @@: 'a','b' XX 1,2  # same thing
Feed operators are no longer list infix, "demoted" to statement separators.
Explicit target of a feed now just an empty contextualizer.
The each function now gone in favor of smooth/chunky contextualized zip.


Modified: doc/trunk/design/syn/S03.pod
==============================================================================
--- doc/trunk/design/syn/S03.pod        (original)
+++ doc/trunk/design/syn/S03.pod        Sun Jan 28 16:04:21 2007
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 8 Mar 2004
-  Last Modified: 26 Jan 2007
+  Last Modified: 28 Jan 2007
   Number: 3
-  Version: 91
+  Version: 92
 
 =head1 Overview
 
@@ -22,7 +22,7 @@
 
 =head1 Operator precedence
 
-Not counting terms and terminators, Perl 6 has 20 operator precedence
+Not counting terms and terminators, Perl 6 has 21 operator precedence
 levels. (Perl 5 has 23!)  Here we list the levels from "tightest" to
 "loosest", along with a few examples of each level:
 
@@ -45,11 +45,12 @@
     Conditional         ?? !!
     Item assignment     = := ::= => += -= **= xx= .=
     Loose unary         true not
-    List ops            , = print push say die map substr ... [+] [*] any all
-    List infix          ¥ <== ==> minmax X XX X~X X*X XeqvX
+    Comma operator      ,
+    List infix          ¥ minmax X XX X~X X*X XeqvX
+    List prefix         = : print push say die map substr ... [+] [*] any all
     Loose and           and
     Loose or            or xor err
-    Terminator          ; {...}, modifiers, unmatched ), ], }
+    Terminator          ; <==, ==>, {...}, modifiers, unmatched ), ], }
 
 If you don't see your favorite operator there, the following
 sections cover all the operators in precedence order.  Basic operator
@@ -454,7 +455,7 @@
 
 =item *
 
-infix:<div>
+infix:<div>, generic division
 
     $dividend div $divisor
 
@@ -466,6 +467,16 @@
 
     %
 
+Always floor semantics using Num or Int.
+
+=item *
+
+infix:<mod>, generic modulus
+
+    mod
+
+Dispatches to the infix:<mod> multi most appropriate to the operand types.
+
 =item *
 
 infix:<x>, string replication
@@ -492,7 +503,7 @@
 
 =item *
 
-infix:{'+<'}, numeric shift right
+infix:{'+>'}, numeric shift right
 
     +>
 
@@ -520,18 +531,6 @@
 
     ?&
 
-=item *
-
-infix:<div>, generic division
-
-    div
-
-=item *
-
-infix:<mod>, generic modulus
-
-    mod
-
 =back
 
 =head2 Additive precedence
@@ -974,24 +973,12 @@
 
 =back
 
-=head2 List ops precedence
+=head2 Comma operator precedence
 
 =over
 
 =item *
 
-infix:<=>, list assignment
-
-    @array = 1,2,3;
-
-With compound targets, performs list assignment.  The right side is looser
-than comma.  You can view the left side as a special syntax for a prefix
-listop, much as if you'd said:
-
-    @array.assign: 1,2,3
-
-=item *
-
 infix:<,>, the argument separator
 
     1, 2, 3, @many
@@ -999,148 +986,156 @@
 Unlike in Perl 5, comma operator never returns the last value.  (In item
 context it returns a list instead.)
 
-=item *
+=back
 
-infix:<:>, the invocant marker
+=head2 List infix precedence
 
-    say $*OUT: "howdy, world"
+List infixes all have list associativity, which means that identical
+infix operators work together in parallel rather than one after
+the other.  Non-identical operators are considered non-associative
+and must be parenthesized for clarity.
 
-The colon that turns a method call into a list operator also sits
-in the "comma" slot.  It cannot be used just anywhere though.
-Much like list assignment, it takes a special syntax on the left
-side and turns it into a list operator over the list on the right.
-See L</Invocant marker>.
-
-Comma, C<=>, and C<:> are the only listops that are allowed to occur
-where an infix is expected.  All other listops function as a term
-within the expression to the left.
+=over
 
 =item *
 
-Normal listops
+infix:<¥>, the zip operator
 
-    print push say join split substr open etc.
+    1,2 ¥ 3,4   # (1,3),(2,4)
 
 =item *
 
-Listop forms of junctional operators
+The minmax operator
 
-    any all one none
+    $min0, $max0 minmax $min1, $max1    # ($min0 min $min1, $max0 max $max1)
 
 =item *
 
-Exception generators
+List and string cross operators
 
-    fail "Division by zero"
-    die System::Error(ENOSPC,"Drive $d seems to be full");
-    warn "Can't open file: $!"
+    1,2 XX 3,4          # (1,3), (1,4), (2,3), (2,4)
+    1,2 X 3,4           # '13', '14', '23', '24'
 
-=item *
+In contrast to the zip operator, the C<XX> operator returns all the
+permutations of its sublists.  Hence you may say:
 
-Stubby exception generators
+    <a b> XX <1 2>
 
-    ...
-    !!! "fill this in later, Dave"
-    ??? "oops in $?CLASS"
+and you end up with
 
-The C<...> operator is the "yada, yada, yada" list operator, which
-among other things is used as the body in function prototypes.
-It complains bitterly (by calling C<fail>) if it is ever executed.
-Variant C<???> calls C<warn>, and C<!!!> calls C<die>.  The argument
-is optional, but if provided, is passed onto the C<fail>, C<warn>,
-or C<die>.  Otherwise the system will make up a message for you based
-on the context, indicating that you tried to execute something that
-is stubbed out.  (This message differs from what C<fail>, C<warn>, and
-C<die> would say by default, since the latter operators typically point
-out bad data or programming rather than just an incomplete design.)
+    ('a', '1'), ('a', '2'), ('b', '1'), ('b', '2')
 
-=item *
+The C<X> variant crosses the arrays but concatenates strings:
 
-Reduce operators
+    <a b> X <1 2>
 
-    [+] [*] [<] [\+] [\*] etc.
+produces
 
-See L<Reduction operators>.
+    'a1', 'a2', 'b1', 'b2'
+
+The resemblance to C<x> and C<xx> is not entirely accidental.
 
 =item *
 
-The C<list> contextualizer
+Cross hyperoperators
 
-    list
+    X~X
+    X*X
+    XeqvX
+    etc.
 
-Forces the subsequent expression to be evaluated in list context.
-Equivalent to C<@()>.
+See L</Cross operators>.
 
 =back
 
-=head2 List infix precedence
+Many of these operators return a list of Captures, which depending on
+context may or may not flatten them all out into one flat list.  The
+default is to flatten, but see the contextualizers below.
+
+=head2 List prefix precedence
 
 =over
 
 =item *
 
-infix:<¥>, the zip operator
-
-    1,2 ¥ 3,4   # (1,3),(2,4)
+infix:<=>, list assignment
 
-=item *
+    @array = 1,2,3;
 
-infix:{'<=='}, the feed-left operator
+With compound targets, performs list assignment.  The right side
+is looser than comma.  You might be wondering why we've classified
+this as a prefix operator when its token name is C<< infix:<=> >>.
+That's because you can view the left side as a special syntax for a
+prefix listop, much as if you'd said:
 
-    target <== @list
+    @array.assign: 1,2,3
 
-See L</Feed operators>.
+However, the tokener classifies it as infix because it sees it when
+it's expecting an infix operator.  Assignments in general are treated
+more like retroactive macros, since their meaning depends greatly on
+what is on the left, especially if what is on the left is a declarator
+of some sort.  We even call some of them pseudo-assignments, but they're
+all a bit pseudo insofar as we have to figure out whether the left side
+is a list or a scalar destination.
 
 =item *
 
-infix:{'==>'}, the feed-right operator
+infix:<:>, the invocant marker
 
-    @list ==> target
+    say $*OUT: "howdy, world"
 
-See L</Feed operators>.
+The colon operator turns method calls and contextualizers into
+list operators.  It's not really a general operator; much like list
+assignment, it takes a special syntax on the left side and turns it
+into a list operator over the list on the right.  See L</Invocant
+marker>.
 
 =item *
 
-The minmax operator
+Normal listops
 
-    $min0, $max0 minmax $min1, $max1    # ($min0 min $min1, $max0 max $max1)
+    print push say join split substr open etc.
 
 =item *
 
-List and string cross operators
-
-    1,2 XX 3,4          # (1,3), (1,4), (2,3), (2,4)
-    1,2 X 3,4           # '13', '14', '23', '24'
-
-In contrast to the zip operator, the C<XX> operator returns all the
-permutations of its sublists.  Hence you may say:
+Listop forms of junctional operators
 
-    <a b> XX <1 2>
+    any all one none
 
-and you end up with
+=item *
 
-    ('a', '1'), ('a', '2'), ('b', '1'), ('b', '2')
+Exception generators
 
-The C<X> variant crosses the arrays but concatenates strings:
+    fail "Division by zero"
+    die System::Error(ENOSPC,"Drive $d seems to be full");
+    warn "Can't open file: $!"
 
-    <a b> X <1 2>
+=item *
 
-produces
+Stubby exception generators
 
-    'a1', 'a2', 'b1', 'b2'
+    ...
+    !!! "fill this in later, Dave"
+    ??? "oops in $?CLASS"
 
-The resemblance to C<x> and C<xx> is not entirely accidental.
+The C<...> operator is the "yada, yada, yada" list operator, which
+among other things is used as the body in function prototypes.
+It complains bitterly (by calling C<fail>) if it is ever executed.
+Variant C<???> calls C<warn>, and C<!!!> calls C<die>.  The argument
+is optional, but if provided, is passed onto the C<fail>, C<warn>,
+or C<die>.  Otherwise the system will make up a message for you based
+on the context, indicating that you tried to execute something that
+is stubbed out.  (This message differs from what C<fail>, C<warn>, and
+C<die> would say by default, since the latter operators typically point
+out bad data or programming rather than just an incomplete design.)
 
 =item *
 
-Cross hyperoperators
+Reduce operators
 
-    X~X
-    X*X
-    XeqvX
-    etc.
+    [+] [*] [<] [\+] [\*] etc.
 
-See L</Cross operators>.
+See L<Reduction operators>.
 
 =item *
 
@@ -1152,26 +1147,35 @@
     &:
     @@:
 
-Like listops, these look like terms from the left, but raise their
-precedence on the right sufficiently to govern the list infix
-operators above:
+As listops, these look like terms from the left, but raise their
+precedence on the right sufficiently to govern list infix
+operators:
 
-     $: 1,2 ¥ 3,4       # [1,3,2,4]
+     $: 1,2 ¥ 3,4       # [[1,3],[2,4]]
      @: 1,2 ¥ 3,4       # 1,3,2,4
     @@: 1,2 ¥ 3,4       # [1,3],[2,4]
      %: 1,2 ¥ 3,4       # { 1 => 3, 2 => 4 }
 
-     $: 1,2 XX 3,4      # [1,3,1,4,2,3,2,4]
+     $: 1,2 XX 3,4      # [[1,3],[1,4],[2,3],[2,4]]
      @: 1,2 XX 3,4      # 1,3,1,4,2,3,2,4
     @@: 1,2 XX 3,4      # [1,3],[1,4],[2,3],[2,4]
 
 These can also influence the result of functions that returns lists of 
captures:
 
-     $: map { $_, $_*2 }, ^4   # [0,0,1,2,2,4,3,6]
+     $: map { $_, $_*2 }, ^4   # [[0,0],[1,2],[2,4],[3,6]]
      @: map { $_, $_*2 }, ^4   # 0,0,1,2,2,4,3,6
     @@: map { $_, $_*2 }, ^4   # [0,0],[1,2],[2,4],[3,6]
      %: map { $_, $_*2 }, ^4   # { 0 => 0, 1 => 2, 2 => 4, 3 => 6 }
 
+=item *
+
+The C<list> contextualizer
+
+    list
+
+Forces the subsequent expression to be evaluated in list context.
+Equivalent to C<@:>.
+
 =back
 
 =head2 Loose and precedence
@@ -1229,22 +1233,38 @@
 
 =head2 Terminator precedence
 
-As with terms, terminators are not really a precedence level, but looser
-than the loosest precedence level.  They all have the effect of terminating
-any operator precedence parsing and returning a complete expression to the main
-parser.
+As with terms, terminators are not really a precedence level, but
+looser than the loosest precedence level.  They all have the effect of
+terminating any operator precedence parsing and returning a complete
+expression to the main parser.  They don't care what state the operator
+precedence parser is in.  If the parser is currently expecting a term
+and the final operator in the expression can't deal with a nullterm,
+then it's a syntax error.  (Notably, the comma operator and many prefix
+list operators can handle a nullterm.)
 
 =over
 
 =item *
 
-infix:<;>
+Semicolon: ;
 
     $x = 1; $y = 2;
 
+The context determines how the expressions terminated by semicolon
+are interpreted.  At statement level they are statements.  Within
+a bracketing construct they are interpreted as multidimension slices.
+(Other contexts may have other interpretations or disallow semicolons
+entirely.)
+
+=item *
+
+Feed operators: <==, ==>
+
+    source() ==> filter() ==> sink()
+
 =item *
 
-{} as control block
+Control block: <ws>{...}
 
 When a block occurs after whitespace where an infix is expected, it is
 interpreated as a control block for a statement control construct.
@@ -1254,11 +1274,13 @@
 
 =item *
 
+Statement modifiers: if, unless, while, until, for
+
 Statement modifiers terminate one expression and start another.
 
 =item *
 
-Unmatched ), ], }, etc.
+Any unexpected ), ], } at this level.
 
 Calls into the operator precedence parser may be parameterized
 to recognize additional terminators, but right brackets of any
@@ -1270,6 +1292,12 @@
 for your weird operator.)  Angle brackets are exempted so that they
 can form hyperoperators (see L</Hyper operators>).
 
+=item *
+
+A block-final } at the end of the line terminates the current expression.
+A block within an argument list terminates the argument list unless
+followed by the comma operator.
+
 =back
 
 =head1 Changes to Perl 5 operators
@@ -2311,10 +2339,10 @@
 
 =head1 Feed operators
 
-The new operators C<< ==> >> and C<< <== >> are akin to UNIX pipes, but
-work with functions that accept and return lists.  Since these lists are
-composed of discrete objects and not liquids, we call these I<feed> operators
-rather than pipes.  For example,
+The new operators C<< ==> >> and C<< <== >> are akin to UNIX pipes,
+but work with functions or statements that accept and return lists.
+Since these lists are composed of discrete objects and not liquids,
+we call these I<feed> operators rather than pipes.  For example,
 
      @result = map { floor($^x / 2) },
                  grep { /^ \d+ $/ },

Modified: doc/trunk/design/syn/S06.pod
==============================================================================
--- doc/trunk/design/syn/S06.pod        (original)
+++ doc/trunk/design/syn/S06.pod        Sun Jan 28 16:04:21 2007
@@ -13,9 +13,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 21 Mar 2003
-  Last Modified: 23 Dec 2006
+  Last Modified: 28 Jan 2007
   Number: 6
-  Version: 66
+  Version: 67
 
 
 This document summarizes Apocalypse 6, which covers subroutines and the
@@ -821,9 +821,11 @@
 
 =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<< ==> >>.
+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
+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.
 
 Each operator expects to find a call to a variadic receiver on its
 "sharp" end, and a list of values on its "blunt" end:
@@ -869,33 +871,33 @@
 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 =
-            (@nums ==> grep { $_ % 2 } ==> sort ==> map { $_**2 });
+    @oddsquares = do
+            @nums ==> grep { $_ % 2 } ==> sort ==> map { $_**2 };
 
-Note that the parens are necessary there due to precedence.
+Note that the C<do> is necessary because feeds operate at the statement
+level.  (Parens would also work, since a "do" is assumed there.)
 
 If the operand on the sharp end of a feed is not a call to a variadic
 operation, it must be something else that can be interpreted as a
 list receiver.
 
-Any list operator is considered a variadic operation, so ordinarily
+Any prefix list operator is considered a variadic operation, so ordinarily
 a list operator adds any feed input to the end of its list.
-But sometimes you want to interpolate elsewhere, so the C<***> term
+But sometimes you want to interpolate elsewhere, so any empty contextualizer
 may be used to indicate the target of a feed without the use of a
 temporary array:
 
-    foo() ==> say ***, " is what I meant";
-    bar() ==> ***.baz();
+    foo() ==> say @(), " is what I meant";
+    bar() ==> (@@).baz();
 
-Feeding into the C<*> "whatever" term will extend the lexically
-following C<***> term:
+Feeding into the C<*> "whatever" term adds extra sources to the next sink:
 
     0..*       ==> *;
     'a'..*     ==> *;
     pidigits() ==> *;
 
     # outputs "(0, 'a', 3)\n"...
-    for zip(***) { .perl.say }
+    for zip(@@) { .perl.say }
 
 You may use a variable (or variable declaration) as a receiver, in
 which case the list value is bound as the "todo" of the variable.
@@ -941,7 +943,7 @@
 sometimes you want to capture the outputs as a list of two iterators,
 namely the two iterators that represent the two input feeds.  You can
 get at those two iterators by using the name C<@@foo> instead, where
-the "feed" twigil marks a multidimensional array, that is, an
+the "multislice" twigil marks a multidimensional array, that is, an
 array of slices.
 
     0..*       ==> @@foo;
@@ -996,21 +998,28 @@
     (0..2; 'a'..'c') ==> my @@tmp;
     for @@tmp.cat { .say }
 
-As we saw earlier, "zip" produces little arrays by taking one element
+As we saw earlier, "zip" produces an interleaved result by taking one element
 from each list in turn, so
 
     (0..2; 'a'..'c') ==> my @@tmp;
     for @@tmp.zip { .say }
 
-produces [0,'a'],[1,'b'],[2,'c'].  If you don't want the subarrays, then
-use C<each()> instead:
+produces 0,'a',1,'b',2,'c'.
+
+If you want the result as a list of subarrays, then you need to put
+the zip into a "chunky" context instead:
 
     (0..2; 'a'..'c') ==> my @@tmp;
-    for @@tmp.each { .say }
+    for @@tmp.zip.@@() { .say }
+
+This produces [0,'a'],[1,'b'],[2,'c'].  But usually you want the flat
+form so you can just bind it directly to a signature:
+
+    for @@tmp.zip -> $i, $a { say "$i: $a" }
 
-and then you just get 0,'a',1,'b',2,'c'.  This is good for
+Otherwise you'd have to say this:
 
-    for @@tmp.each -> $i, $a { say "$i: $a" }
+    for @@tmp.zip.@@() -> [$i, $a] { say "$i: $a" }
 
 In list context the C<@@foo> notation is really a shorthand for C<[;](@@foo)>.
 In particular, you can use C<@@foo> to interpolate a multidimensional slice
@@ -1026,41 +1035,21 @@
 So
 
     ('a'..*; 0..*) ==> *;
-     for zip(*** <== @foo) -> [$a, $i, $x] { ... }
+     for zip(@@() <== @foo) -> $a, $i, $x { ... }
 
 is the same as
 
     'a'..* ==> *;
      0..*  ==> *;
-     for zip(*** <== @foo) -> [$a, $i, $x] { ... }
+     for zip(@@ <== @foo) -> $a, $i, $x { ... }
 
 which is the same as
 
-    for zip('a'..*; 0..*; @foo) -> [$a, $i, $x] { ... }
-
-Likewise,
-
-    @foo ==> *;
-    0..* ==> *;
-    for each(***) -> $x, $i { ... }
-
-is the same as
-
-    0..* ==> *;
-    for each(@foo; ***) -> $x, $i { ... }
-
-and also
-
-    for each(@foo; 0..*) -> $x, $i { ... }
-
-Note that the C<each> method is also sensitive to multislicing, so you
-could also just write that as:
-
-    (@foo; 0..*).each: -> $x, $i { ... }
+    for zip('a'..*; 0..*; @foo) -> $a, $i, $x { ... }
 
 Also note that these come out to be identical for ordinary arrays:
 
-    @foo.each
+    @foo.zip
     @foo.cat
 
 The C<@@($foo)> coercer can be used to pull a multidim out of some

Reply via email to