Author: larry
Date: Fri Jun 16 15:06:45 2006
New Revision: 9680

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

Log:
Further decoupling of assignment parsing policy from behavior.


Modified: doc/trunk/design/syn/S03.pod
==============================================================================
--- doc/trunk/design/syn/S03.pod        (original)
+++ doc/trunk/design/syn/S03.pod        Fri Jun 16 15:06:45 2006
@@ -14,7 +14,7 @@
   Date: 8 Mar 2004
   Last Modified: 16 Jun 2006
   Number: 3
-  Version: 40
+  Version: 41
 
 =head1 Changes to existing operators
 
@@ -111,10 +111,10 @@
 
     loop ($a = 1, $b = 2; ; $a++, $b++) {...}
 
-still works fine.  The distinction between scalar and list
-assignment is similar to the way Perl 5 does it, but has to be a
+still works fine.  The syntactic distinction between scalar and list
+assignment is similar to the way Perl 5 defines it, but has to be a
 little different because we can no longer decide on the basis of
-the sigil.  The following forms are defined as "simple lvalues",
+the sigil.  The following forms are parsed as "simple lvalues",
 and imply scalar assignment:
 
     $a         # simple scalar variable
@@ -138,6 +138,10 @@
     !TERM      # any single term coerced to boolean
     (SIMPLE)   # any simple expression in circumfix parens
 
+Note that circumfix parens are considered simple only when used as
+part of a subscript.  Putting parens around the entire lvalue still
+implies list context as in Perl 5.
+
 We also include:
 
     OP SIMPLE  
@@ -154,24 +158,64 @@
 also excluded, but post-assigment forms such as C<SIMPLE += SIMPLE>
 are allowed.
 
-All other forms imply list assignment, and will evaluate both sides
-of the assignment in list context at runtime.  However, this is
-primarily a syntactic distinction, and no semantic or type information
+All other forms imply parsing as a list assignment, which may or may not
+result in a list assignment at run time.  (See below.) However, this is
+exclusively a syntactic distinction, and no semantic or type information
 is used, since it influences subsequent parsing.  In particular, even
 if a function is known to return a scalar value from its declaration,
-you must use C<+> or or C<~> to use it as a scalar within a subscript:
+you must use C<+> or or C<~> if you wish to force scalar parsing from
+within a subscript:
 
     @a[foo()] = bar();         # foo() and bar() called in list context
     @a[+foo()] = bar();                # foo() and bar() called in scalar 
context
 
-(But note that the first form still works fine if C<foo()> and C<bar()>
+But note that the first form still works fine if C<foo()> and C<bar()>
 are scalar functions that are not context sensitive.  The difference
 in parsing is only an issue if C<bar()> is followed by a comma or
-some such.)
+some such.
 
-Note that circumfix parens are considered simple only when used as
-part of a subscript.  Putting parens around the entire lvalue still
-implies list context as in Perl 5.
+For non-simple lvalues, at run time, both sides are evaluated in list
+context, but if the left side results in a single non-list scalar,
+the right side is treated as a single scalar value, as if the right
+side had been evaluated in list context (which is indeed the case)
+but coerced into scalar context.
+
+If the left side returns a list, however, then regardless of whether the
+list contains a single or multiple values, the right side is bound
+as in a list assignment, and any extra values are discarded.  To force
+list assignment even if the function returns a non-list, either put
+parens around the entire lvalue, or use a comma within the subscript.
+
+Assuming
+
+    sub bar { return <a b c> }
+
+then we have:
+
+    sub foo { return 1,2,3 }
+    @a[foo()] = bar();         # (@a[1,2,3]) = <a b c>
+
+    sub foo { return 1 }
+    @a[foo()] = bar();         # @a[1] = [<a b c>]
+
+    sub foo { return(1) }
+    @a[foo()] = bar();         # @a[1] = [<a b c>]
+
+    sub foo { return (1) }
+    @a[foo()] = bar();         # (@a[1,2,3]) = <a b c>
+
+    sub foo { return 1 }
+    @a[foo(),] = bar();                # (@a[1,2,3]) = <a b c>
+
+    sub foo { return 1 }
+    (@a[foo()]) = bar();       # (@a[1,2,3]) = <a b c>
+
+Those are all parsed as list assignments, but we get different run-time
+behaviors based on the run-time type of the left side.
+
+In general, this will all just do what the user expects most of the time.
+The rest of the time scalar or list behavior can be forced with minimal
+syntax.
 
 =item * List operators are all parsed consistently.  As in Perl 5,
 to the left they look like terms, while to the right they look like

Reply via email to