From f852034eb0e3f1397d5510b900d8c8dbf8b18746 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 28 Aug 2014 08:53:25 -0700 Subject: [PATCH] spec: move Method expr/value section near selectors Preparation for fixing issue 5769 (method selectors do not auto-dereference): The actual fix may require some cleanups in all these sections, and syntactically, method expressions and method values are selector expressions. Moving them next to each other so that it's easy to see the actual changes (next CL). No content changes besides the section moves. LGTM=iant, rsc R=r, rsc, iant, ken CC=golang-codereviews https://golang.org/cl/132300043 --- doc/go_spec.html | 455 ++++++++++++++++++++++++----------------------- 1 file changed, 228 insertions(+), 227 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index a32fa457c9..a5edc8646c 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -2537,6 +2537,233 @@ p.M0() // ((*p).T0).M0() +

Method expressions

+ +

+If M is in the method set of type T, +T.M is a function that is callable as a regular function +with the same arguments as M prefixed by an additional +argument that is the receiver of the method. +

+ +
+MethodExpr    = ReceiverType "." MethodName .
+ReceiverType  = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
+
+ +

+Consider a struct type T with two methods, +Mv, whose receiver is of type T, and +Mp, whose receiver is of type *T. +

+ +
+type T struct {
+	a int
+}
+func (tv  T) Mv(a int) int         { return 0 }  // value receiver
+func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver
+
+var t T
+
+ +

+The expression +

+ +
+T.Mv
+
+ +

+yields a function equivalent to Mv but +with an explicit receiver as its first argument; it has signature +

+ +
+func(tv T, a int) int
+
+ +

+That function may be called normally with an explicit receiver, so +these five invocations are equivalent: +

+ +
+t.Mv(7)
+T.Mv(t, 7)
+(T).Mv(t, 7)
+f1 := T.Mv; f1(t, 7)
+f2 := (T).Mv; f2(t, 7)
+
+ +

+Similarly, the expression +

+ +
+(*T).Mp
+
+ +

+yields a function value representing Mp with signature +

+ +
+func(tp *T, f float32) float32
+
+ +

+For a method with a value receiver, one can derive a function +with an explicit pointer receiver, so +

+ +
+(*T).Mv
+
+ +

+yields a function value representing Mv with signature +

+ +
+func(tv *T, a int) int
+
+ +

+Such a function indirects through the receiver to create a value +to pass as the receiver to the underlying method; +the method does not overwrite the value whose address is passed in +the function call. +

+ +

+The final case, a value-receiver function for a pointer-receiver method, +is illegal because pointer-receiver methods are not in the method set +of the value type. +

+ +

+Function values derived from methods are called with function call syntax; +the receiver is provided as the first argument to the call. +That is, given f := T.Mv, f is invoked +as f(t, 7) not t.f(7). +To construct a function that binds the receiver, use a +function literal or +method value. +

+ +

+It is legal to derive a function value from a method of an interface type. +The resulting function takes an explicit receiver of that interface type. +

+ +

Method values

+ +

+If the expression x has static type T and +M is in the method set of type T, +x.M is called a method value. +The method value x.M is a function value that is callable +with the same arguments as a method call of x.M. +The expression x is evaluated and saved during the evaluation of the +method value; the saved copy is then used as the receiver in any calls, +which may be executed later. +

+ +

+The type T may be an interface or non-interface type. +

+ +

+As in the discussion of method expressions above, +consider a struct type T with two methods, +Mv, whose receiver is of type T, and +Mp, whose receiver is of type *T. +

+ +
+type T struct {
+	a int
+}
+func (tv  T) Mv(a int) int         { return 0 }  // value receiver
+func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver
+
+var t T
+var pt *T
+func makeT() T
+
+ +

+The expression +

+ +
+t.Mv
+
+ +

+yields a function value of type +

+ +
+func(int) int
+
+ +

+These two invocations are equivalent: +

+ +
+t.Mv(7)
+f := t.Mv; f(7)
+
+ +

+Similarly, the expression +

+ +
+pt.Mp
+
+ +

+yields a function value of type +

+ +
+func(float32) float32
+
+ +

+As with selectors, a reference to a non-interface method with a value receiver +using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv. +

+ +

+As with method calls, a reference to a non-interface method with a pointer receiver +using an addressable value will automatically take the address of that value: t.Mp is equivalent to (&t).Mp. +

+ +
+f := t.Mv; f(7)   // like t.Mv(7)
+f := pt.Mp; f(7)  // like pt.Mp(7)
+f := pt.Mv; f(7)  // like (*pt).Mv(7)
+f := t.Mp; f(7)   // like (&t).Mp(7)
+f := makeT().Mp   // invalid: result of makeT() is not addressable
+
+ +

+Although the examples above use non-interface types, it is also legal to create a method value +from a value of interface type. +

+ +
+var i interface { M(int) } = myVal
+f := i.M; f(7)  // like i.M(7)
+
+ +

Index expressions

@@ -3436,232 +3663,6 @@ channel is closed and empty.

-

Method expressions

- -

-If M is in the method set of type T, -T.M is a function that is callable as a regular function -with the same arguments as M prefixed by an additional -argument that is the receiver of the method. -

- -
-MethodExpr    = ReceiverType "." MethodName .
-ReceiverType  = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
-
- -

-Consider a struct type T with two methods, -Mv, whose receiver is of type T, and -Mp, whose receiver is of type *T. -

- -
-type T struct {
-	a int
-}
-func (tv  T) Mv(a int) int         { return 0 }  // value receiver
-func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver
-
-var t T
-
- -

-The expression -

- -
-T.Mv
-
- -

-yields a function equivalent to Mv but -with an explicit receiver as its first argument; it has signature -

- -
-func(tv T, a int) int
-
- -

-That function may be called normally with an explicit receiver, so -these five invocations are equivalent: -

- -
-t.Mv(7)
-T.Mv(t, 7)
-(T).Mv(t, 7)
-f1 := T.Mv; f1(t, 7)
-f2 := (T).Mv; f2(t, 7)
-
- -

-Similarly, the expression -

- -
-(*T).Mp
-
- -

-yields a function value representing Mp with signature -

- -
-func(tp *T, f float32) float32
-
- -

-For a method with a value receiver, one can derive a function -with an explicit pointer receiver, so -

- -
-(*T).Mv
-
- -

-yields a function value representing Mv with signature -

- -
-func(tv *T, a int) int
-
- -

-Such a function indirects through the receiver to create a value -to pass as the receiver to the underlying method; -the method does not overwrite the value whose address is passed in -the function call. -

- -

-The final case, a value-receiver function for a pointer-receiver method, -is illegal because pointer-receiver methods are not in the method set -of the value type. -

- -

-Function values derived from methods are called with function call syntax; -the receiver is provided as the first argument to the call. -That is, given f := T.Mv, f is invoked -as f(t, 7) not t.f(7). -To construct a function that binds the receiver, use a -function literal or -method value. -

- -

-It is legal to derive a function value from a method of an interface type. -The resulting function takes an explicit receiver of that interface type. -

- -

Method values

- -

-If the expression x has static type T and -M is in the method set of type T, -x.M is called a method value. -The method value x.M is a function value that is callable -with the same arguments as a method call of x.M. -The expression x is evaluated and saved during the evaluation of the -method value; the saved copy is then used as the receiver in any calls, -which may be executed later. -

- -

-The type T may be an interface or non-interface type. -

- -

-As in the discussion of method expressions above, -consider a struct type T with two methods, -Mv, whose receiver is of type T, and -Mp, whose receiver is of type *T. -

- -
-type T struct {
-	a int
-}
-func (tv  T) Mv(a int) int         { return 0 }  // value receiver
-func (tp *T) Mp(f float32) float32 { return 1 }  // pointer receiver
-
-var t T
-var pt *T
-func makeT() T
-
- -

-The expression -

- -
-t.Mv
-
- -

-yields a function value of type -

- -
-func(int) int
-
- -

-These two invocations are equivalent: -

- -
-t.Mv(7)
-f := t.Mv; f(7)
-
- -

-Similarly, the expression -

- -
-pt.Mp
-
- -

-yields a function value of type -

- -
-func(float32) float32
-
- -

-As with selectors, a reference to a non-interface method with a value receiver -using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv. -

- -

-As with method calls, a reference to a non-interface method with a pointer receiver -using an addressable value will automatically take the address of that value: t.Mp is equivalent to (&t).Mp. -

- -
-f := t.Mv; f(7)   // like t.Mv(7)
-f := pt.Mp; f(7)  // like pt.Mp(7)
-f := pt.Mv; f(7)  // like (*pt).Mv(7)
-f := t.Mp; f(7)   // like (&t).Mp(7)
-f := makeT().Mp   // invalid: result of makeT() is not addressable
-
- -

-Although the examples above use non-interface types, it is also legal to create a method value -from a value of interface type. -

- -
-var i interface { M(int) } = myVal
-f := i.M; f(7)  // like i.M(7)
-
-

Conversions

-- 2.48.1