Commit f852034e authored by Robert Griesemer's avatar Robert Griesemer

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
parent 1e47854d
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of August 5, 2014",
"Subtitle": "Version of August 28, 2014",
"Path": "/ref/spec"
}-->
......@@ -2537,6 +2537,233 @@ p.M0() // ((*p).T0).M0()
</pre>
<h3 id="Method_expressions">Method expressions</h3>
<p>
If <code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
<code>T.M</code> is a function that is callable as a regular function
with the same arguments as <code>M</code> prefixed by an additional
argument that is the receiver of the method.
</p>
<pre class="ebnf">
MethodExpr = ReceiverType "." MethodName .
ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
</pre>
<p>
Consider a struct type <code>T</code> with two methods,
<code>Mv</code>, whose receiver is of type <code>T</code>, and
<code>Mp</code>, whose receiver is of type <code>*T</code>.
</p>
<pre>
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
</pre>
<p>
The expression
</p>
<pre>
T.Mv
</pre>
<p>
yields a function equivalent to <code>Mv</code> but
with an explicit receiver as its first argument; it has signature
</p>
<pre>
func(tv T, a int) int
</pre>
<p>
That function may be called normally with an explicit receiver, so
these five invocations are equivalent:
</p>
<pre>
t.Mv(7)
T.Mv(t, 7)
(T).Mv(t, 7)
f1 := T.Mv; f1(t, 7)
f2 := (T).Mv; f2(t, 7)
</pre>
<p>
Similarly, the expression
</p>
<pre>
(*T).Mp
</pre>
<p>
yields a function value representing <code>Mp</code> with signature
</p>
<pre>
func(tp *T, f float32) float32
</pre>
<p>
For a method with a value receiver, one can derive a function
with an explicit pointer receiver, so
</p>
<pre>
(*T).Mv
</pre>
<p>
yields a function value representing <code>Mv</code> with signature
</p>
<pre>
func(tv *T, a int) int
</pre>
<p>
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.
</p>
<p>
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.
</p>
<p>
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 <code>f := T.Mv</code>, <code>f</code> is invoked
as <code>f(t, 7)</code> not <code>t.f(7)</code>.
To construct a function that binds the receiver, use a
<a href="#Function_literals">function literal</a> or
<a href="#Method_values">method value</a>.
</p>
<p>
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.
</p>
<h3 id="Method_values">Method values</h3>
<p>
If the expression <code>x</code> has static type <code>T</code> and
<code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
<code>x.M</code> is called a <i>method value</i>.
The method value <code>x.M</code> is a function value that is callable
with the same arguments as a method call of <code>x.M</code>.
The expression <code>x</code> 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.
</p>
<p>
The type <code>T</code> may be an interface or non-interface type.
</p>
<p>
As in the discussion of <a href="#Method_expressions">method expressions</a> above,
consider a struct type <code>T</code> with two methods,
<code>Mv</code>, whose receiver is of type <code>T</code>, and
<code>Mp</code>, whose receiver is of type <code>*T</code>.
</p>
<pre>
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
</pre>
<p>
The expression
</p>
<pre>
t.Mv
</pre>
<p>
yields a function value of type
</p>
<pre>
func(int) int
</pre>
<p>
These two invocations are equivalent:
</p>
<pre>
t.Mv(7)
f := t.Mv; f(7)
</pre>
<p>
Similarly, the expression
</p>
<pre>
pt.Mp
</pre>
<p>
yields a function value of type
</p>
<pre>
func(float32) float32
</pre>
<p>
As with <a href="#Selectors">selectors</a>, a reference to a non-interface method with a value receiver
using a pointer will automatically dereference that pointer: <code>pt.Mv</code> is equivalent to <code>(*pt).Mv</code>.
</p>
<p>
As with <a href="#Calls">method calls</a>, a reference to a non-interface method with a pointer receiver
using an addressable value will automatically take the address of that value: <code>t.Mp</code> is equivalent to <code>(&amp;t).Mp</code>.
</p>
<pre>
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 (&amp;t).Mp(7)
f := makeT().Mp // invalid: result of makeT() is not addressable
</pre>
<p>
Although the examples above use non-interface types, it is also legal to create a method value
from a value of interface type.
</p>
<pre>
var i interface { M(int) } = myVal
f := i.M; f(7) // like i.M(7)
</pre>
<h3 id="Index_expressions">Index expressions</h3>
<p>
......@@ -3436,232 +3663,6 @@ channel is closed and empty.
</p>
<h3 id="Method_expressions">Method expressions</h3>
<p>
If <code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
<code>T.M</code> is a function that is callable as a regular function
with the same arguments as <code>M</code> prefixed by an additional
argument that is the receiver of the method.
</p>
<pre class="ebnf">
MethodExpr = ReceiverType "." MethodName .
ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
</pre>
<p>
Consider a struct type <code>T</code> with two methods,
<code>Mv</code>, whose receiver is of type <code>T</code>, and
<code>Mp</code>, whose receiver is of type <code>*T</code>.
</p>
<pre>
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
</pre>
<p>
The expression
</p>
<pre>
T.Mv
</pre>
<p>
yields a function equivalent to <code>Mv</code> but
with an explicit receiver as its first argument; it has signature
</p>
<pre>
func(tv T, a int) int
</pre>
<p>
That function may be called normally with an explicit receiver, so
these five invocations are equivalent:
</p>
<pre>
t.Mv(7)
T.Mv(t, 7)
(T).Mv(t, 7)
f1 := T.Mv; f1(t, 7)
f2 := (T).Mv; f2(t, 7)
</pre>
<p>
Similarly, the expression
</p>
<pre>
(*T).Mp
</pre>
<p>
yields a function value representing <code>Mp</code> with signature
</p>
<pre>
func(tp *T, f float32) float32
</pre>
<p>
For a method with a value receiver, one can derive a function
with an explicit pointer receiver, so
</p>
<pre>
(*T).Mv
</pre>
<p>
yields a function value representing <code>Mv</code> with signature
</p>
<pre>
func(tv *T, a int) int
</pre>
<p>
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.
</p>
<p>
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.
</p>
<p>
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 <code>f := T.Mv</code>, <code>f</code> is invoked
as <code>f(t, 7)</code> not <code>t.f(7)</code>.
To construct a function that binds the receiver, use a
<a href="#Function_literals">function literal</a> or
<a href="#Method_values">method value</a>.
</p>
<p>
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.
</p>
<h3 id="Method_values">Method values</h3>
<p>
If the expression <code>x</code> has static type <code>T</code> and
<code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
<code>x.M</code> is called a <i>method value</i>.
The method value <code>x.M</code> is a function value that is callable
with the same arguments as a method call of <code>x.M</code>.
The expression <code>x</code> 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.
</p>
<p>
The type <code>T</code> may be an interface or non-interface type.
</p>
<p>
As in the discussion of <a href="#Method_expressions">method expressions</a> above,
consider a struct type <code>T</code> with two methods,
<code>Mv</code>, whose receiver is of type <code>T</code>, and
<code>Mp</code>, whose receiver is of type <code>*T</code>.
</p>
<pre>
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
</pre>
<p>
The expression
</p>
<pre>
t.Mv
</pre>
<p>
yields a function value of type
</p>
<pre>
func(int) int
</pre>
<p>
These two invocations are equivalent:
</p>
<pre>
t.Mv(7)
f := t.Mv; f(7)
</pre>
<p>
Similarly, the expression
</p>
<pre>
pt.Mp
</pre>
<p>
yields a function value of type
</p>
<pre>
func(float32) float32
</pre>
<p>
As with <a href="#Selectors">selectors</a>, a reference to a non-interface method with a value receiver
using a pointer will automatically dereference that pointer: <code>pt.Mv</code> is equivalent to <code>(*pt).Mv</code>.
</p>
<p>
As with <a href="#Calls">method calls</a>, a reference to a non-interface method with a pointer receiver
using an addressable value will automatically take the address of that value: <code>t.Mp</code> is equivalent to <code>(&amp;t).Mp</code>.
</p>
<pre>
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 (&amp;t).Mp(7)
f := makeT().Mp // invalid: result of makeT() is not addressable
</pre>
<p>
Although the examples above use non-interface types, it is also legal to create a method value
from a value of interface type.
</p>
<pre>
var i interface { M(int) } = myVal
f := i.M; f(7) // like i.M(7)
</pre>
<h3 id="Conversions">Conversions</h3>
<p>
......
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