Hello Internals,

  our new closures can easily work as prototypes and I actually thought
of simply doing it as a bug fix. But it appeared that my first attempt
was inclomplete if not to say completely wrong. It further more turned
out that not everyone is a fan of the genral idea.

Basically what I expected is that closures assigned to object properties
behave in the same way prototypes behave. That is:

1) a non static closure assigned to an instance changes the closures
this to be set to the actual object:
$closure = function() {}
// $closure->this == NULL
$obj1->property = $closure;
// $obj1->property->this == $obj1;
// $closure->this == NULL

2) a static closure assigned to an instance sets the closure's scope

1+2) both give access to private members

3) Assignment of a closure from one object property to another objects
property changes it $this.
$obj2->property = $obj1->property;
// $obj1->property->this == $obj1
// $obj2->property->this == $obj2

4) Cloning an object assigns the properties correct. Right now we
increase the refcount only instead of cloning as that is the default
behavior of cloning. Since a normal variable splits on changes nothing
ever notices this. For oject types that do not support cloning this is
very different though. Now we cannot simply add cloning as then we'd
further change closure behavior. And this way we would not fix the this
pointer.
$obj3 = clone $obj;
// $obj3>property->this == $obj3

5) A closure assigned to a property can be called directly rather
than just by a temporary variable:
$obj->property = function() {}
$obj->property();  // valid call

The above requires the following internal modifications:

1) Closures internally support clone, but do not set the actual handler,
thus preventing anything else from cloning them (current behavior).

2) Default object cloning does not only call add_ref per member variable
but also checks for a member being a prototype method in which case it
performs the necessary cloning of that property.

3) An additonal check in the default property get handler is reaquired
to check for a closure property (prototype) in case a function cannot be
found. Unless someone uses closures there will be no change in behavior.
If this gets done later we will change behavior.

Why did I work on this:

1) Because to me the current implementation is broken. While as closures
themselves work perfect, they simply work very unexpected when assigned
to an object.

2) The current behavior seems inconsistent as it matters where an
assignment of a closure to a proeprty is being performed. OR how a closure
is being created.

3) The current behavior can be used as an impleentation of prototype
methods in PHP. However it just does a very tiny subset that makes it
a broken implementation. So we will end up in a situation where users see
prototype methods but don't get them to work.

4) We could finally get more consistency because we would have a partial
protoype ojbect model not only for member variables but also for member
functions.

Issues that speak against this:

1) A closure bound to a property is case sensitive  unlike a member
function. We have this however anyway. As we already have functions
callable by variables whether the variable is a closure or just a
function name.

2) To close to a release. Well that's why we have beta cycles to identify
tsituations like this.

3) If closures get callable by property directly then we end up in a
situation where we can have two methods with the same name. That means it
is discussable whether we want to allow assignment of a closure to a
member variable name that already exists as a private member function.

Best regards,
 Marcus


-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to