]> Cypherpunks repositories - gostls13.git/commitdiff
spec: permit "for range x" (no index variables)
authorRobert Griesemer <gri@golang.org>
Mon, 14 Jul 2014 22:08:09 +0000 (15:08 -0700)
committerRobert Griesemer <gri@golang.org>
Mon, 14 Jul 2014 22:08:09 +0000 (15:08 -0700)
This is a fully backward-compatible language change.

There are not a lot of cases in the std library, but
there are some. Arguably this makes the syntax a bit
more regular - any trailing index variable that is _
can be left away, and there's some analogy to type
switches where the temporary can be left away.

Implementation-wise the change should be trivial as
it can be done completely syntactically. For instance,
the respective change in go/parser is a dozen lines
(see https://golang.org/cl/112970044 ).

Fixes #6102.

LGTM=iant, r, rsc
R=r, rsc, iant, ken
CC=golang-codereviews
https://golang.org/cl/104680043

doc/go_spec.html

index ca9e50203ef4dcb649a08c31e870f7688ae8ab6b..883237537805a0d392fb69ac9128c75dd4cc765c 100644 (file)
@@ -1,6 +1,6 @@
 <!--{
        "Title": "The Go Programming Language Specification",
-       "Subtitle": "Version of June 24, 2014",
+       "Subtitle": "Version of July 14, 2014",
        "Path": "/ref/spec"
 }-->
 
@@ -4714,41 +4714,42 @@ for      { S() }    is the same as    for true     { S() }
 A "for" statement with a "range" clause
 iterates through all entries of an array, slice, string or map,
 or values received on a channel. For each entry it assigns <i>iteration values</i>
-to corresponding <i>iteration variables</i> and then executes the block.
+to corresponding <i>iteration variables</i> if present and then executes the block.
 </p>
 
 <pre class="ebnf">
-RangeClause = ( ExpressionList "=" | IdentifierList ":=" ) "range" Expression .
+RangeClause = [ ExpressionList "=" | IdentifierList ":=" ] "range" Expression .
 </pre>
 
 <p>
 The expression on the right in the "range" clause is called the <i>range expression</i>,
 which may be an array, pointer to an array, slice, string, map, or channel permitting
 <a href="#Receive_operator">receive operations</a>.
-As with an assignment, the operands on the left must be
+As with an assignment, if present the operands on the left must be
 <a href="#Address_operators">addressable</a> or map index expressions; they
-denote the iteration variables. If the range expression is a channel, only
-one iteration variable is permitted, otherwise there may be one or two. In the latter case,
-if the second iteration variable is the <a href="#Blank_identifier">blank identifier</a>,
-the range clause is equivalent to the same clause with only the first variable present.
+denote the iteration variables. If the range expression is a channel, at most
+one iteration variable is permitted, otherwise there may be up to two.
+If the last iteration variable is the <a href="#Blank_identifier">blank identifier</a>,
+the range clause is equivalent to the same clause without that identifier.
 </p>
 
 <p>
 The range expression is evaluated once before beginning the loop,
-with one exception. If the range expression is an array or a pointer to an array
-and only the first iteration value is present, only the range expression's
-length is evaluated; if that length is constant
-<a href="#Length_and_capacity">by definition</a>,
+with one exception: if the range expression is an array or a pointer to an array
+and at most one iteration variable is present, only the range expression's
+length is evaluated; if that length is constant,
+<a href="#Length_and_capacity">by definition</a>
 the range expression itself will not be evaluated.
 </p>
 
 <p>
 Function calls on the left are evaluated once per iteration.
-For each iteration, iteration values are produced as follows:
+For each iteration, iteration values are produced as follows
+if the respective iteration variables are present:
 </p>
 
 <pre class="grammar">
-Range expression                          1st value          2nd value (if 2nd variable is present)
+Range expression                          1st value          2nd value
 
 array or slice  a  [n]E, *[n]E, or []E    index    i  int    a[i]       E
 string          s  string type            index    i  int    see below  rune
@@ -4760,7 +4761,7 @@ channel         c  chan E, &lt;-chan E       element  e  E
 <li>
 For an array, pointer to array, or slice value <code>a</code>, the index iteration
 values are produced in increasing order, starting at element index 0.
-If only the first iteration variable is present, the range loop produces
+If at most one iteration variable is present, the range loop produces
 iteration values from 0 up to <code>len(a)-1</code> and does not index into the array
 or slice itself. For a <code>nil</code> slice, the number of iterations is 0.
 </li>
@@ -4841,6 +4842,9 @@ var ch chan Work = producer()
 for w := range ch {
        doWork(w)
 }
+
+// empty a channel
+for range ch {}
 </pre>