mirror of
https://github.com/golang/go
synced 2024-11-22 03:44:39 -07:00
- explained function and method pointers
- removed need for method types and literals (gri & r) R=r DELTA=178 (101 added, 51 deleted, 26 changed) OCL=14402 CL=14405
This commit is contained in:
parent
c2c49bec77
commit
2dabb6525a
190
doc/go_lang.txt
190
doc/go_lang.txt
@ -4,7 +4,7 @@ The Go Programming Language (DRAFT)
|
||||
Robert Griesemer, Rob Pike, Ken Thompson
|
||||
|
||||
----
|
||||
(August 20, 2008)
|
||||
(August 21, 2008)
|
||||
|
||||
This document is a semi-formal specification/proposal for a new
|
||||
systems programming language. The document is under active
|
||||
@ -791,16 +791,10 @@ Function types
|
||||
|
||||
A function type denotes the set of all functions with the same signature.
|
||||
|
||||
A method is a function with a receiver declaration.
|
||||
[OLD
|
||||
, which is of type pointer to struct.
|
||||
END]
|
||||
|
||||
Functions can return multiple values simultaneously.
|
||||
|
||||
FunctionType = "func" AnonymousSignature .
|
||||
AnonymousSignature = [ Receiver "." ] Parameters [ Result ] .
|
||||
Receiver = "(" identifier Type ")" .
|
||||
FunctionType = "func" Signature .
|
||||
Signature = Parameters [ Result ] .
|
||||
Parameters = "(" [ ParameterList ] ")" .
|
||||
ParameterList = ParameterSection { "," ParameterSection } .
|
||||
ParameterSection = IdentifierList Type .
|
||||
@ -812,12 +806,6 @@ Functions can return multiple values simultaneously.
|
||||
func (a, b int, z float) (success bool)
|
||||
func (a, b int, z float) (success bool, result float)
|
||||
|
||||
// Method types
|
||||
func (p *T) . ()
|
||||
func (p *T) . (a, b int, z float) bool
|
||||
func (p *T) . (a, b int, z float) (success bool)
|
||||
func (p *T) . (a, b int, z float) (success bool, result float)
|
||||
|
||||
A variable can hold only a pointer to a function, not a function value.
|
||||
In particular, v := func() {} creates a variable of type *func(). To call the
|
||||
function referenced by v, one writes v(). It is illegal to dereference a
|
||||
@ -843,45 +831,13 @@ variables, and variables declared within the function literal.
|
||||
// Function literal
|
||||
func (a, b int, z float) bool { return a*b < int(z); }
|
||||
|
||||
// Method literal
|
||||
func (p *T) . (a, b int, z float) bool { return a*b < int(z) + p.x; }
|
||||
|
||||
Unresolved issues: Are there method literals? How do you use them?
|
||||
|
||||
|
||||
Methods
|
||||
----
|
||||
|
||||
A method is a function bound to a particular type T, where T is the
|
||||
type of the receiver. For instance, given type Point
|
||||
|
||||
type Point struct { x, y float }
|
||||
|
||||
the declaration
|
||||
|
||||
func (p *Point) distance(scale float) float {
|
||||
return scale * (p.x*p.x + p.y*p.y);
|
||||
}
|
||||
|
||||
creates a method of type *Point. Note that methods may appear anywhere
|
||||
after the declaration of the receiver type and may be forward-declared.
|
||||
|
||||
When invoked, a method behaves like a function whose first argument
|
||||
is the receiver, but at the call site the receiver is bound to the method
|
||||
using the notation
|
||||
|
||||
receiver.method()
|
||||
|
||||
For instance, given a *Point variable pt, one may call
|
||||
|
||||
pt.distance(3.5)
|
||||
|
||||
|
||||
Interface of a type
|
||||
----
|
||||
|
||||
The interface of a type is defined to be the unordered set of methods
|
||||
associated with that type.
|
||||
associated with that type. Methods are defined in a later section;
|
||||
they are functions bound to a type.
|
||||
|
||||
|
||||
Interface types
|
||||
@ -891,7 +847,7 @@ An interface type denotes a set of methods.
|
||||
|
||||
InterfaceType = "interface" "{" [ MethodDeclList [ ";" ] ] "}" .
|
||||
MethodDeclList = MethodDecl { ";" MethodDecl } .
|
||||
MethodDecl = identifier Parameters [ Result ] .
|
||||
MethodDecl = identifier Signature .
|
||||
|
||||
// A basic file interface.
|
||||
type File interface {
|
||||
@ -1021,7 +977,7 @@ and "true", are predeclared. A declaration associates an identifier
|
||||
with a language entity (package, constant, type, variable, function, method,
|
||||
or label) and may specify properties of that entity such as its type.
|
||||
|
||||
Declaration = [ "export" ] ( ConstDecl | TypeDecl | VarDecl | FunctionDecl ) .
|
||||
Declaration = [ "export" ] ( ConstDecl | TypeDecl | VarDecl | FunctionDecl | MethodDecl ) .
|
||||
|
||||
The ``scope'' of a language entity named 'x' extends textually from the point
|
||||
immediately after the identifier 'x' in the declaration to the end of the
|
||||
@ -1219,18 +1175,12 @@ Also, in some contexts such as "if", "for", or "switch" statements,
|
||||
this construct can be used to declare local temporary variables.
|
||||
|
||||
|
||||
Function and method declarations
|
||||
Function declarations
|
||||
----
|
||||
|
||||
Functions and methods have a special declaration syntax, slightly
|
||||
different from the type syntax because an identifier must be present
|
||||
in the signature.
|
||||
A function declaration declares an identifier of type function.
|
||||
|
||||
Implementation restriction: Functions and methods can only be declared
|
||||
at the global level.
|
||||
|
||||
FunctionDecl = "func" NamedSignature ( ";" | Block ) .
|
||||
NamedSignature = [ Receiver ] identifier Parameters [ Result ] .
|
||||
FunctionDecl = "func" identifier Signature ( ";" | Block ) .
|
||||
|
||||
func min(x int, y int) int {
|
||||
if x < y {
|
||||
@ -1239,16 +1189,24 @@ at the global level.
|
||||
return y;
|
||||
}
|
||||
|
||||
func foo(a, b int, z float) bool {
|
||||
return a*b < int(z);
|
||||
}
|
||||
A function declaration without a body serves as a forward declaration:
|
||||
|
||||
func MakeNode(left, right *Node) *Node;
|
||||
|
||||
|
||||
A method is a function that also declares a receiver.
|
||||
Implementation restriction: Functions can only be declared at the global level.
|
||||
|
||||
func (p *T) foo(a, b int, z float) bool {
|
||||
return a*b < int(z) + p.x;
|
||||
}
|
||||
|
||||
Method declarations
|
||||
----
|
||||
|
||||
A method declaration declares a function with a receiver.
|
||||
|
||||
MethodDecl = "func" Receiver identifier Signature ( ";" | Block ) .
|
||||
Receiver = "(" identifier Type ")" .
|
||||
|
||||
A method is bound to the type of its receiver.
|
||||
For instance, given type Point, the declarations
|
||||
|
||||
func (p *Point) Length() float {
|
||||
return Math.sqrt(p.x * p.x + p.y * p.y);
|
||||
@ -1259,10 +1217,31 @@ A method is a function that also declares a receiver.
|
||||
p.y = p.y * factor;
|
||||
}
|
||||
|
||||
Functions and methods can be forward declared by omitting the body:
|
||||
create methods for type *Point. Note that methods may appear anywhere
|
||||
after the declaration of the receiver type and may be forward-declared.
|
||||
|
||||
func foo(a, b int, z float) bool;
|
||||
func (p *T) foo(a, b int, z float) bool;
|
||||
|
||||
Method invocation
|
||||
----
|
||||
|
||||
A method is invoked using the notation
|
||||
|
||||
receiver.method()
|
||||
|
||||
where receiver is a value of the receive type of the method.
|
||||
|
||||
For instance, given a *Point variable pt, one may call
|
||||
|
||||
pt.Scale(3.5)
|
||||
|
||||
The type of a method is the type of a function with the receiver as first
|
||||
argument. For instance, the method "Scale" has type
|
||||
|
||||
func(p *Point, factor float)
|
||||
|
||||
However, a function declared this way is not a method.
|
||||
|
||||
There is no distinct method type and there are no method literals.
|
||||
|
||||
|
||||
Initial values
|
||||
@ -1418,6 +1397,7 @@ Examples of primary expressions
|
||||
obj.color
|
||||
Math.sin
|
||||
f.p[i].x()
|
||||
&point.distance
|
||||
|
||||
Examples of general expressions
|
||||
|
||||
@ -1462,6 +1442,76 @@ TODO: if interfaces were explicitly pointers, this gets simpler.
|
||||
END]
|
||||
|
||||
|
||||
Function and method pointers
|
||||
----
|
||||
|
||||
Given a function f, declared as
|
||||
|
||||
func f(a int) int;
|
||||
|
||||
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 *func(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 {
|
||||
a int;
|
||||
}
|
||||
func (tp *T) M(a int) int;
|
||||
var t *T;
|
||||
|
||||
To construct the address of method M, we write
|
||||
|
||||
&t.M
|
||||
|
||||
using the variable t (not the type T). The expression is a pointer to a
|
||||
function, with type
|
||||
|
||||
*func(t *T, a int) int
|
||||
|
||||
and may be invoked only as a function, not a method:
|
||||
|
||||
var f *func(t *T, a int) int;
|
||||
f = &t.M;
|
||||
x := f(t, 7);
|
||||
|
||||
Note that one does not write t.f(7); taking the address of a method demotes
|
||||
it to a function.
|
||||
|
||||
In general, given type T with method M and variable t of type *T,
|
||||
the method invocation
|
||||
|
||||
t.M(args)
|
||||
|
||||
is equivalent to the function call
|
||||
|
||||
(&t.M)(t, args)
|
||||
|
||||
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
|
||||
T1 and T2, both implementing interface I with interface M, the sequence
|
||||
|
||||
var t1 *T1;
|
||||
var t2 *T2;
|
||||
var i I = t1;
|
||||
m := &i.M;
|
||||
m(t2);
|
||||
|
||||
will invoke t2.M() even though m was constructed with an expression involving
|
||||
t1.
|
||||
|
||||
Allocation
|
||||
----
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user