Author: larry Date: Wed Sep 20 22:07:47 2006 New Revision: 12284 Modified: doc/trunk/design/syn/S02.pod doc/trunk/design/syn/S03.pod doc/trunk/design/syn/S06.pod doc/trunk/design/syn/S12.pod
Log: The | sigil and operator. Modified: doc/trunk/design/syn/S02.pod ============================================================================== --- doc/trunk/design/syn/S02.pod (original) +++ doc/trunk/design/syn/S02.pod Wed Sep 20 22:07:47 2006 @@ -12,9 +12,9 @@ Maintainer: Larry Wall <[EMAIL PROTECTED]> Date: 10 Aug 2004 - Last Modified: 18 Sept 2006 + Last Modified: 20 Sept 2006 Number: 2 - Version: 69 + Version: 70 This document summarizes Apocalypse 2, which covers small-scale lexical items and typological issues. (These Synopses also contain @@ -670,6 +670,7 @@ @ ordered array % unordered hash (associative array) & code/rule/token/regex + | capture/arguments/match :: package/module/class/role/subset/enum/type/grammar @@ multislice view of @ @@ -817,15 +818,22 @@ $$args; # same as "$args as Scalar" or "Scalar($args)" @$args; # same as "$args as Array" or "Array($args)" %$args; # same as "$args as Hash" or "Hash($args)" + |$args; # all of the above When cast into an array, you can access all the positional arguments; into a hash, all named arguments; into a scalar, its invocant. +When stored in a variable using the C<|> sigil, the capture autointerpolates +into argument lists much like C<@> autoflattens into lists: + + |args := \($a, @b, :option($c)); + somefunc(|args); # same as somefunc($a, @b, :option($c)) + All prefix sigil operators accept one positional argument, evaluated in scalar context as a rvalue. They can interpolate in strings if called with parentheses. The special syntax form C<$()> translates into C<$( $/ )> to operate on the current match object; the same applies to C<@()>, C<%()> and -C<*()> forms. +C<|()> forms. C<Capture> objects fill the ecological niche of references in Perl 6. You can think of them as "fat" references, that is, references that Modified: doc/trunk/design/syn/S03.pod ============================================================================== --- doc/trunk/design/syn/S03.pod (original) +++ doc/trunk/design/syn/S03.pod Wed Sep 20 22:07:47 2006 @@ -12,9 +12,9 @@ Maintainer: Larry Wall <[EMAIL PROTECTED]> Date: 8 Mar 2004 - Last Modified: 16 Sep 2006 + Last Modified: 20 Sept 2006 Number: 3 - Version: 66 + Version: 67 =head1 Changes to Perl 5 operators @@ -65,7 +65,8 @@ argument, and C<+> imposes a numeric (C<Num>) context (as opposed to being a no-op in Perl 5). Along the same lines, C<?> imposes a boolean (C<Bool>) context, and the C<[,]> list operator imposes -a function-arguments (C<Capture>) context on its arguments. +a function-arguments (C<Capture>) context on its arguments (as does +the C<|> sigil when used as an operator). Unary sigils impose the container context implied by their sigil. As with Perl 5, however, C<$$foo[bar]> parses as C<( $($foo) )[bar]>, so you need C<$($foo[bar])> to mean the other way. @@ -1295,11 +1296,14 @@ interpolator, by casting its operands to C<Capture> objects and inserting them into the current argument list. -It can be used to interpolate an C<Array> or C<Hash> into the current -call, as positional and named arguments respectively. +The C<|> capture sigil may also be used for this when you want to +interpolate a single item. + +Either of these can be used to interpolate an C<Array> or C<Hash> +into the current call, as positional and named arguments respectively. Note that those arguments still must comply with the subroutine's -signature, but the presence of C<[,]> defers that test until run time for +signature, but the presence of C<|> or C<[,]> defers that test until run time for that argument (and for any subsequent arguments): my @args = [EMAIL PROTECTED], @bar; @@ -1312,7 +1316,16 @@ as is this: my $args = \(@foo, @bar); # construct a Capture object - push [,] @$args; + push |$args; + +The C<|> sigil functions as a unary form of the C<[,]> +list operator, so we could have written the earlier example as: + + my @args = [EMAIL PROTECTED], @bar; + push |@args; + +To the extent possible, the C<|> will treat its argument as +a C<Capture> even if it isn't. In list context, a C<Scalar> holding an C<Array> object does not flatten. Hence @@ -1320,15 +1333,16 @@ push @foo, $bar; merely pushes a single C<Array> object onto C<@foo>. You can -explicitly flatten it in either of these ways: +explicitly flatten it in one of these ways: push @foo, @$bar; push @foo, $bar[]; + push @foo, |$bar; -Those two forms work because the slurpy array in C<push>'s signature +Those three forms work because the slurpy array in C<push>'s signature flattens the C<Array> object into a list argument. -Note that those two forms also allow you to specify list context on +Note that the first two forms also allow you to specify list context on assignment: @$bar = 1,2,3; @@ -1351,18 +1365,20 @@ as well as the C<< <> >>, C<< .<> >>, C<«»>, and C<.«»> constant and interpolating slice subscripting forms. -The C<[,]> operator interpolates lazily for C<Array> and C<Range> objects. +The C<[,]> and C<|> operators interpolate lazily for C<Array> and C<Range> objects. To get an immediate interpolation like Perl 5 does, add the C<eager> list operator: func([,] 1..Inf); # works fine func([,] eager 1..Inf); # never terminates -To interpolate a function's return value, you must say: +To interpolate a function's return value, you must say one of: push [,] func(); + push |(func()); + push |func(); # WRONG, would parse as (|func).() -Within the argument list of a C<[,]>, function return values are +Within such an argument list, function return values are automatically exploded into their various parts, as if you'd said: my \$capture := func(); @@ -1375,12 +1391,17 @@ as if its colon changed back to a comma. If you already have a capture variable, you can interpolate all of -its bits at once using the C<< prefix:<=> >> operator, which serves -to iterate or dereference a scalar that would otherwise stay packed -into its scalar value. The above is equivalent to: +its bits at once using the C<< prefix:<|> >> operator (really a sigil). my \$capture := func(); - push [,] =$capture; + push |$capture; + +Or you can use the bare sigiled forms: + + my |capture := func(); + push |capture; + +Bare lvalue capture variables may only be bound, not assigned. =head1 Feed operators @@ -1551,7 +1572,7 @@ method postfix .meth .+ .? .* .() .[] .{} .<> .«» .:: .= .^ autoincrement ++ -- exponentiation ** - symbolic unary ! + - ~ ? $ @ % & +^ ~^ ?^ \ ^ = + symbolic unary ! + - ~ ? $ @ % & | +^ ~^ ?^ \ ^ = multiplicative * / % x xx +& +< +> ~& ~< ~> ?& additive + - ~ +| +^ ~| ~^ ?| ?^ junctive and (all) & Modified: doc/trunk/design/syn/S06.pod ============================================================================== --- doc/trunk/design/syn/S06.pod (original) +++ doc/trunk/design/syn/S06.pod Wed Sep 20 22:07:47 2006 @@ -373,23 +373,21 @@ doit :123<now>; # always a positional arg Going the other way, pairs intended as named arguments that don't look -like pairs must be introduced with the C<[,]> reduction operator: +like pairs must be introduced with the C<[,]> reduction operator or +the C<|> capture sigil: $pair = :when<now>; - doit $pair,1,2,3; # always a positional arg - doit [,] %$pair,1,2,3; # always a named arg - doit [,] %(get_pair()),1,2,3; # always a named arg - doit [,] %('when' => 'now'),1,2,3; # always a named arg - -Note that, to apply C<[,]> to a single arg you may need to use parentheses. -In general it doesn't matter. + doit $pair,1,2,3; # always a positional arg + doit |%$pair,1,2,3; # always a named arg + doit |%(get_pair()),1,2,3; # always a named arg + doit |%('when' => 'now'),1,2,3; # always a named arg Likewise, if you wish to pass a hash and have its entries treated as -named arguments, you must dereference it with a C<[,]>: +named arguments, you must dereference it with a C<[,]> or C<|>: %pairs = {:when<now> :what<any>}; doit %pairs,1,2,3; # always a positional arg - doit [,](%pairs),1,2,3; # always named args + doit |%pairs,1,2,3; # always named args Variables with a C<:> prefix in rvalue context autogenerate pairs, so you can also say this: @@ -465,7 +463,7 @@ parameters, similar to how hash constructors work: # Allow "x" and "y" in %defaults to be overridden - f( [,](%defaults), x => 1, y => 2 ); + f( |%defaults, x => 1, y => 2 ); =head2 Invocant parameters @@ -699,41 +697,39 @@ =head2 Argument list binding The underlying C<Capture> object may be bound to a single scalar -parameter marked with a C<\>. +parameter marked with a C<|> sigil. sub bar ($a,$b,$c,:$mice) { say $mice } - sub foo (\$args) { say $args.perl; &bar.call($args); } + sub foo (|args) { say |args.perl; &bar.callargs(|args); } -The C<.call> method of C<Code> objects accepts a single C<Capture> -object, and calls it without introducing a C<CALLER> frame. +The C<.callargs> method of C<Code> objects accepts an argument list, +(which can be specified as a Capture object as above), and calls it +without introducing an official C<CALLER> frame. foo 1,2,3,:mice<blind>; # says "\(1,2,3,:mice<blind>)" then "blind" -It is allowed to specify a return type: - - sub foo (\$args --> Num) { ... } +It is allowed to specify additional parameters. The Capture binding merely +takes a snapshot of what's left of the Capture at that point and then +continues binding as if the Capture parameter weren't there: -Apart from that, no other parameters are allowed in the signature -after the C<Capture>. Parameters before the C<Capture> either do not show up in -the C<Capture> or are marked as already bound somehow. In other words, -parameters are bound normally up to the C<Capture> parameter, and then -C<\$args> takes a snapshot of the remaining input without further -attempts at binding. + sub compare (|args Num $x, Num $y --> Bool) { ... } =head2 Flattening argument lists The reduce operator C<[,]> casts each of its arguments to a C<Capture> object, then splices each of those captures into the argument list -it occurs in. +it occurs in. The unary C<|> sigil has the same effect on a single +argument. Casting C<Capture> to C<Capture> is a no-op: [,](\(1, x=>2)); # Capture, becomes \(1, x=>2) + |(\(1, x=>2)); # Capture, becomes \(1, x=>2) C<Pair> and C<Hash> become named arguments: - [,](x=>1); # Pair, becomes \(x=>1) - [,]{x=>1, y=>2}; # Hash, becomes \(x=>1, y=>2) + |(x=>1); # Pair, becomes \(x=>1) + |{x=>1, y=>2}; # Hash, becomes \(x=>1, y=>2) C<List> (also C<Seq>, C<Range>, etc.) are simply turned into positional arguments: @@ -750,7 +746,7 @@ foo(1,2,3); # okay: three args found foo(@onetothree); # error: only one arg - foo([,[EMAIL PROTECTED]); # okay: @onetothree flattened to three args + foo(|@onetothree); # okay: @onetothree flattened to three args The C<[,]> operator flattens lazily -- the array is flattened only if flattening is actually required within the subroutine. To flatten before @@ -1922,7 +1918,7 @@ On the caller's end, the C<Capture> is interpolated into any new argument list much like an array would be, that is, as a scalar in scalar context, and as a list in list context. This is the default behavior, but as with an array, the -caller may use C<< prefix:<[,]> >> to inline the returned values as part of the +caller may use C<< prefix:<[,]> >> or the C<|> sigil to inline the returned values as part of the new argument list. The caller may also bind the returned C<Capture> directly. =head2 The C<caller> function @@ -2081,16 +2077,20 @@ =head2 Wrapping Every C<Routine> object has a C<.wrap> method. This method expects a single -C<Code> argument. Within the code, the special C<call> function will invoke -the original routine, but does not introduce a C<CALLER> frame: +C<Code> argument. Within the code, the special C<call> and C<callargs> functions will invoke +the original routine, but do not introduce an official C<CALLER> frame: sub thermo ($t) {...} # set temperature in Celsius, returns old value # Add a wrapper to convert from Fahrenheit... - $handle = &thermo.wrap( { call( ($^t-32)/1.8 ) } ); + $handle = &thermo.wrap( { callargs( ($^t-32)/1.8 ) } ); + +The C<callargs> function lets you pass your own arguments to the wrapped +function. The C<call> function takes no arguments and implicitly passes +the original argument list through unchanged. The call to C<.wrap> replaces the original C<Routine> with the C<Code> -argument, and arranges that the call to C<call> invokes the previous +argument, and arranges that the call to C<call> or C<callargs> invokes the previous version of the routine. In other words, the call to C<.wrap> has more or less the same effect as: @@ -2112,29 +2112,35 @@ # Add a wrapper to convert from Kelvin # wrapper self-unwraps at end of current scope - temp &thermo.wrap( { call($^t + 273.16) } ); + temp &thermo.wrap( { callargs($^t + 273.16) } ); -The entire argument list may be captured by the C<\$args> parameter. -It can then be passed to C<call> as C<[,] =$args>: +The entire argument list may be captured by binding to a Capture parameter. +It can then be passed to C<callargs> using that name: # Double the return value for &thermo - &thermo.wrap( -> \$args { call([,] =$args) * 2 } ); + &thermo.wrap( -> |args { callargs(|args) * 2 } ); + +In this case only the return value is changed. The wrapper is not required to call the original routine; it can call another C<Code> object by passing the C<Capture> to its C<call> method: # Transparently redirect all calls to &thermo to &other_thermo - &thermo.wrap( -> \$args { &other_thermo.call($args) } ); + &thermo.wrap( -> |args { &other_thermo.callargs(|args) } ); + +or more briefly: + + &thermo.wrap( { &other_thermo.call } ); -Outside a wrapper, C<call> implicitly calls the next-most-likely method -or multi-sub; see S12 for details. +Outside a wrapper, the various C<call> functions and methods implicitly +call the next-most-likely method or multi-sub; see S12 for details. As with any return value, you may capture the returned C<Capture> of C<call> by binding: - my \$retval := call([,] =$args); + my |retval := callargs(|args); ... # postprocessing - return [,] =$retval; + return |retval; =head2 The C<&?ROUTINE> object @@ -2584,7 +2590,7 @@ and pass the resulting C<Match> object as a C<Capture> to C<MAIN>: @*ARGS ~~ /<MyGrammar::top>/; - MAIN([,] =$/); + MAIN(|$/); exit; sub MAIN ($frompart, $topart, [EMAIL PROTECTED]) { Modified: doc/trunk/design/syn/S12.pod ============================================================================== --- doc/trunk/design/syn/S12.pod (original) +++ doc/trunk/design/syn/S12.pod Wed Sep 20 22:07:47 2006 @@ -12,9 +12,9 @@ Maintainer: Larry Wall <[EMAIL PROTECTED]> Date: 27 Oct 2004 - Last Modified: 14 Sept 2006 + Last Modified: 20 Sept 2006 Number: 12 - Version: 26 + Version: 27 =head1 Overview @@ -1165,7 +1165,7 @@ Since the method name (but nothing else) is known at class construction time, the following C<.wag> method is autogenerated for you: - method wag ([EMAIL PROTECTED] is context(Lazy)) { $!tail.wag([,] @args) } + method wag ([EMAIL PROTECTED] is context(Lazy)) { $!tail.wag(|@args) } You can specify multiple method names: @@ -1175,7 +1175,7 @@ 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.