1
0
mirror of https://github.com/golang/go synced 2024-11-21 20:54:45 -07:00

go spec: clarifications for range clause

R=iant, r, rsc, rog
CC=golang-dev
https://golang.org/cl/2226047
This commit is contained in:
Robert Griesemer 2010-09-28 14:44:19 -07:00
parent 2ccbf83b32
commit 5474e166bc

View File

@ -1,5 +1,5 @@
<!-- title The Go Programming Language Specification --> <!-- title The Go Programming Language Specification -->
<!-- subtitle Version of Sep 27, 2010 --> <!-- subtitle Version of Sep 28, 2010 -->
<!-- <!--
TODO TODO
@ -14,7 +14,6 @@ TODO
[ ] should string(1<<s) and float(1<<s) be valid? [ ] should string(1<<s) and float(1<<s) be valid?
[ ] should probably write something about evaluation order of statements even [ ] should probably write something about evaluation order of statements even
though obvious though obvious
[ ] specify iteration direction for range clause
[ ] review language on implicit dereferencing [ ] review language on implicit dereferencing
[ ] clarify what it means for two functions to be "the same" when comparing them [ ] clarify what it means for two functions to be "the same" when comparing them
--> -->
@ -3572,8 +3571,8 @@ f(x+y)
<p> <p>
The "++" and "--" statements increment or decrement their operands The "++" and "--" statements increment or decrement their operands
by the untyped <a href="#Constants">constant</a> <code>1</code>. by the untyped <a href="#Constants">constant</a> <code>1</code>.
As with an assignment, the operand must be a variable, pointer indirection, As with an assignment, the operand must be <a href="#Address_operators">addressable</a>
field selector or index expression. or a map index expression.
</p> </p>
<pre class="ebnf"> <pre class="ebnf">
@ -3591,6 +3590,7 @@ x++ x += 1
x-- x -= 1 x-- x -= 1
</pre> </pre>
<h3 id="Assignments">Assignments</h3> <h3 id="Assignments">Assignments</h3>
<pre class="ebnf"> <pre class="ebnf">
@ -3949,59 +3949,81 @@ for { S() } is the same as for true { S() }
<p> <p>
A "for" statement with a "range" clause A "for" statement with a "range" clause
iterates through all entries of an array, slice, string or map, iterates through all entries of an array, slice, string or map,
or values received on a channel. or values received on a channel. For each entry it assigns <i>iteration values</i>
For each entry it first assigns the current index or key to an iteration to corresponding <i>iteration variables</i> and then executes the block.
variable - or the current (index, element) or (key, value) pair to a pair
of iteration variables - and then executes the block.
</p> </p>
<pre class="ebnf"> <pre class="ebnf">
RangeClause = ExpressionList ( "=" | ":=" ) "range" Expression . RangeClause = Expression [ "," Expression ] ( "=" | ":=" ) "range" Expression .
</pre> </pre>
<p> <p>
The type of the right-hand expression in the "range" clause must be an The expression on the right in the "range" clause is called the <i>range expression</i>,
array, slice, string or map, or a pointer to an array; which may be an array, pointer to an array, slice, string, map, or channel.
or it may be a channel. As with an assignment, the operands on the left must be
Except for channels, <a href="#Address_operators">addressable</a> or map index expressions; they
the identifier list must contain one or two expressions denote the iteration variables. If the range expression is a channel, only
(as in assignments, these must be a one iteration variable is permitted, otherwise there may be one or two.
variable, pointer indirection, field selector, or index expression)
denoting the
iteration variables. On each iteration,
the first variable is set to the string, array or slice index or
map key, and the second variable, if present, is set to the corresponding
string or array element or map value.
The types of the array or slice index (always <code>int</code>)
and element, or of the map key and value respectively,
must be <a href="#Assignability">assignable</a> to
the type of the iteration variables. The expression on the right hand
side is evaluated once before beginning the loop. At each iteration
of the loop, the values produced by the range clause are assigned to
the left hand side as in an <a href="#Assignments">assignment
statement</a>. Function calls on the left hand side will be evaluated
exactly once per iteration.
</p>
<p> <p>
For a value of a string type, the "range" clause iterates over the Unicode code points
in the string. On successive iterations, the index variable will be the </p>
index of the first byte of successive UTF-8-encoded code points in the string, and The range expression is evaluated once before beginning the loop.
the second variable, of type <code>int</code>, will be the value of Function calls on the left are evaluated once per iteration.
For each iteration, iteration values are produced as follows:
</p>
<pre class="grammar">
Range expression 1st value 2nd value (if 2nd variable is present)
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 int
map m map[K]V key k K m[k] V
channel c chan E element e E
</pre>
<ol>
<li>
For an array or slice value, the index iteration values are produced in
increasing order, starting at element index 0.
</li>
<li>
For a string value, the "range" clause iterates over the Unicode code points
in the string starting at byte index 0. On successive iterations, the index value will be the
index of the first byte of successive UTF-8-encoded code points in the string,
and the second value, of type <code>int</code>, will be the value of
the corresponding code point. If the iteration encounters an invalid the corresponding code point. If the iteration encounters an invalid
UTF-8 sequence, the second variable will be <code>0xFFFD</code>, UTF-8 sequence, the second value will be <code>0xFFFD</code>,
the Unicode replacement character, and the next iteration will advance the Unicode replacement character, and the next iteration will advance
a single byte in the string. a single byte in the string.
</p> </li>
<li>
The iteration order over maps is not specified.
If map entries that have not yet been reached are deleted during iteration,
the corresponding iteration values will not be produced. If map entries are
inserted during iteration, the behavior is implementation-dependent, but the
iteration values for each entry will be produced at most once.
</li>
<li>
For channels, the iteration values produced are the successive values sent on
the channel until the channel is closed; it does not produce the zero value sent
before the channel is closed
<a href="#Close_and_closed"><code>close</code> and <code>closed</code></a>).
</li>
</ol
<p> <p>
For channels, the identifier list must contain one identifier. The iteration values are assigned to the respective
The iteration receives values sent on the channel until the channel is closed; iteration variables as in an <a href="#Assignments">assignment statement</a>.
it does not process the zero value sent before the channel is closed.
</p> </p>
<p> <p>
The iteration variables may be declared by the "range" clause (":="), in which The iteration variables may be declared by the "range" clause (<code>:=</code>).
case their scope ends at the end of the "for" statement (§<a href="#Declarations_and">Declarations and</a> In this case their types are set to the types of the respective iteration values
scope rules). In this case their types are set to and their <a href="#Declarations_and_scope">scope</a> ends at the end of the "for"
<code>int</code> and the array element type, or the map key and value types, respectively. statement; they are re-used in each iteration.
If the iteration variables are declared outside the "for" statement, If the iteration variables are declared outside the "for" statement,
after execution their values will be those of the last iteration. after execution their values will be those of the last iteration.
</p> </p>
@ -4026,11 +4048,6 @@ for key, val = range m {
// val == map[key] // val == map[key]
</pre> </pre>
<p>
If map entries that have not yet been processed are deleted during iteration,
they will not be processed. If map entries are inserted during iteration, the
behavior is implementation-dependent, but each entry will be processed at most once.
</p>
<h3 id="Go_statements">Go statements</h3> <h3 id="Go_statements">Go statements</h3>