From 61af4f905bd0de1eb907da336bb48f9f48d7d2b3 Mon Sep 17 00:00:00 2001 From: Andrew Gerrand Date: Wed, 13 Nov 2013 14:40:41 +1100 Subject: [PATCH] [release-branch.go1.2] spec: clarify rules for blank identifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ««« CL 14415043 / 4daa80747394 spec: clarify rules for blank identifiers This documents the status quo more precisely. Not a language change. Fixes #6006. R=r, rsc, iant, ken CC=golang-dev https://golang.org/cl/14415043 »»» R=golang-dev CC=golang-dev https://golang.org/cl/25790043 --- doc/go_spec.html | 88 +++++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 87ee7459ff..bc9ec682a0 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -1456,10 +1456,6 @@ by a value of type T. -

-Any value may be assigned to the blank identifier. -

-

Blocks

@@ -1516,6 +1512,11 @@ No identifier may be declared twice in the same block, and no identifier may be declared in both the file and package block.

+

+The blank identifier may be used like any other identifier +in a declaration, but it does not introduce a binding and thus is not declared. +

+
 Declaration   = ConstDecl | TypeDecl | VarDecl .
 TopLevelDecl  = Declaration | FunctionDecl | MethodDecl .
@@ -1585,8 +1586,10 @@ the body of any nested function.
 

Blank identifier

-The blank identifier, represented by the underscore character _, may be used in a declaration like -any other identifier but the declaration does not introduce a new binding. +The blank identifier is represented by the underscore character _. +It serves as an anonymous placeholder instead of a regular (non-blank) +identifier and has special meaning in declarations, +as an operand, and in assignments.

@@ -2077,8 +2080,8 @@ operators and functions to operands.

Operands denote the elementary values in an expression. An operand may be a -literal, a (possibly qualified) identifier -denoting a +literal, a (possibly qualified) +non-blank identifier denoting a constant, variable, or function, @@ -2086,6 +2089,11 @@ a method expression yielding a function, or a parenthesized expression.

+

+The blank identifier may appear as an +operand only on the left-hand side of an assignment. +

+
 Operand    = Literal | OperandName | MethodExpr | "(" Expression ")" .
 Literal    = BasicLit | CompositeLit | FunctionLit .
@@ -4255,7 +4263,8 @@ assign_op = [ add_op | mul_op ] "=" .
 
 

Each left-hand side operand must be addressable, -a map index expression, or the blank identifier. +a map index expression, or (for = assignments only) the +blank identifier. Operands may be parenthesized.

@@ -4268,12 +4277,13 @@ a[i] = 23

An assignment operation x op= -y where op is a binary arithmetic operation is equivalent +y where op is a binary arithmetic operation equivalent to x = x op y but evaluates x only once. The op= construct is a single token. In assignment operations, both the left- and right-hand expression lists -must contain exactly one single-valued expression. +must contain exactly one single-valued expression, and the left-hand +expression must not be the blank identifier.

@@ -4298,21 +4308,26 @@ x, y = f()
 
 

assigns the first value to x and the second to y. -The blank identifier provides a -way to ignore values returned by a multi-valued expression: -

- -
-x, _ = f()  // ignore second value returned by f()
-
- -

In the second form, the number of operands on the left must equal the number of expressions on the right, each of which must be single-valued, and the nth expression on the right is assigned to the nth -operand on the left. +operand on the left:

+
+one, two, three = '一', '二', '三'
+
+ +

+The blank identifier provides a way to +ignore right-hand side values in an assignment: +

+ +
+_ = x       // evaluate x but ignore it
+x, _ = f()  // evaluate f() but ignore second result value
+
+

The assignment proceeds in two phases. First, the operands of index expressions @@ -4350,16 +4365,29 @@ for i, x[i] = range x { // set i, x[2] = 0, x[0]

-In assignments, each value must be -assignable to the type of the -operand to which it is assigned. If an untyped constant -is assigned to a variable of interface type, the constant is converted -to type bool, rune, int, float64, -complex128 or string -respectively, depending on whether the value is a -boolean, rune, integer, floating-point, complex, or string constant. +In assignments, each value must be assignable +to the type of the operand to which it is assigned, with the following special cases:

+
    +
  1. + If an untyped constant + is assigned to a variable of interface type or the blank identifier, + the constant is first converted to type + bool, rune, int, float64, + complex128 or string respectively, depending on + whether the value is a boolean, rune, integer, floating-point, complex, or + string constant. +

  2. + +
  3. + + If a left-hand side is the blank identifier, any typed or non-constant + value except for the predeclared identifier + nil + may be assigned to it. +

  4. +

If statements