Commit 2dabb652 authored by Robert Griesemer's avatar Robert Griesemer

- 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
parent c2c49bec
...@@ -4,7 +4,7 @@ The Go Programming Language (DRAFT) ...@@ -4,7 +4,7 @@ The Go Programming Language (DRAFT)
Robert Griesemer, Rob Pike, Ken Thompson Robert Griesemer, Rob Pike, Ken Thompson
---- ----
(August 20, 2008) (August 21, 2008)
This document is a semi-formal specification/proposal for a new This document is a semi-formal specification/proposal for a new
systems programming language. The document is under active systems programming language. The document is under active
...@@ -791,16 +791,10 @@ Function types ...@@ -791,16 +791,10 @@ Function types
A function type denotes the set of all functions with the same signature. 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. Functions can return multiple values simultaneously.
FunctionType = "func" AnonymousSignature . FunctionType = "func" Signature .
AnonymousSignature = [ Receiver "." ] Parameters [ Result ] . Signature = Parameters [ Result ] .
Receiver = "(" identifier Type ")" .
Parameters = "(" [ ParameterList ] ")" . Parameters = "(" [ ParameterList ] ")" .
ParameterList = ParameterSection { "," ParameterSection } . ParameterList = ParameterSection { "," ParameterSection } .
ParameterSection = IdentifierList Type . ParameterSection = IdentifierList Type .
...@@ -812,12 +806,6 @@ Functions can return multiple values simultaneously. ...@@ -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)
func (a, b int, z float) (success bool, result float) 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. 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 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 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. ...@@ -843,45 +831,13 @@ variables, and variables declared within the function literal.
// Function literal // Function literal
func (a, b int, z float) bool { return a*b < int(z); } 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 Interface of a type
---- ----
The interface of a type is defined to be the unordered set of methods 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 Interface types
...@@ -891,7 +847,7 @@ An interface type denotes a set of methods. ...@@ -891,7 +847,7 @@ An interface type denotes a set of methods.
InterfaceType = "interface" "{" [ MethodDeclList [ ";" ] ] "}" . InterfaceType = "interface" "{" [ MethodDeclList [ ";" ] ] "}" .
MethodDeclList = MethodDecl { ";" MethodDecl } . MethodDeclList = MethodDecl { ";" MethodDecl } .
MethodDecl = identifier Parameters [ Result ] . MethodDecl = identifier Signature .
// A basic file interface. // A basic file interface.
type File interface { type File interface {
...@@ -1021,7 +977,7 @@ and "true", are predeclared. A declaration associates an identifier ...@@ -1021,7 +977,7 @@ and "true", are predeclared. A declaration associates an identifier
with a language entity (package, constant, type, variable, function, method, with a language entity (package, constant, type, variable, function, method,
or label) and may specify properties of that entity such as its type. 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 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 immediately after the identifier 'x' in the declaration to the end of the
...@@ -1219,36 +1175,38 @@ Also, in some contexts such as "if", "for", or "switch" statements, ...@@ -1219,36 +1175,38 @@ Also, in some contexts such as "if", "for", or "switch" statements,
this construct can be used to declare local temporary variables. 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 A function declaration declares an identifier of type function.
different from the type syntax because an identifier must be present
in the signature.
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 { func min(x int, y int) int {
if x < y { if x < y {
return x; return x;
} }
return y; return y;
} }
A function declaration without a body serves as a forward declaration:
func foo(a, b int, z float) bool { func MakeNode(left, right *Node) *Node;
return a*b < int(z);
}
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 { func (p *Point) Length() float {
return Math.sqrt(p.x * p.x + p.y * p.y); 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. ...@@ -1259,10 +1217,31 @@ A method is a function that also declares a receiver.
p.y = p.y * factor; 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; Method invocation
func (p *T) foo(a, b int, z float) bool; ----
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 Initial values
...@@ -1418,6 +1397,7 @@ Examples of primary expressions ...@@ -1418,6 +1397,7 @@ Examples of primary expressions
obj.color obj.color
Math.sin Math.sin
f.p[i].x() f.p[i].x()
&point.distance
Examples of general expressions Examples of general expressions
...@@ -1462,6 +1442,76 @@ TODO: if interfaces were explicitly pointers, this gets simpler. ...@@ -1462,6 +1442,76 @@ TODO: if interfaces were explicitly pointers, this gets simpler.
END] 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 Allocation
---- ----
......
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