Author: larry
Date: Thu May 31 22:43:55 2007
New Revision: 14411

Modified:
   doc/trunk/design/syn/S12.pod

Log:
There is no longer any run-time dwimmery in indirect dispatch.
Now use $obj."$foo" exclusively for symbolic method indirection
$obj.$var and [EMAIL PROTECTED] forms now allow *only* hard refs to Code 
objects.
Prefix ops written as postfix no longer use quote form, but $obj.prefix:<+>
$obj.:<+> is allowed as a shorthand for $obj.prefix:<+>
Clarified that all anonymous Code objects are closures, not methods.
WALK pseudo-class is dead.  Now just use .WALK method to return candidates.


Modified: doc/trunk/design/syn/S12.pod
==============================================================================
--- doc/trunk/design/syn/S12.pod        (original)
+++ doc/trunk/design/syn/S12.pod        Thu May 31 22:43:55 2007
@@ -12,9 +12,9 @@
 
   Maintainer: Larry Wall <[EMAIL PROTECTED]>
   Date: 27 Oct 2004
-  Last Modified: 29 May 2007
+  Last Modified: 31 May 2007
   Number: 12
-  Version: 53
+  Version: 54
 
 =head1 Overview
 
@@ -218,15 +218,30 @@
 
     .doit(1,2,3)
 
-It can use a simple scalar variable for the method name:
+There are several forms of indirection for the method name.  You can
+replace the identifier with a quoted string, and it will be evaluated
+as a quote and then the result of that is used as the method name.
 
-    $obj.$methodname(1,2,3)
+    $obj."$methodname"(1,2,3)   # use contents of $methodname as method name
+    $obj.'$methodname'(1,2,3)   # no interpolation; call method with $ in name!
 
-The variable may contain either the name of a method or a closure
-object.  In the latter case the closure is called with the object
-as its first argument, so that a closure may be used to abstract a
+For situations where you already have a method located, you
+can use a simple scalar variable in place of method name:
+
+    $methodobj = $foo ?? &bar !! &baz;
+    $obj.$methodobj(1,2,3)
+
+or more succinctly but less readably:
+
+    $obj.$($foo ?? &bar !! &baz)(1,2,3)
+
+The variable must contain a Code object, that is, a closure of some
+sort.  Regardless of whether the closure was defined as a method or
+a sub or a block, the closure is called as a method, with the object
+as its first argument, and the rest of the arguments second, third,
+and so on.   For instance, such a closure may be used to abstract a
 "navigational" path through a data structure without specifying the
-root of the path till later.
+root of the path till later:
 
     $locator = -> $root, $x, $y { $root.<foo>[$x]<bar>{$y}[3] }
     $obj.$locator(42,"baz")  # $obj<foo>[42]<bar><baz>[3]
@@ -234,30 +249,61 @@
     $locator = { .<here> }
     $obj.$locator            # $obj<here>
 
-The method name may also be quoted with either single or double quotes:
-
-    $obj."$methodname"(1,2,3)   # same as previous
-    $obj.'$methodname'(1,2,3)   # call method with $ in name!
+As a convenient form of documentation, such a closure may also be written
+in the form of an anonymous method:
 
-The latter is especially useful for postfix forms that might be confusing
-to the lexer or to the human reader:
-
-    $filename.'+'      # same as +$filename.
-    .'+'               # same as +$_
-
-And in fact, if there is a choice between a unary prefix and a postfix
-operator, the quoted forms will choose the prefix operator.  See S03.
-Likewise, presuming that C<$op> does not name an ordinary method on
-C<$left>, this calls any arbitrary infix operator:
+    $locator = method ($root: $x, $y) { $root.<foo>[$x]<bar>{$y}[3] }
+    $obj.$locator(42,"baz")  # $obj<foo>[42]<bar><baz>[3]
 
-    $left.$op($right)
+    $locator = method { self.<here> }
+    $obj.$locator            # $obj<here>
 
-Of course you can force that with:
+Note however that, like any anonymous closure, an anonymous method
+can only be dispatched to directly, like a sub.  You may, of course,
+bind an anonymous method to the name of a method in a class's public
+interface, in which case it is no longer anonymous, and may be
+dispatched to normally via the class.  (And in fact, when the normal
+method dispatcher is calling individual candidates in its candidate
+list, it calls each candidate as a sub, not as a method, or you'd
+end up with recursive dispatchers.)  But fundamentally, there's
+no such thing as a method closure.  The C<method> declarator on an
+anonymous method has the primary effect of making the declaration
+of the invocant optional.  (It also makes it an official C<Routine>
+that can be returned from, just as if you'd used C<sub> to declare it.)
+
+Instead of a scalar variable, an array variable may also be used:
+
+    [EMAIL PROTECTED](1,2,3)
+
+As with the scalar variant, each array element must be a Code object,
+but the list is treated as a list of candidates to call.
+
+Another form of indirection relies on the fact that operators are named
+using a variant on hash subscript notation, which gives you these forms:
+
+    $x.infix:{$op}($y)
+    $x.prefix:{$op}
+    $x.postfix:{$op}
+
+Generally you see these with the literal angle bracket form of subscript:
+
+    $a.infix:<*>($b)      # equivalent to $a * $b
+    $a.prefix:<++>        # equivalent to ++$a
+    $a.postfix:<++>       # equivalent to $a++
+
+If you omit the syntactic category, the call will be dispatched according
+to the number of arguments either as "prefix" or as "infix":
+
+    $a.:<+>($b)           # equivalent to $a + $b
+    $a.:<++>              # equivalent to ++$a
+    $a.:<!>               # equivalent to !$a
+    @a.:<[*]>             # equivalent to [*] @a
 
-    $left.infix:{$op}($right)
+But it's probably better to spell out the syntactic category when
+the actual operator is not obvious:
 
-The C<q> forms of quoting are not allowed for method indirection,
-since they'd be taken as ordinary method names.
+    $x.infix:{$op}($y)
+    $x.prefix:{$op}
 
 You must use a special syntax to call a private method:
 
@@ -651,7 +697,8 @@
 are expected to return a value that can be used as a boolean.
 While this is primarily intended for use by file tests, other classes
 may define such methods to provide a similar mechanism for interrogating
-properties.
+properties.  (Also note that syntactic category names are reserved for
+calling operators as if they were methods.)
 
 Depending on the class, the pairs in question may have arguments.
 The C<Hash> class in particular makes use of pair syntax for subscript
@@ -691,12 +738,15 @@
     $object."+meth"(@args)
     $object.'VAR'(@args)
 
-The order and selection of the candidates may be
-specified by arguments to a pseudo-class known as C<WALK>:
+As with ordinary calls, the identifier supplying the literal method
+name may be replaced with an interpolated quote to specify the method
+name indirectly.  It may also be replaced with an array to specify
+the exact list of candidates to be considered:
 
-    $object.*WALK[:breadth:omit($?CLASS)]::meth(@args);
+    my @candidates := $object.WALK(:name<foo>, :breadth, :omit($?CLASS));
+    [EMAIL PROTECTED](@args);
 
-The C<WALK> pseudo-class takes these arguments:
+The C<WALK> method takes these arguments:
 
     :canonical      # canonical dispatch order
     :ascendant      # most-derived first, like destruction order
@@ -705,7 +755,7 @@
     :breadth        # like multi dispatch
 
     :super              # only immediate parent classes
-    :method<name>       # only classes containing method declaration
+    :name<name>         # only classes containing named method declaration
     :omit(Selector)     # only classes that don't match selector
     :include(Selector)  # only classes that match selector
 
@@ -770,6 +820,9 @@
 
     $junction.values».meth(@args);
 
+As with other forms of method call, the "meth" above may be replaced
+with a quoted string or variable to do various forms of indirection.
+
 =head1 Multisubs and Multimethods
 
 The "long name" of a subroutine or method includes the type signature

Reply via email to