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