Good evening,
I’ve updated the patch to work with phpng, so the Closure::call() RFC has been put to a vote:
https://wiki.php.net/rfc/closure_apply#vote
The vote ends 2014-08-17. The Function Referencing as Closures RFC is not yet being put to a vote.
Thanks!
Andrea Faulds
http://ajf.me/
I have a small clarification question on the RFC: you are adding
another parameter to bindTo which defaults to false, but I didn't
quite understand the reasoning. Can you try explaining that to me in a
different way?
Hi!
I have a small clarification question on the RFC: you are adding
another parameter to bindTo which defaults to false, but I didn't
quite understand the reasoning. Can you try explaining that to me in a
different way?
Interestingly enough, the RFC doesn't even mention this change.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
I have a small clarification question on the RFC: you are adding
another parameter to bindTo which defaults to false, but I didn't
quite understand the reasoning. Can you try explaining that to me in a
different way?
I’ll give it a go.
Closures have a bound object and a scope. The bound object is whatever $this will be set to when that closure is called. The scope is the class whose private variables can be seen by a closure.
->call() will call the closure and use its existing scope but the bound object will be what is passed as its first parameter. ->call() doesn’t permit calling with a different scope.
This presents a conundrum, however, if you want to use ->call() with a closure and you want to have a scope. Currently, ::bind() and ->bindTo() only permit two types of closures with scopes: those that are static (can’t have $this bound) and those that have an object bound. This means to create a closure with a scope that you can then use with ->call(), you’d have to make one with a dummy object already bound. In most cases you can do this, but there are a few you can’t, and it’s weird to have to bind an object when we’re not going to use it anyway as ->call() is going to override it.
For this reason, a third parameter is added to ::bind() and ->bindTo() which makes it produce an unbound, scoped closure rather than a static scoped closure if we don’t pass an object to be bound and we specify a scope. The need for the third parameter is really just backwards-compatibility. At the moment, if you pass NULL
for the object to bind to and pass a class name for the scope, it’ll make a static closure. We could change this and make it produce an unbound closure and add some other mechanism to obtain a static closure, but that would break backwards-compatibility. For this reason, we instead add a third parameter to say, yes, we do want an unbound closure. The same thing is done internally too, with zend_create_closure_ex.
Hi!
I have a small clarification question on the RFC: you are adding
another parameter to bindTo which defaults to false, but I didn't
quite understand the reasoning. Can you try explaining that to me in a
different way?Interestingly enough, the RFC doesn't even mention this change.
It does, but maybe you missed it. Under the Proposal section:
To solve this, we relax the current invariant of scoped closures having to be bound, and add a new parameter to bind(To) to produce an unbound, scoped closure, like so:
--
Andrea Faulds
http://ajf.me/
Hi!
It does, but maybe you missed it. Under the Proposal section:
To solve this, we relax the current invariant of scoped closures
having to be bound, and add a new parameter to bind(To) to produce
an unbound, scoped closure, like so:
Indeed, I missed it - I was looking for bindTo. I think it should be
made more prominent, and I'm not sure what closure that is not static,
but does not have a bound object, means. What happens if you call it? It
sounds a bit strange concept - why would you need a closure that is not
static, but is not bound to any object?
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
Hi!
It does, but maybe you missed it. Under the Proposal section:
To solve this, we relax the current invariant of scoped closures
having to be bound, and add a new parameter to bind(To) to produce
an unbound, scoped closure, like so:Indeed, I missed it - I was looking for bindTo. I think it should be
made more prominent, and I'm not sure what closure that is not static,
but does not have a bound object, means. What happens if you call it? It
sounds a bit strange concept - why would you need a closure that is not
static, but is not bound to any object?
Hence the vote was cancelled while it is reworked.
Hi!
It does, but maybe you missed it. Under the Proposal section:
To solve this, we relax the current invariant of scoped closures
having to be bound, and add a new parameter to bind(To) to produce
an unbound, scoped closure, like so:Indeed, I missed it - I was looking for bindTo. I think it should be
made more prominent, and I'm not sure what closure that is not static,
but does not have a bound object, means. What happens if you call it? It
sounds a bit strange concept - why would you need a closure that is not
static, but is not bound to any object?Hence the vote was cancelled while it is reworked.
To clarify: The RFC has been reworked now, I actually changed the RFC and patch just before I cancelled the vote. Review appreciated before vote is reopened.
--
Andrea Faulds
http://ajf.me/
I will +1 this as I have had to deal with some of these struggles, as a
suggestion though:
"Like the bind(To) methods, a static class cannot be bound (using →call
will fail)"
I would like to see this function work like
Closure::bind()/Closure::bindTo() and give the option for the $newScope
option.
why would you need a closure that is not static,
but is not bound to any object?
I think I can answer this, I wrote a project which allows for "hooks" to be
installed in areas of the code. I made it so each [static] method has a
"before" and "after" which may be tied to it. This allows for things like:
"beforeUpdate()" or "afterUpdate" or "afterCreate" exc... The framework
handled the installation and execution of all hooks that a dev may have
wished to install. If a method like this was available it would use much
less resources and be faster in theory because the PHP engine would not
need to create an entirely new object/closure every time I wished to
execute the method.
Simple example of what I spoke of above:
https://gist.github.com/allada/b7e880104e3a7eb13a63
Notice how you don't need to create an entirely new object just to call a
method inside a scope. This allows a dev to make their closure have access
to $this just as if it was installed inside the function it's hooking into.
On Sun, Aug 17, 2014 at 5:13 PM, Stas Malyshev smalyshev@sugarcrm.com
wrote:Hi!
It does, but maybe you missed it. Under the Proposal section:
To solve this, we relax the current invariant of scoped closures
having to be bound, and add a new parameter to bind(To) to produce
an unbound, scoped closure, like so:Indeed, I missed it - I was looking for bindTo. I think it should be
made more prominent, and I'm not sure what closure that is not static,
but does not have a bound object, means. What happens if you call it? It
sounds a bit strange concept - why would you need a closure that is not
static, but is not bound to any object?Hence the vote was cancelled while it is reworked.
To clarify: The RFC has been reworked now, I actually changed the RFC and
patch just before I cancelled the vote. Review appreciated before vote is
reopened.--
Andrea Faulds
http://ajf.me/
https://wiki.php.net/rfc/closure_apply#vote
The vote ends 2014-08-17. The Function Referencing as Closures RFC is not yet being put to a vote.
I cancelled the vote as I’ve changed what the RFC does after some discussion. Instead of having unbound, scoped closures, I’ve instead just made ->call use whatever class the passed object has as its scope.
I’ll reopen voting in 2 days as I think this is a rather uncontroversial change.
Andrea Faulds
http://ajf.me/