Author: larry
Date: Tue Dec 19 01:02:59 2006
New Revision: 13494
Modified:
doc/trunk/design/syn/S06.pod
Log:
Rehuffmanized call/goto to callmumble/nextmumble at suggestion of TheDamian++.
Eliminated the capture forms since unary |$args is just fine for that.
Changed interaction of normal sigs and capture sigs to deal with ambiguities
pointed out by luqui++ on #perl6. Dual mapping now requires subsig syntax
so we can express invocants and multi types adequately. No longer a
requirement to support binding of partially bound captures.
Modified: doc/trunk/design/syn/S06.pod
==============================================================================
--- doc/trunk/design/syn/S06.pod (original)
+++ doc/trunk/design/syn/S06.pod Tue Dec 19 01:02:59 2006
@@ -15,7 +15,7 @@
Date: 21 Mar 2003
Last Modified: 18 Dec 2006
Number: 6
- Version: 64
+ Version: 65
This document summarizes Apocalypse 6, which covers subroutines and the
@@ -703,29 +703,39 @@
parameter marked with a C<|>.
sub bar ($a,$b,$c,:$mice) { say $mice }
- sub foo (|$args) { say |$args.perl; &bar.callc($args); }
+ sub foo (|$args) { say $args.perl; &bar.callwith(|$args); }
-The C<.callc> method of C<Code> objects takes a C<Capture> argument.
-The C<.callv> method accepts an ordinary variadic argument list, so the
-following is equivalent:
+This prints:
- sub foo (|$args) { say |$args.perl; &bar.callv(|$args); }
+ foo 1,2,3,:mice<blind>; # says "\(1,2,3,:mice<blind>)" then "blind"
-In either case, the wrapped routine is called
-without introducing an official C<CALLER> frame, and produces:
+As demonstrated above, the capture may be interpolated into another
+call's arguments. (The C<|> prefix is described in the next section.)
+Use of C<callwith> allows the routine to be called without introducing
+an official C<CALLER> frame. For more see "Wrapping" below.
- foo 1,2,3,:mice<blind>; # says "\(1,2,3,:mice<blind>)" then "blind"
+It is allowed to rebind the parameters within the signature, but
+only as a subsignature of the capture argument:
+
+ sub compare (|$args (Num $x, Num $y --> Bool)) { ... }
+
+For all normal declarative purposes (invocants and multiple dispatch
+types, for instance), the inner signature is treated as the entire
+signature:
-It is allowed to specify additional parameters within the signature.
-The C<Capture> binding merely takes a snapshot of what's left of
-the C<Capture> at that point and then continues binding as if the
-C<Capture> parameter weren't there:
+ method addto (|$args ($self: @x)) { trace($args); $self += [+] @x }
- sub compare (|$args, Num $x, Num $y --> Bool) { ... }
+The inner signature is not required for non-multies since there can
+only be one candidate, but for multiple dispatch the inner signature
+is required at least for its types, or the declaration would not know
+what signature to match against.
+
+ multi foo (|$args (Int; Bool?, *@, *%)) { reallyintfoo($args) }
+ multi foo (|$args (Str; Bool?, *@, *%)) { reallystrfoo($args) }
=head2 Flattening argument lists
-The unary C<|> operator casts its arguments to a C<Capture>
+The unary C<|> operator casts its argument to a C<Capture>
object, then splices that capture into the argument list
it occurs in. To get the same effect on multiple arguments you
can use the C<< |« >> hyperoperator.
@@ -1776,6 +1786,7 @@
trait_verb:<of>
trait_auxiliary:<is>
scope_declarator:<my>
+ statement_prefix:<do>
statement_control:<if>
statement_modifier:<if>
infix_prefix_meta_operator:<!>
@@ -2118,24 +2129,25 @@
=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> and C<callv> functions
will invoke
-the original routine, but do not introduce an official C<CALLER> frame:
+Every C<Routine> object has a C<.wrap> method. This method expects a
+single C<Code> argument. Within the code, the special C<callsame>,
+C<callwith>, C<nextsame> and C<nextwith> 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( { callv( ($^t-32)/1.8 ) } );
+ $handle = &thermo.wrap( { callwith( ($^t-32)/1.8 ) } );
-The C<callv> function lets you pass your own arguments to the wrapped
-function. The C<call> function takes an optional C<Capture> argument,
-with no arguments it implicitly passes the original argument list
-through unchanged.
+The C<callwith> function lets you pass your own arguments to the wrapped
+function. The C<callsame> function takes no argument; it
+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> or C<callv> invokes the
previous
-version of the routine. In other words, the call to C<.wrap> has more
-or less the same effect as:
+argument, and arranges that any call to C<callsame>, C<callwith>,
+C<nextsame> or C<nextwith> invokes the previous version of the
+routine. In other words, the call to C<.wrap> has more or less the
+same effect as:
&old_thermo := &thermo;
&thermo := sub ($t) { old_thermo( ($t-32)/1.8 ) }
@@ -2155,52 +2167,45 @@
# Add a wrapper to convert from Kelvin
# wrapper self-unwraps at end of current scope
- temp &thermo.wrap( { callv($^t + 273.16) } );
+ temp &thermo.wrap( { callwith($^t + 273.16) } );
The entire argument list may be captured by binding to a C<Capture> parameter.
-It can then be passed to C<call> using that name:
+It can then be passed to C<callwith> using that name:
# Double the return value for &thermo
- &thermo.wrap( -> |$args { call($args) * 2 } );
+ &thermo.wrap( -> |$args { callwith(|$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 one of its C<call> method:
+C<Code> object by passing the C<Capture> to its C<callwith> method:
# Transparently redirect all calls to &thermo to &other_thermo
- &thermo.wrap( sub (|$args) { &other_thermo.callv(|$args) } );
+ &thermo.wrap( sub (|$args) { &other_thermo.callwith(|$args) } );
or more briefly:
- &thermo.wrap( -> |$args { &other_thermo.callc($args) } );
-
-or even more briefly:
-
- &thermo.wrap( { &other_thermo.call } );
+ &thermo.wrap( { &other_thermo.callsame } );
-Outside a wrapper, the various C<call> and C<goto> functions and
-methods implicitly call the next-most-likely method or multi-sub;
-see S12 for details.
+Since the method versions of C<callsame>, C<callwith>, C<nextsame>,
+and C<nextwith> specify an explicit destination, their semantics do
+not change outside of wrappers. However, the corresponding functions
+have no explicit destination, so instead they 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 := callc($args);
+ my |$retval := callwith(|$args);
... # postprocessing
return |$retval;
Alternately, you may prevent any return at all by using the variants
-C<goto>, C<gotoc> and C<gotov>. Arguments are passed just as with
-C<call>, C<callc>, and C<callv>, but a tail call is explicitly
-enforced; any following code will be unreached. The C<callc> and
-C<gotoc> variants take a single optional C<Capture> argument supplying
-the new argument list; if not supplied, the incoming C<Capture> is
-passed verbatim (regardless of any capture bindings in the signature).
-You may also use the C<callv> or C<gotov> variants to pass an ordinary
-variadic argument list to the wrapped function. Use C<< prefix:<|>
->> to incorporate a capture (such as the original argument list)
-into the new argument list.
+C<nextsame> and C<nextwith>. Arguments are passed just as with
+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>.
=head2 The C<&?ROUTINE> object