1
0
mirror of https://github.com/golang/go synced 2024-11-25 01:57:56 -07:00

Revised proposal for const/var cleanup, with

Ken's suggestion for the "iota" extension to tuples.

DELTA=171  (88 added, 57 deleted, 26 changed)
OCL=20460
CL=20544
This commit is contained in:
Robert Griesemer 2008-12-04 17:33:37 -08:00
parent a0a14b98fa
commit 7354b864b5

View File

@ -4,7 +4,7 @@ The Go Programming Language Specification (DRAFT)
Robert Griesemer, Rob Pike, Ken Thompson Robert Griesemer, Rob Pike, Ken Thompson
---- ----
(November 17, 2008) (December 4, 2008)
This document is a semi-formal specification of the Go systems This document is a semi-formal specification of the Go systems
@ -85,9 +85,6 @@ Open issues:
with nil with nil
[ ] consider syntactic notation for composite literals to make them parseable w/o type information [ ] consider syntactic notation for composite literals to make them parseable w/o type information
(require ()'s in control clauses) (require ()'s in control clauses)
[ ] global var decls: "var a, b, c int = 0, 0, 0" is ok, but "var a, b, c = 0, 0, 0" is not
(seems inconsistent with "var a = 0", and ":=" notation)
[ ] const decls: "const a, b = 1, 2" is not allowed - why not? Should be symmetric to vars.
Decisions in need of integration into the doc: Decisions in need of integration into the doc:
@ -98,6 +95,9 @@ Decisions in need of integration into the doc:
Closed: Closed:
[x] global var decls: "var a, b, c int = 0, 0, 0" is ok, but "var a, b, c = 0, 0, 0" is not
(seems inconsistent with "var a = 0", and ":=" notation)
[x] const decls: "const a, b = 1, 2" is not allowed - why not? Should be symmetric to vars.
[x] new(arraytype, n1, n2): spec only talks about length, not capacity [x] new(arraytype, n1, n2): spec only talks about length, not capacity
(should only use new(arraytype, n) - this will allow later (should only use new(arraytype, n) - this will allow later
extension to multi-dim arrays w/o breaking the language) - documented extension to multi-dim arrays w/o breaking the language) - documented
@ -146,6 +146,7 @@ Contents
Predeclared identifiers Predeclared identifiers
Exported declarations Exported declarations
Const declarations Const declarations
Iota
Type declarations Type declarations
Variable declarations Variable declarations
Export declarations Export declarations
@ -168,7 +169,6 @@ Contents
Operands Operands
Constants Constants
Qualified identifiers Qualified identifiers
Iota
Composite Literals Composite Literals
Function Literals Function Literals
@ -275,7 +275,6 @@ but is usually defined close to its first use. Productions and code
examples are indented. examples are indented.
Source code representation Source code representation
---- ----
@ -661,22 +660,40 @@ A constant declaration binds an identifier to the value of a constant
expression (§Constant expressions). expression (§Constant expressions).
ConstDecl = "const" Decl<ConstSpec> . ConstDecl = "const" Decl<ConstSpec> .
ConstSpec = identifier [ CompleteType ] [ "=" Expression ] . ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] .
const pi float = 3.14159265 IdentifierList = identifier { "," identifier } .
ExpressionList = Expression { "," Expression } .
A constant declaration binds a list of identifiers (the names of the constants)
to the values of a list of constant expressions. The number of identifiers must
be equal to the number of expressions, with the i'th identifier on the left
corresponding to the i'th expression on the right. If CompleteType is omitted,
the types of the constants are the types of the corresponding expressions;
different expressions may have different types. If CompleteType is present,
the type of all constants is the type specified, and the types of all
expressions in ExpressionList must be assignment-compatible with the
constant type.
const pi float64 = 3.14159265358979323846
const e = 2.718281828 const e = 2.718281828
const ( const (
one int = 1; size int64 = 1024;
two = 3 eof = -1;
) )
const a, b, c = 3, 4, "foo" // a = 3, b = 4, c = "foo"
const u, v float = 0, 3 // u = 0.0, v = 3.0
The constant expression may be omitted, in which case the expression is As a special case, within a parenthesized "const" declaration list the
the last expression used after the reserved word "const". If no such expression ExpressionList may be omitted from any but the first declaration. Such an empty
exists, the constant expression cannot be omitted. ExpressionList is equivalent to the textual substitution of the first preceding
non-empty ExpressionList in the same "const" declaration list.
That is, omitting the list of expressions is equivalent to repeating the
previous list. The number of identifiers must be equal to the number of
expressions in the previous list.
Together with the "iota" constant generator (§Iota), Together with the "iota" constant generator implicit repetition of
implicit repetition permits light-weight declaration of enumerated ExpressionLists permit light-weight declaration of enumerated values (§Iota):
values:
const ( const (
Sunday = iota; Sunday = iota;
@ -688,12 +705,6 @@ values:
Partyday; Partyday;
) )
The initializing expression of a constant may contain only other
constants. This is illegal:
var i int = 10;
const c = i; // error
The initializing expression for a numeric constant is evaluated The initializing expression for a numeric constant is evaluated
using the principles described in the section on numeric literals: using the principles described in the section on numeric literals:
constants are mathematical values given a size only upon assignment constants are mathematical values given a size only upon assignment
@ -702,7 +713,7 @@ may require precision significantly larger than any concrete type
in the language. Thus the following is legal: in the language. Thus the following is legal:
const Huge = 1 << 100; const Huge = 1 << 100;
var Four int8 = Huge >> 98; const Four int8 = Huge >> 98;
A given numeric constant expression is, however, defined to be A given numeric constant expression is, however, defined to be
either an integer or a floating point value, depending on the syntax either an integer or a floating point value, depending on the syntax
@ -717,18 +728,82 @@ yields a floating point constant of value 2.5 (1.5 + 1); its
constituent expressions are evaluated using different rules for constituent expressions are evaluated using different rules for
division. division.
If the type is specified, the resulting constant has the named type. If the type is missing from a numeric constant declaration, the constant
If the type is missing from the constant declaration, the constant
represents a value of abitrary precision, either integer or floating represents a value of abitrary precision, either integer or floating
point, determined by the type of the initializing expression. Such point, determined by the type of the initializing expression. Such
a constant may be assigned to any variable that can represent its a constant may be assigned to any variable that can represent its
value accurately, regardless of type. For instance, 3 can be value accurately, regardless of type. For instance, 3 can be
assigned to any int variable but also to any floating point variable, assigned to any integer variable but also to any floating point variable,
while 1e12 can be assigned to a float32, float64, or even int64. while 1e12 can be assigned to a "float32", "float64", or even "int64".
It is erroneous to assign a value with a non-zero fractional It is erroneous to assign a value with a non-zero fractional part
part to an integer, or if the assignment would overflow or to an integer, or if the assignment would overflow or underflow.
underflow.
Iota
----
Within a constant declaration, the predeclared operand "iota" represents
successive elements of an integer sequence. It is reset to 0 whenever the
reserved word "const" appears in the source and increments with each
semicolon. For instance, "iota" can be used to construct a set of related
constants:
const ( // iota is set to 0
enum0 = iota; // sets enum0 to 0, etc.
enum1 = iota;
enum2 = iota
)
const (
a = 1 << iota; // a == 1 (iota has been reset)
b = 1 << iota; // b == 2
c = 1 << iota; // c == 4
)
const (
u = iota * 42; // u == 0 (ideal integer)
v float = iota * 42; // v == 42.0 (float)
w = iota * 42; // w == 84 (ideal integer)
)
const x = iota; // x == 0 (iota has been reset)
const y = iota; // y == 0 (iota has been reset)
Within an ExpressionList, the value of all "iota"'s is the same because "iota"
is only incremented at each semicolon:
const (
base0, mask0 int64 = 1 << iota, i << iota - 1; // base0 == 1, mask0 = 0
base1, mask1 int64 = 1 << iota, i << iota - 1; // base1 == 2, mask1 = 1
base2, mask2 int64 = 1 << iota, i << iota - 1; // base2 == 4, mask2 = 3
)
Since the ExpressionList in constant declarations repeats implicitly
if omitted, some of the examples above can be abbreviated:
const (
enum0 = iota;
enum1;
enum2
)
const (
a = 1 << iota;
b;
c;
)
const (
u = iota * 42;
v float;
w;
)
const (
base0, mask0 int64 = 1 << iota, i << iota - 1;
base1, mask1 int64;
base2, mask2 int64;
)
Type declarations Type declarations
@ -774,16 +849,13 @@ of the variable.
VarDecl = "var" Decl<VarSpec> . VarDecl = "var" Decl<VarSpec> .
VarSpec = IdentifierList ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) . VarSpec = IdentifierList ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) .
IdentifierList = identifier { "," identifier } .
ExpressionList = Expression { "," Expression } .
var i int var i int
var u, v, w float var u, v, w float
var k = 0 var k = 0
var x, y float = -1.0, -2.0 var x, y float = -1.0, -2.0
var ( var (
i int; i int;
u, v = 2.0, 3.0 u, v, s = 2.0, 3.0, "bar"
) )
If the expression list is present, it must have the same number of elements If the expression list is present, it must have the same number of elements
@ -803,13 +875,13 @@ of the variable is "int" or "float" respectively:
The syntax The syntax
SimpleVarDecl = identifier ":=" Expression . SimpleVarDecl = IdentifierList ":=" ExpressionList .
is shorthand for is shorthand for
var identifier = Expression. "var" ExpressionList = ExpressionList .
i := 0 i, j := 0, 10;
f := func() int { return 7; } f := func() int { return 7; }
ch := new(chan int); ch := new(chan int);
@ -1557,47 +1629,6 @@ TODO(gri) expand this section.
PackageName = identifier . PackageName = identifier .
Iota
----
Within a declaration, the predeclared operand "iota"
represents successive elements of an integer sequence.
It is reset to zero whenever the reserved word "const"
introduces a new declaration and increments as each identifier
is declared. For instance, "iota" can be used to construct
a set of related constants:
const (
enum0 = iota; // sets enum0 to 0, etc.
enum1 = iota;
enum2 = iota
)
const (
a = 1 << iota; // sets a to 1 (iota has been reset)
b = 1 << iota; // sets b to 2
c = 1 << iota; // sets c to 4
)
const x = iota; // sets x to 0
const y = iota; // sets y to 0
Since the expression in constant declarations repeats implicitly
if omitted, the first two examples above can be abbreviated:
const (
enum0 = iota; // sets enum0 to 0, etc.
enum1;
enum2
)
const (
a = 1 << iota; // sets a to 1 (iota has been reset)
b; // sets b to 2
c; // sets c to 4
)
Composite Literals Composite Literals
---- ----