Commit f57bf7a5 authored by Robert Griesemer's avatar Robert Griesemer Committed by Russ Cox

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
parent c72bce90
<!--{ <!--{
"Title": "The Go Programming Language Specification", "Title": "The Go Programming Language Specification",
"Subtitle": "Version of Oct 16, 2013", "Subtitle": "Version of Nov 13, 2013",
"Path": "/ref/spec" "Path": "/ref/spec"
}--> }-->
...@@ -1456,10 +1456,6 @@ by a value of type <code>T</code>. ...@@ -1456,10 +1456,6 @@ by a value of type <code>T</code>.
</li> </li>
</ul> </ul>
<p>
Any value may be assigned to the <a href="#Blank_identifier">blank identifier</a>.
</p>
<h2 id="Blocks">Blocks</h2> <h2 id="Blocks">Blocks</h2>
...@@ -1516,6 +1512,11 @@ No identifier may be declared twice in the same block, and ...@@ -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. no identifier may be declared in both the file and package block.
</p> </p>
<p>
The <a href="#Blank_identifier">blank identifier</a> may be used like any other identifier
in a declaration, but it does not introduce a binding and thus is not declared.
</p>
<pre class="ebnf"> <pre class="ebnf">
Declaration = ConstDecl | TypeDecl | VarDecl . Declaration = ConstDecl | TypeDecl | VarDecl .
TopLevelDecl = Declaration | FunctionDecl | MethodDecl . TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
...@@ -1585,8 +1586,10 @@ the body of any nested function. ...@@ -1585,8 +1586,10 @@ the body of any nested function.
<h3 id="Blank_identifier">Blank identifier</h3> <h3 id="Blank_identifier">Blank identifier</h3>
<p> <p>
The <i>blank identifier</i>, represented by the underscore character <code>_</code>, may be used in a declaration like The <i>blank identifier</i> is represented by the underscore character <code>_</code>.
any other identifier but the declaration does not introduce a new <a href="#Declarations_and_scope">binding</a>. It serves as an anonymous placeholder instead of a regular (non-blank)
identifier and has special meaning in <a href="#Declarations_and_scope">declarations</a>,
as an <a href="#Operands">operand</a>, and in <a href="#Assignments">assignments</a>.
</p> </p>
...@@ -2077,8 +2080,8 @@ operators and functions to operands. ...@@ -2077,8 +2080,8 @@ operators and functions to operands.
<p> <p>
Operands denote the elementary values in an expression. An operand may be a Operands denote the elementary values in an expression. An operand may be a
literal, a (possibly <a href="#Qualified_identifiers">qualified</a>) identifier literal, a (possibly <a href="#Qualified_identifiers">qualified</a>)
denoting a non-<a href="#Blank_identifier">blank</a> identifier denoting a
<a href="#Constant_declarations">constant</a>, <a href="#Constant_declarations">constant</a>,
<a href="#Variable_declarations">variable</a>, or <a href="#Variable_declarations">variable</a>, or
<a href="#Function_declarations">function</a>, <a href="#Function_declarations">function</a>,
...@@ -2086,6 +2089,11 @@ a <a href="#Method_expressions">method expression</a> yielding a function, ...@@ -2086,6 +2089,11 @@ a <a href="#Method_expressions">method expression</a> yielding a function,
or a parenthesized expression. or a parenthesized expression.
</p> </p>
<p>
The <a href="#Blank_identifier">blank identifier</a> may appear as an
operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
</p>
<pre class="ebnf"> <pre class="ebnf">
Operand = Literal | OperandName | MethodExpr | "(" Expression ")" . Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
Literal = BasicLit | CompositeLit | FunctionLit . Literal = BasicLit | CompositeLit | FunctionLit .
...@@ -4255,7 +4263,8 @@ assign_op = [ add_op | mul_op ] "=" . ...@@ -4255,7 +4263,8 @@ assign_op = [ add_op | mul_op ] "=" .
<p> <p>
Each left-hand side operand must be <a href="#Address_operators">addressable</a>, Each left-hand side operand must be <a href="#Address_operators">addressable</a>,
a map index expression, or the <a href="#Blank_identifier">blank identifier</a>. a map index expression, or (for <code>=</code> assignments only) the
<a href="#Blank_identifier">blank identifier</a>.
Operands may be parenthesized. Operands may be parenthesized.
</p> </p>
...@@ -4268,12 +4277,13 @@ a[i] = 23 ...@@ -4268,12 +4277,13 @@ a[i] = 23
<p> <p>
An <i>assignment operation</i> <code>x</code> <i>op</i><code>=</code> An <i>assignment operation</i> <code>x</code> <i>op</i><code>=</code>
<code>y</code> where <i>op</i> is a binary arithmetic operation is equivalent <code>y</code> where <i>op</i> is a binary arithmetic operation equivalent
to <code>x</code> <code>=</code> <code>x</code> <i>op</i> to <code>x</code> <code>=</code> <code>x</code> <i>op</i>
<code>y</code> but evaluates <code>x</code> <code>y</code> but evaluates <code>x</code>
only once. The <i>op</i><code>=</code> construct is a single token. only once. The <i>op</i><code>=</code> construct is a single token.
In assignment operations, both the left- and right-hand expression lists 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.
</p> </p>
<pre> <pre>
...@@ -4298,21 +4308,26 @@ x, y = f() ...@@ -4298,21 +4308,26 @@ x, y = f()
<p> <p>
assigns the first value to <code>x</code> and the second to <code>y</code>. assigns the first value to <code>x</code> and the second to <code>y</code>.
The <a href="#Blank_identifier">blank identifier</a> provides a In the second form, the number of operands on the left must equal the number
way to ignore values returned by a multi-valued expression: of expressions on the right, each of which must be single-valued, and the
<i>n</i>th expression on the right is assigned to the <i>n</i>th
operand on the left:
</p> </p>
<pre> <pre>
x, _ = f() // ignore second value returned by f() one, two, three = '一', '二', '三'
</pre> </pre>
<p> <p>
In the second form, the number of operands on the left must equal the number The <a href="#Blank_identifier">blank identifier</a> provides a way to
of expressions on the right, each of which must be single-valued, and the ignore right-hand side values in an assignment:
<i>n</i>th expression on the right is assigned to the <i>n</i>th
operand on the left.
</p> </p>
<pre>
_ = x // evaluate x but ignore it
x, _ = f() // evaluate f() but ignore second result value
</pre>
<p> <p>
The assignment proceeds in two phases. The assignment proceeds in two phases.
First, the operands of <a href="#Index_expressions">index expressions</a> First, the operands of <a href="#Index_expressions">index expressions</a>
...@@ -4350,16 +4365,29 @@ for i, x[i] = range x { // set i, x[2] = 0, x[0] ...@@ -4350,16 +4365,29 @@ for i, x[i] = range x { // set i, x[2] = 0, x[0]
</pre> </pre>
<p> <p>
In assignments, each value must be In assignments, each value must be <a href="#Assignability">assignable</a>
<a href="#Assignability">assignable</a> to the type of the to the type of the operand to which it is assigned, with the following special cases:
operand to which it is assigned. If an untyped <a href="#Constants">constant</a>
is assigned to a variable of interface type, the constant is <a href="#Conversions">converted</a>
to type <code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>,
<code>complex128</code> or <code>string</code>
respectively, depending on whether the value is a
boolean, rune, integer, floating-point, complex, or string constant.
</p> </p>
<ol>
<li><p>
If an untyped <a href="#Constants">constant</a>
is assigned to a variable of interface type or the blank identifier,
the constant is first <a href="#Conversions">converted</a> to type
<code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>,
<code>complex128</code> or <code>string</code> respectively, depending on
whether the value is a boolean, rune, integer, floating-point, complex, or
string constant.
</p></li>
<li><p>
<!-- Note that the result of a comparison is an untyped bool that may not be constant. -->
If a left-hand side is the blank identifier, any typed or non-constant
value except for the predeclared identifier
<a href="#Predeclared_identifiers"><code>nil</code></a>
may be assigned to it.
</p></li>
</ol>
<h3 id="If_statements">If statements</h3> <h3 id="If_statements">If 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