mirror of
https://github.com/golang/go
synced 2024-11-25 07:57:56 -07:00
language for range clause
(I have deliberately left away the forms w/ := or = and the forms with :) R=r DELTA=106 (44 added, 13 deleted, 49 changed) OCL=21192 CL=21283
This commit is contained in:
parent
ef77c22626
commit
30a1a8c922
125
doc/go_spec.txt
125
doc/go_spec.txt
@ -28,7 +28,6 @@ Timeline (9/5/08):
|
|||||||
|
|
||||||
Missing:
|
Missing:
|
||||||
[ ] partial export of structs, methods
|
[ ] partial export of structs, methods
|
||||||
[ ] range statement: to be defined more reasonably
|
|
||||||
[ ] packages of multiple files
|
[ ] packages of multiple files
|
||||||
[ ] Helper syntax for composite types: allow names/indices for maps/arrays,
|
[ ] Helper syntax for composite types: allow names/indices for maps/arrays,
|
||||||
remove need for type in elements of composites
|
remove need for type in elements of composites
|
||||||
@ -56,7 +55,6 @@ Open issues:
|
|||||||
[ ] old-style export decls (still needed, but ideally should go away)
|
[ ] old-style export decls (still needed, but ideally should go away)
|
||||||
[ ] like to have assert() in the language, w/ option to disable code gen for it
|
[ ] like to have assert() in the language, w/ option to disable code gen for it
|
||||||
[ ] composite types should uniformly create an instance instead of a pointer
|
[ ] composite types should uniformly create an instance instead of a pointer
|
||||||
[ ] semantics of statements
|
|
||||||
[ ] need for type switch? (or use type guard with ok in tuple assignment?)
|
[ ] need for type switch? (or use type guard with ok in tuple assignment?)
|
||||||
[ ] do we need anything on package vs file names?
|
[ ] do we need anything on package vs file names?
|
||||||
[ ] type switch or some form of type test needed
|
[ ] type switch or some form of type test needed
|
||||||
@ -93,6 +91,8 @@ Decisions in need of integration into the doc:
|
|||||||
|
|
||||||
|
|
||||||
Closed:
|
Closed:
|
||||||
|
[x] semantics of statements - we just need to fill in the language, the semantics is mostly clear
|
||||||
|
[x] range statement: to be defined more reasonably
|
||||||
[x] need to be specific on (unsigned) integer operations: one must be able
|
[x] need to be specific on (unsigned) integer operations: one must be able
|
||||||
to rely on wrap-around on overflow
|
to rely on wrap-around on overflow
|
||||||
[x] global var decls: "var a, b, c int = 0, 0, 0" is ok, but "var a, b, c = 0, 0, 0" is not
|
[x] global var decls: "var a, b, c int = 0, 0, 0" is ok, but "var a, b, c = 0, 0, 0" is not
|
||||||
@ -198,7 +198,6 @@ Contents
|
|||||||
If statements
|
If statements
|
||||||
Switch statements
|
Switch statements
|
||||||
For statements
|
For statements
|
||||||
Range statements
|
|
||||||
Go statements
|
Go statements
|
||||||
Select statements
|
Select statements
|
||||||
Return statements
|
Return statements
|
||||||
@ -583,7 +582,9 @@ same identifier declared in an outer block.
|
|||||||
|
|
||||||
3. The scope of a constant or variable extends textually from
|
3. The scope of a constant or variable extends textually from
|
||||||
after the declaration to the end of the innermost surrounding
|
after the declaration to the end of the innermost surrounding
|
||||||
block.
|
block. If the variable is declared in the init statement of an
|
||||||
|
if, for, or switch statement, the innermost surrounding block
|
||||||
|
is the block associated with the respective statement.
|
||||||
|
|
||||||
4. The scope of a parameter or result identifier is the body of the
|
4. The scope of a parameter or result identifier is the body of the
|
||||||
corresponding function.
|
corresponding function.
|
||||||
@ -2369,8 +2370,7 @@ Statements control execution.
|
|||||||
Statement =
|
Statement =
|
||||||
Declaration | LabelDecl | EmptyStat |
|
Declaration | LabelDecl | EmptyStat |
|
||||||
SimpleStat | GoStat | ReturnStat | BreakStat | ContinueStat | GotoStat |
|
SimpleStat | GoStat | ReturnStat | BreakStat | ContinueStat | GotoStat |
|
||||||
FallthroughStat | Block | IfStat | SwitchStat | SelectStat | ForStat |
|
FallthroughStat | Block | IfStat | SwitchStat | SelectStat | ForStat .
|
||||||
RangeStat .
|
|
||||||
|
|
||||||
SimpleStat =
|
SimpleStat =
|
||||||
ExpressionStat | IncDecStat | Assignment | SimpleVarDecl .
|
ExpressionStat | IncDecStat | Assignment | SimpleVarDecl .
|
||||||
@ -2589,68 +2589,99 @@ If the expression is omitted, it is equivalent to "true".
|
|||||||
For statements
|
For statements
|
||||||
----
|
----
|
||||||
|
|
||||||
For statements are a combination of the "for" and "while" loops of C.
|
A for statement specifies repeated execution of a block. The iteration is
|
||||||
|
controlled by a condition, a for clause, or a range clause.
|
||||||
|
|
||||||
ForStat = "for" [ Condition | ForClause ] Block .
|
ForStat = "for" [ Condition | ForClause | RangeClause ] Block .
|
||||||
ForClause = [ InitStat ] ";" [ Condition ] ";" [ PostStat ] .
|
|
||||||
|
|
||||||
InitStat = SimpleStat .
|
|
||||||
Condition = Expression .
|
Condition = Expression .
|
||||||
PostStat = SimpleStat .
|
|
||||||
|
|
||||||
A SimpleStat is a simple statement such as an assignment, a SimpleVarDecl,
|
In its simplest form, a for statement specifies the repeated execution of
|
||||||
or an increment or decrement statement. Therefore one may declare a loop
|
a block as long as a condition evaluates to true. The condition is evaluated
|
||||||
variable in the init statement.
|
before each iteration. The type of the condition expression must be boolean.
|
||||||
|
If the condition is absent, it is equivalent to "true".
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
print(i, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
A for statement with just a condition executes until the condition becomes
|
|
||||||
false. Thus it is the same as C's while statement.
|
|
||||||
|
|
||||||
for a < b {
|
for a < b {
|
||||||
a *= 2
|
a *= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
If the condition is absent, it is equivalent to "true".
|
A for statement with a for clause is also controlled by its condition, but
|
||||||
|
additionally it may specify an init and post statement, such as an assignment,
|
||||||
|
an increment or decrement statement. The init statement may also be a (simple)
|
||||||
|
variable declaration; no variables can be declared in the post statement.
|
||||||
|
|
||||||
for {
|
ForClause = [ InitStat ] ";" [ Condition ] ";" [ PostStat ] .
|
||||||
f()
|
InitStat = SimpleStat .
|
||||||
|
PostStat = SimpleStat .
|
||||||
|
|
||||||
|
For instance, one may declare an iteration variable in the init statement:
|
||||||
|
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
f(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
If present, the init statement is executed once before commencing the iteration;
|
||||||
|
the post statement is executed after each execution of the statement block (and
|
||||||
|
only if the block was executed). The scope of any variable declared in the init
|
||||||
|
statement ends with the end of the for statement block ($Declarations and scope
|
||||||
|
rules, Rule 3).
|
||||||
|
|
||||||
Range statements
|
The init and post statement as well as the condition may be omitted; however
|
||||||
----
|
if either the init or post statement are present, the separating semicolons
|
||||||
|
must be present. If the condition is absent, it is equivalent to "true".
|
||||||
|
The following statements are equivalent:
|
||||||
|
|
||||||
Range statements are a special control structure for iterating over
|
for ; cond ; { S() } is the same as for cond { S() }
|
||||||
the contents of arrays and maps.
|
for true { S() } is the same as for { S() }
|
||||||
|
|
||||||
RangeStat = "range" IdentifierList ":=" RangeExpression Block .
|
Alternatively, a for statement may be controlled by a range clause. A
|
||||||
RangeExpression = Expression .
|
range clause specifies iteration through all entries of an array or map.
|
||||||
|
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. Iteration terminates
|
||||||
|
when all entries have been processed, or if the for statement is terminated
|
||||||
|
early, for instance by a break or return statement.
|
||||||
|
|
||||||
A range expression must evaluate to an array, map or string. The identifier list must contain
|
RangeClause = IdentifierList ( "=" | ":=" ) "range" Expression .
|
||||||
either one or two identifiers. If the range expression is a map, a single identifier is declared
|
|
||||||
to range over the keys of the map; two identifiers range over the keys and corresponding
|
|
||||||
values. For arrays and strings, the behavior is analogous for integer indices (the keys) and
|
|
||||||
array elements (the values).
|
|
||||||
|
|
||||||
a := []int(1, 2, 3);
|
The type of the right-hand expression in the range clause must be an array or
|
||||||
m := [string]map int("fo",2, "foo",3, "fooo",4)
|
map, or a pointer to an array or map. If it is a pointer, it must not be nil.
|
||||||
|
The left-hand identifier list must contain one or two identifiers denoting the
|
||||||
|
iteration variables. The first variable is set to the current array index or
|
||||||
|
map key, and the second variable, if present, is set to the corresponding
|
||||||
|
array element or map value. The types of the array index (int) and element,
|
||||||
|
or of the map key and value respectively, must be assignment-compatible to
|
||||||
|
the iteration variables.
|
||||||
|
|
||||||
range i := a {
|
The iteration variables may be declared by the range clause (":="), in which
|
||||||
f(a[i]);
|
case their scope ends at the end of the for statement block ($Declarations and
|
||||||
|
scope rules, Rule 3). In this case their types are the array index and element,
|
||||||
|
or the map key and value types, respectively.
|
||||||
|
|
||||||
|
var a [10]string;
|
||||||
|
m := map[string]int{"mon":0, "tue":1, "wed":2, "thu":3, "fri":4, "sat":5, "sun":6};
|
||||||
|
|
||||||
|
for i, s := range a {
|
||||||
|
// type of i is int
|
||||||
|
// type of s is string
|
||||||
|
// s == a[i]
|
||||||
|
g(i, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
range i, v := a {
|
var key string;
|
||||||
f(v);
|
var val interface {}; // value type of m is assignment-compatible to val
|
||||||
|
for key, value = range m {
|
||||||
|
h(key, value)
|
||||||
}
|
}
|
||||||
|
// key == last map key encountered in iteration
|
||||||
|
// val == map[key]
|
||||||
|
|
||||||
range k, v := m {
|
If map entries that have not yet been processed are deleted during iteration,
|
||||||
assert(len(k) == v);
|
they will not be processed. If map entries are inserted during iteration, the
|
||||||
}
|
behavior is implementation-dependent. Likewise, if the range expression is a
|
||||||
|
pointer variable, the behavior of assigning to that variable is implementation-
|
||||||
TODO: is this right?
|
dependent. Assigning to the iteration variables during iteration simply changes
|
||||||
|
the values of those variables for the current iteration; it does not affect any
|
||||||
|
subsequent iterations.
|
||||||
|
|
||||||
|
|
||||||
Go statements
|
Go statements
|
||||||
|
Loading…
Reference in New Issue
Block a user