Commit 5474e166 authored by Robert Griesemer's avatar Robert Griesemer

go spec: clarifications for range clause

R=iant, r, rsc, rog
CC=golang-dev
https://golang.org/cl/2226047
parent 2ccbf83b
<!-- title The Go Programming Language Specification -->
<!-- subtitle Version of Sep 27, 2010 -->
<!-- subtitle Version of Sep 28, 2010 -->
<!--
TODO
......@@ -14,7 +14,6 @@ TODO
[ ] should string(1<<s) and float(1<<s) be valid?
[ ] should probably write something about evaluation order of statements even
though obvious
[ ] specify iteration direction for range clause
[ ] review language on implicit dereferencing
[ ] clarify what it means for two functions to be "the same" when comparing them
-->
......@@ -3572,8 +3571,8 @@ f(x+y)
<p>
The "++" and "--" statements increment or decrement their operands
by the untyped <a href="#Constants">constant</a> <code>1</code>.
As with an assignment, the operand must be a variable, pointer indirection,
field selector or index expression.
As with an assignment, the operand must be <a href="#Address_operators">addressable</a>
or a map index expression.
</p>
<pre class="ebnf">
......@@ -3591,6 +3590,7 @@ x++ x += 1
x-- x -= 1
</pre>
<h3 id="Assignments">Assignments</h3>
<pre class="ebnf">
......@@ -3949,59 +3949,81 @@ for { S() } is the same as for true { S() }
<p>
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 first assigns the current index or key to an iteration
variable - or the current (index, element) or (key, value) pair to a pair
of iteration variables - and then executes the block.
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.
</p>
<pre class="ebnf">
RangeClause = ExpressionList ( "=" | ":=" ) "range" Expression .
</pre>
<p>
The type of the right-hand expression in the "range" clause must be an
array, slice, string or map, or a pointer to an array;
or it may be a channel.
Except for channels,
the identifier list must contain one or two expressions
(as in assignments, these must be a
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>
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
index of the first byte of successive UTF-8-encoded code points in the string, and
the second variable, of type <code>int</code>, will be the value of
RangeClause = Expression [ "," Expression ] ( "=" | ":=" ) "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.
As with an assignment, 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.
<p>
</p>
The range expression is evaluated once before beginning the loop.
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
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
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>
For channels, the identifier list must contain one identifier.
The iteration receives values sent on the channel until the channel is closed;
it does not process the zero value sent before the channel is closed.
The iteration values are assigned to the respective
iteration variables as in an <a href="#Assignments">assignment statement</a>.
</p>
<p>
The iteration variables may be declared by the "range" clause (":="), in which
case their scope ends at the end of the "for" statement (§<a href="#Declarations_and">Declarations and</a>
scope rules). In this case their types are set to
<code>int</code> and the array element type, or the map key and value types, respectively.
The iteration variables may be declared by the "range" clause (<code>:=</code>).
In this case their types are set to the types of the respective iteration values
and their <a href="#Declarations_and_scope">scope</a> ends at the end of the "for"
statement; they are re-used in each iteration.
If the iteration variables are declared outside the "for" statement,
after execution their values will be those of the last iteration.
</p>
......@@ -4026,11 +4048,6 @@ for key, val = range m {
// val == map[key]
</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>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment