Skip to content

Commit 124838c

Browse files
Corrected to cover closure binding and scoping properly
1 parent a610388 commit 124838c

File tree

1 file changed

+32
-12
lines changed

1 file changed

+32
-12
lines changed

spec/php-spec-draft.md

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3830,7 +3830,7 @@ unset($x->m); // if m is a dynamic property, $x's __unset("m") is called
38303830

38313831
<pre>
38323832
<i>anonymous-function-creation-expression:</i>
3833-
function &<sub>opt</sub> ( <i>parameter-declaration-list<sub>opt<sub></i> ) <i>anonymous-function-use-clause<sub>opt</sub></i>
3833+
static<sub>opt</sub> function &<sub>opt</sub> ( <i>parameter-declaration-list<sub>opt<sub></i> ) <i>anonymous-function-use-clause<sub>opt</sub></i>
38343834
<i>compound-statement</i>
38353835

38363836
<i>anonymous-function-use-clause:</i>
@@ -3862,13 +3862,20 @@ needed. The values used for these variables are those at the time the
38623862
`Closure` object is created, not when it is used to call the function it
38633863
encapsulates.
38643864

3865-
An anonymous function defined inside an instance method has access to
3866-
the variable `$this`.
3865+
An anonymous function defined inside an instance or static method has its
3866+
*scope* ([§§](#class-closure)) set to the class it was defined in. Otherwise,
3867+
an anonymous function is *unscoped* ([§§](#class-closure)).
3868+
3869+
An anonymous function defined inside an instance method is is *bound*
3870+
([§§](#class-closure)) to the object on which that method is called, while an
3871+
an anonymous function defined inside a static method, or prefixed with the
3872+
optional `static` modifier is *static* ([§§](#class-closure)), and otherwise
3873+
an anonymous function is *unbound* ([§§](#class-closure)).
38673874

38683875
**Examples**
38693876

38703877
```
3871-
function doit($value, callable $process) // return type is "Closure"
3878+
function doit($value, callable $process) // return type is "Closure", unbound
38723879
{
38733880
return $process($value);
38743881
}
@@ -9335,6 +9342,19 @@ for representing an [anonymous
93359342
function](http://php.net/manual/functions.anonymous.php). It
93369343
cannot be instantiated except by the Engine, as described below.
93379344

9345+
Closures can be *bound*, *unbound* or *static*. If a closure is said to be
9346+
bound, then it has an object that $this will be bound to when called. If a
9347+
closure is unbound, then it has no object $this will be bound to. If a closure
9348+
is static, then it cannot be bound.
9349+
9350+
Closures can be *scoped* or *unscoped*. If a closure is said to be *scoped*, it
9351+
has a class *scope* which determines the visibility of the private and protected
9352+
members of objects of tha class, including but not limited to such members on
9353+
`$this`. If a closure is said to be *unscoped*, it has no class scope set.
9354+
9355+
Closures have an invariant that scoped closures must be bound or static, and
9356+
unbound closures must be unscoped.
9357+
93389358
```
93399359
class Closure
93409360
{
@@ -9348,7 +9368,7 @@ The class members are defined below:
93489368

93499369
Name | Purpose
93509370
-----|--------
9351-
`bind` | Duplicates closure `$closure` with a specific bound object `$newthis` and class scope `$newscope`. Make `$newthis` `NULL` if the closure is to be unbound. `$newscope` is the class scope to which the closure is to be associated, or static to keep the current one. If an object is given, the type of the object will be used instead. This determines the visibility of protected and private methods of the bound object. Returns a new `Closure` object or `FALSE` on failure.
9371+
`bind` | Duplicates closure `$closure` with a specific bound object `$newthis` and class scope `$newscope`. Make `$newthis` `NULL` if the closure is to be unbound, or if a scope is specified, static. `$newscope` is the class scope to which the closure is to be associated, or static to keep the current one. If an object is given, the type of the object will be used instead. This determines the visibility of protected and private methods of the bound object. Returns a new `Closure` object or `FALSE` on failure. This function must not violate the invariant that closures must either be both scoped and bound or static, or otherwise both unscoped and unbound.
93529372
`bindTo` | Duplicates the closure designated by the current instance with a new-bound object and class scope. This method is an instance version of bind.
93539373

93549374
When the anonymous function-creation operator ([§§](#anonymous-function-creation)) is evaluated,
@@ -9383,13 +9403,13 @@ in order: `static`, `this`, and `parameter`.
93839403

93849404
If an *anonymous-function-creation-expression* contains an
93859405
*anonymous-function-use-clause*, a dynamic property called `static` is
9386-
present. This property is an array having an element for each
9387-
*variable-name* in the *use-variable-name-list*, inserted in lexical
9388-
order of their appearance in the use clause. Each element's key is the
9389-
corresponding *variable-name*, and each element value is the value of
9390-
that variable at the time the time the `Closure` object is created (not
9391-
when it is used to call the encapsulated function). In the scenario
9392-
above, this leads to the following, shown as pseudo code:
9406+
present. This is unrelated to whether a closure is said to be *static*. This
9407+
property is an array having an element for each *variable-name* in the
9408+
*use-variable-name-list*, inserted in lexical order of their appearance in the
9409+
use clause. Each element's key is the corresponding *variable-name*, and each
9410+
element value is the value of that variable at the time the time the `Closure`
9411+
object is created (not when it is used to call the encapsulated function). In
9412+
the scenario above, this leads to the following, shown as pseudo code:
93939413

93949414
```
93959415
$this->static = array(["count"]=>&0,["values"]=>array(["red"]=>3,[0]=>10));

0 commit comments

Comments
 (0)