mirror of
https://github.com/golang/go
synced 2024-11-22 06:14:39 -07:00
Test balloon: Changed the spec to see the implications of changing the
syntax of function types and making them "reference types" like slice, map, and chan. First step in Russ' proposal. DELTA=111 (32 added, 15 deleted, 64 changed) OCL=23669 CL=23964
This commit is contained in:
parent
4a43198390
commit
2b9fe0ea24
153
doc/go_spec.txt
153
doc/go_spec.txt
@ -3,7 +3,7 @@ The Go Programming Language Specification (DRAFT)
|
|||||||
|
|
||||||
Robert Griesemer, Rob Pike, Ken Thompson
|
Robert Griesemer, Rob Pike, Ken Thompson
|
||||||
|
|
||||||
(January 27, 2009)
|
(January 30, 2009)
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
@ -1215,7 +1215,7 @@ types (§Types).
|
|||||||
StructType = "struct" [ "{" [ FieldDeclList ] "}" ] .
|
StructType = "struct" [ "{" [ FieldDeclList ] "}" ] .
|
||||||
FieldDeclList = FieldDecl { ";" FieldDecl } [ ";" ] .
|
FieldDeclList = FieldDecl { ";" FieldDecl } [ ";" ] .
|
||||||
FieldDecl = (IdentifierList CompleteType | TypeName) [ Tag ] .
|
FieldDecl = (IdentifierList CompleteType | TypeName) [ Tag ] .
|
||||||
Tag = string_lit .
|
Tag = StringLit .
|
||||||
|
|
||||||
// An empty struct.
|
// An empty struct.
|
||||||
struct {}
|
struct {}
|
||||||
@ -1225,7 +1225,7 @@ types (§Types).
|
|||||||
x, y int;
|
x, y int;
|
||||||
u float;
|
u float;
|
||||||
A *[]int;
|
A *[]int;
|
||||||
F *();
|
F func();
|
||||||
}
|
}
|
||||||
|
|
||||||
A struct may contain ``anonymous fields'', which are declared with a type
|
A struct may contain ``anonymous fields'', which are declared with a type
|
||||||
@ -1326,9 +1326,10 @@ Function types
|
|||||||
----
|
----
|
||||||
|
|
||||||
A function type denotes the set of all functions with the same parameter
|
A function type denotes the set of all functions with the same parameter
|
||||||
and result types.
|
and result types, and the value "nil".
|
||||||
|
|
||||||
FunctionType = "(" [ ParameterList ] ")" [ Result ] .
|
FunctionType = "func" Signature .
|
||||||
|
Signature = "(" [ ParameterList ] ")" [ Result ] .
|
||||||
ParameterList = ParameterDecl { "," ParameterDecl } .
|
ParameterList = ParameterDecl { "," ParameterDecl } .
|
||||||
ParameterDecl = [ IdentifierList ] ( Type | "..." ) .
|
ParameterDecl = [ IdentifierList ] ( Type | "..." ) .
|
||||||
Result = Type | "(" ParameterList ")" .
|
Result = Type | "(" ParameterList ")" .
|
||||||
@ -1345,22 +1346,32 @@ no additional arguments). If the parameters are named, the identifier
|
|||||||
list immediately preceding "..." must contain only one identifier (the
|
list immediately preceding "..." must contain only one identifier (the
|
||||||
name of the last parameter).
|
name of the last parameter).
|
||||||
|
|
||||||
()
|
func ()
|
||||||
(x int)
|
func (x int)
|
||||||
() int
|
func () int
|
||||||
(string, float, ...)
|
func (string, float, ...)
|
||||||
(a, b int, z float) bool
|
func (a, b int, z float) bool
|
||||||
(a, b int, z float) (bool)
|
func (a, b int, z float) (bool)
|
||||||
(a, b int, z float, opt ...) (success bool)
|
func (a, b int, z float, opt ...) (success bool)
|
||||||
(int, int, float) (float, *[]int)
|
func (int, int, float) (float, *[]int)
|
||||||
|
|
||||||
A variable can hold only a pointer to a function, not a function value.
|
If the result type of a function is itself a function type, the result type
|
||||||
In particular, v := func() {} creates a variable of type *(). To call the
|
must be parenthesized to resolve a parsing ambiguity:
|
||||||
function referenced by v, one writes v(). It is illegal to dereference a
|
|
||||||
function pointer.
|
|
||||||
|
|
||||||
Assignment compatibility: A function pointer can be assigned to a function
|
func (n int) (func (p* T))
|
||||||
(pointer) variable only if both function types are equal.
|
|
||||||
|
Assignment compatibility: A function can be assigned to a function
|
||||||
|
variable only if both function types are equal.
|
||||||
|
|
||||||
|
Comparisons: A variable of function type can be compared against "nil" with the
|
||||||
|
operators "==" and "!=" (§Comparison operators). The variable is
|
||||||
|
"nil" only if "nil" is assigned explicitly to the variable (§Assignments), or
|
||||||
|
if the variable has not been modified since creation (§Program initialization
|
||||||
|
and execution).
|
||||||
|
|
||||||
|
Two variables of equal function type can be tested for equality with the
|
||||||
|
operators "==" and "!=" (§Comparison operators). The variables are equal
|
||||||
|
if they refer to the same function.
|
||||||
|
|
||||||
|
|
||||||
Interface types
|
Interface types
|
||||||
@ -1372,7 +1383,7 @@ the set of methods specified by the interface type, and the value "nil".
|
|||||||
|
|
||||||
InterfaceType = "interface" [ "{" [ MethodSpecList ] "}" ] .
|
InterfaceType = "interface" [ "{" [ MethodSpecList ] "}" ] .
|
||||||
MethodSpecList = MethodSpec { ";" MethodSpec } [ ";" ] .
|
MethodSpecList = MethodSpec { ";" MethodSpec } [ ";" ] .
|
||||||
MethodSpec = IdentifierList FunctionType .
|
MethodSpec = IdentifierList Signature .
|
||||||
|
|
||||||
// An interface specifying a basic File type.
|
// An interface specifying a basic File type.
|
||||||
interface {
|
interface {
|
||||||
@ -1704,8 +1715,8 @@ For instance, given the declarations
|
|||||||
T1 []string
|
T1 []string
|
||||||
T2 struct { a, b int };
|
T2 struct { a, b int };
|
||||||
T3 struct { a, c int };
|
T3 struct { a, c int };
|
||||||
T4 *(int, float) *T0
|
T4 func (int, float) *T0
|
||||||
T5 *(x int, y float) *[]string
|
T5 func (x int, y float) *[]string
|
||||||
)
|
)
|
||||||
|
|
||||||
these are some types that are equal
|
these are some types that are equal
|
||||||
@ -1759,7 +1770,8 @@ Operands denote the elementary values in an expression.
|
|||||||
|
|
||||||
Operand = Literal | QualifiedIdent | "(" Expression ")" .
|
Operand = Literal | QualifiedIdent | "(" Expression ")" .
|
||||||
Literal = BasicLit | CompositeLit | FunctionLit .
|
Literal = BasicLit | CompositeLit | FunctionLit .
|
||||||
BasicLit = int_lit | float_lit | char_lit | string_lit .
|
BasicLit = int_lit | float_lit | char_lit | StringLit .
|
||||||
|
StringLit = string_lit { string_lit } .
|
||||||
|
|
||||||
|
|
||||||
Constants
|
Constants
|
||||||
@ -1848,15 +1860,15 @@ A function literal represents an anonymous function. It consists of a
|
|||||||
specification of the function type and the function body. The parameter
|
specification of the function type and the function body. The parameter
|
||||||
and result types of the function type must all be complete types (§Types).
|
and result types of the function type must all be complete types (§Types).
|
||||||
|
|
||||||
FunctionLit = "func" FunctionType Block .
|
FunctionLit = "func" Signature Block .
|
||||||
Block = "{" [ StatementList ] "}" .
|
Block = "{" [ StatementList ] "}" .
|
||||||
|
|
||||||
The type of a function literal is a pointer to the function type.
|
The type of a function literal is the function type specified.
|
||||||
|
|
||||||
func (a, b int, z float) bool { return a*b < int(z); }
|
func (a, b int, z float) bool { return a*b < int(z); }
|
||||||
|
|
||||||
A function literal can be assigned to a variable of the
|
A function literal can be assigned to a variable of the
|
||||||
corresponding function pointer type, or invoked directly.
|
corresponding function type, or invoked directly.
|
||||||
|
|
||||||
f := func(x, y int) int { return x + y; }
|
f := func(x, y int) int { return x + y; }
|
||||||
func(ch chan int) { ch <- ACK; } (reply_chan)
|
func(ch chan int) { ch <- ACK; } (reply_chan)
|
||||||
@ -2073,7 +2085,9 @@ TODO add examples
|
|||||||
Calls
|
Calls
|
||||||
----
|
----
|
||||||
|
|
||||||
Given a function pointer, one writes
|
TODO: This needs to be expanded and cleaned up.
|
||||||
|
|
||||||
|
Given a function or a function variable p, one writes
|
||||||
|
|
||||||
p()
|
p()
|
||||||
|
|
||||||
@ -2083,7 +2097,7 @@ A method is called using the notation
|
|||||||
|
|
||||||
receiver.method()
|
receiver.method()
|
||||||
|
|
||||||
where receiver is a value of the receive type of the method.
|
where receiver is a value of the receiver type of the method.
|
||||||
|
|
||||||
For instance, given a *Point variable pt, one may call
|
For instance, given a *Point variable pt, one may call
|
||||||
|
|
||||||
@ -2357,26 +2371,11 @@ Address operators
|
|||||||
|
|
||||||
TODO: Need to talk about unary "*", clean up section below.
|
TODO: Need to talk about unary "*", clean up section below.
|
||||||
|
|
||||||
Given a function f, declared as
|
TODO: This text needs to be cleaned up and go elsewhere, there are no address
|
||||||
|
operators involved.
|
||||||
|
|
||||||
func f(a int) int;
|
Methods are a form of function, and a method ``value'' has a function type.
|
||||||
|
Consider the type T with method M:
|
||||||
taking the address of f with the expression
|
|
||||||
|
|
||||||
&f
|
|
||||||
|
|
||||||
creates a pointer to the function that may be stored in a value of type pointer
|
|
||||||
to function:
|
|
||||||
|
|
||||||
var fp *(a int) int = &f;
|
|
||||||
|
|
||||||
The function pointer may be invoked with the usual syntax; no explicit
|
|
||||||
indirection is required:
|
|
||||||
|
|
||||||
fp(7)
|
|
||||||
|
|
||||||
Methods are a form of function, and the address of a method has the type
|
|
||||||
pointer to function. Consider the type T with method M:
|
|
||||||
|
|
||||||
type T struct {
|
type T struct {
|
||||||
a int;
|
a int;
|
||||||
@ -2384,45 +2383,62 @@ pointer to function. Consider the type T with method M:
|
|||||||
func (tp *T) M(a int) int;
|
func (tp *T) M(a int) int;
|
||||||
var t *T;
|
var t *T;
|
||||||
|
|
||||||
To construct the address of method M, one writes
|
To construct the value of method M, one writes
|
||||||
|
|
||||||
&t.M
|
t.M
|
||||||
|
|
||||||
using the variable t (not the type T). The expression is a pointer to a
|
using the variable t (not the type T).
|
||||||
function, with type
|
TODO: It makes perfect sense to be able to say T.M (in fact, it makes more
|
||||||
|
sense then t.M, since only the type T is needed to find the method M, i.e.,
|
||||||
|
its address). TBD.
|
||||||
|
|
||||||
*(t *T, a int) int
|
The expression t.M is a function value with type
|
||||||
|
|
||||||
and may be invoked only as a function, not a method:
|
func (t *T, a int) int
|
||||||
|
|
||||||
var f *(t *T, a int) int;
|
and may be invoked only as a function, not as a method:
|
||||||
f = &t.M;
|
|
||||||
|
var f func (t *T, a int) int;
|
||||||
|
f = t.M;
|
||||||
x := f(t, 7);
|
x := f(t, 7);
|
||||||
|
|
||||||
Note that one does not write t.f(7); taking the address of a method demotes
|
Note that one does not write t.f(7); taking the value of a method demotes
|
||||||
it to a function.
|
it to a function.
|
||||||
|
|
||||||
In general, given type T with method M and variable t of type *T,
|
In general, given type T with method M and variable t of type T,
|
||||||
the method invocation
|
the method invocation
|
||||||
|
|
||||||
t.M(args)
|
t.M(args)
|
||||||
|
|
||||||
is equivalent to the function call
|
is equivalent to the function call
|
||||||
|
|
||||||
(&t.M)(t, args)
|
(t.M)(t, args)
|
||||||
|
|
||||||
If T is an interface type, the expression &t.M does not determine which
|
TODO: should probably describe the effect of (t.m) under §Expressions if t.m
|
||||||
|
denotes a method: Effect is as described above, converts into function.
|
||||||
|
|
||||||
|
If T is an interface type, the expression t.M does not determine which
|
||||||
underlying type's M is called until the point of the call itself. Thus given
|
underlying type's M is called until the point of the call itself. Thus given
|
||||||
T1 and T2, both implementing interface I with interface M, the sequence
|
T1 and T2, both implementing interface I with interface M, the sequence
|
||||||
|
|
||||||
var t1 *T1;
|
var t1 *T1;
|
||||||
var t2 *T2;
|
var t2 *T2;
|
||||||
var i I = t1;
|
var i I = t1;
|
||||||
m := &i.M;
|
m := i.M;
|
||||||
m(t2);
|
m(t2, 7);
|
||||||
|
|
||||||
will invoke t2.M() even though m was constructed with an expression involving
|
will invoke t2.M() even though m was constructed with an expression involving
|
||||||
t1.
|
t1. Effectively, the value of m is a function literal
|
||||||
|
|
||||||
|
func (recv I, a int) {
|
||||||
|
recv.M(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
that is automatically created.
|
||||||
|
|
||||||
|
TODO: Document implementation restriction: It is illegal to take the address
|
||||||
|
of a result parameter (e.g.: func f() (x int, p *int) { return 2, &x }).
|
||||||
|
(TBD: is it an implementation restriction or fact?)
|
||||||
|
|
||||||
|
|
||||||
Communication operators
|
Communication operators
|
||||||
@ -2643,7 +2659,7 @@ and the "else" branch. If Expression evaluates to true,
|
|||||||
the "if" branch is executed. Otherwise the "else" branch is executed if present.
|
the "if" branch is executed. Otherwise the "else" branch is executed if present.
|
||||||
If Condition is omitted, it is equivalent to true.
|
If Condition is omitted, it is equivalent to true.
|
||||||
|
|
||||||
IfStat = "if" [ [ Simplestat ] ";" ] [ Expression ] Block [ "else" Statement ] .
|
IfStat = "if" [ [ SimpleStat ] ";" ] [ Expression ] Block [ "else" Statement ] .
|
||||||
|
|
||||||
if x > 0 {
|
if x > 0 {
|
||||||
return true;
|
return true;
|
||||||
@ -2666,7 +2682,7 @@ the variable is initialized once before the statement is entered.
|
|||||||
TODO: gri thinks that Statement needs to be changed as follows:
|
TODO: gri thinks that Statement needs to be changed as follows:
|
||||||
|
|
||||||
IfStat =
|
IfStat =
|
||||||
"if" [ [ Simplestat ] ";" ] [ Expression ] Block
|
"if" [ [ SimpleStat ] ";" ] [ Expression ] Block
|
||||||
[ "else" ( IfStat | Block ) ] .
|
[ "else" ( IfStat | Block ) ] .
|
||||||
|
|
||||||
To facilitate the "if else if" code pattern, if the "else" branch is
|
To facilitate the "if else if" code pattern, if the "else" branch is
|
||||||
@ -2688,7 +2704,7 @@ Switch statements
|
|||||||
|
|
||||||
Switches provide multi-way execution.
|
Switches provide multi-way execution.
|
||||||
|
|
||||||
SwitchStat = "switch" [ [ Simplestat ] ";" ] [ Expression ] "{" { CaseClause } "}" .
|
SwitchStat = "switch" [ [ SimpleStat ] ";" ] [ Expression ] "{" { CaseClause } "}" .
|
||||||
CaseClause = SwitchCase ":" [ StatementList ] .
|
CaseClause = SwitchCase ":" [ StatementList ] .
|
||||||
SwitchCase = "case" ExpressionList | "default" .
|
SwitchCase = "case" ExpressionList | "default" .
|
||||||
|
|
||||||
@ -3069,9 +3085,9 @@ Function declarations
|
|||||||
A function declaration binds an identifier to a function.
|
A function declaration binds an identifier to a function.
|
||||||
Functions contain declarations and statements. They may be
|
Functions contain declarations and statements. They may be
|
||||||
recursive. Except for forward declarations (see below), the parameter
|
recursive. Except for forward declarations (see below), the parameter
|
||||||
and result types of the function type must all be complete types (§Type declarations).
|
and result types of the signature must all be complete types (§Type declarations).
|
||||||
|
|
||||||
FunctionDecl = "func" identifier FunctionType [ Block ] .
|
FunctionDecl = "func" identifier Signature [ Block ] .
|
||||||
|
|
||||||
func min(x int, y int) int {
|
func min(x int, y int) int {
|
||||||
if x < y {
|
if x < y {
|
||||||
@ -3102,7 +3118,7 @@ it is declared within the scope of that type (§Type declarations). If the
|
|||||||
receiver value is not needed inside the method, its identifier may be omitted
|
receiver value is not needed inside the method, its identifier may be omitted
|
||||||
in the declaration.
|
in the declaration.
|
||||||
|
|
||||||
MethodDecl = "func" Receiver identifier FunctionType [ Block ] .
|
MethodDecl = "func" Receiver identifier Signature [ Block ] .
|
||||||
Receiver = "(" [ identifier ] [ "*" ] TypeName ")" .
|
Receiver = "(" [ identifier ] [ "*" ] TypeName ")" .
|
||||||
|
|
||||||
All methods bound to a receiver base type must have the same receiver type:
|
All methods bound to a receiver base type must have the same receiver type:
|
||||||
@ -3296,6 +3312,7 @@ through an import declaration:
|
|||||||
ImportDecl = "import" ( ImportSpec | "(" [ ImportSpecList ] ")" ) .
|
ImportDecl = "import" ( ImportSpec | "(" [ ImportSpecList ] ")" ) .
|
||||||
ImportSpecList = ImportSpec { ";" ImportSpec } [ ";" ] .
|
ImportSpecList = ImportSpec { ";" ImportSpec } [ ";" ] .
|
||||||
ImportSpec = [ "." | PackageName ] PackageFileName .
|
ImportSpec = [ "." | PackageName ] PackageFileName .
|
||||||
|
PackageFileName = StringLit .
|
||||||
|
|
||||||
An import statement makes the exported top-level identifiers of the named
|
An import statement makes the exported top-level identifiers of the named
|
||||||
package file accessible to this package.
|
package file accessible to this package.
|
||||||
|
Loading…
Reference in New Issue
Block a user