Hi,
this is probably not the best time to raise concerns about __invoke
(closures) now that alpha1 is already realeased, but I believe it's
worth it.
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:
function foo(Invokable $obj) {
$obj();
}
if ($foo instanceof Invokable) $foo();
etc..
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.
class A { public function __invoke($arg) {var_dump($arg); }} $a = new
A; $a(1,2); // int(1), currently. IMHO it should be array(1,2)
- Do we really want to allow both static and non-static versions of __invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.
I hope these issues can be discussed and maybe addressed before a
final 5.3 release. I'm willing to do patches for all three concerns if
I sense a positive feeling towards this.
Regards,
--
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
Hi Etienne,
Am Samstag, den 02.08.2008, 19:36 +0200 schrieb Etienne Kneuss:
[...]
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:
I would like that too, but if we do so, we must pass the parameters as
an array. With an interface we lose flexibility and that's why I would
not do it.
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.
class A { public function __invoke($arg) {var_dump($arg); }} $a = new
A; $a(1,2); // int(1), currently. IMHO it should be array(1,2)
That's what I don't like and this is really a dependency for 1).
- Do we really want to allow both static and non-static versions of __invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.
Doesn't make any sense yes indeed. If we would have __invokeStatic() it
would be another story.
cu, Lars
Hello Etienne,
Saturday, August 2, 2008, 7:36:23 PM, you wrote:
Hi,
this is probably not the best time to raise concerns about __invoke
(closures) now that alpha1 is already realeased, but I believe it's
worth it.
Actually it is the best time, well earlier would probably have been even
better. But seriously, the reason for an extended alpha phase is testing
and adjusting features if they do not behave as we like.
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:
function foo(Invokable $obj) {
$obj();
}
if ($foo instanceof Invokable) $foo();
etc..
Invokable sounds fine with me. It would be like Traversable. We don't
use Interfaces for much other stuff but imo we should.
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.
class A { public function __invoke($arg) {var_dump($arg); }} $a = new
A; $a(1,2); // int(1), currently. IMHO it should be array(1,2)
Of course not this must be fixed. After all we have invocation by
reflection with and without array. And this would be so badly inconsistent.
Which reminds me of writing a mail about the new inconsistencies in 5.3.
- Do we really want to allow both static and non-static versions of __invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.
I hope these issues can be discussed and maybe addressed before a
final 5.3 release. I'm willing to do patches for all three concerns if
I sense a positive feeling towards this.
Regards,
--
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
Best regards,
Marcus
Hello,
Hi,
this is probably not the best time to raise concerns about __invoke
(closures) now that alpha1 is already realeased, but I believe it's
worth it.
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:function foo(Invokable $obj) {
$obj();
}if ($foo instanceof Invokable) $foo();
etc..
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.
class A { public function __invoke($arg) {var_dump($arg); }} $a = new
A; $a(1,2); // int(1), currently. IMHO it should be array(1,2)
- Do we really want to allow both static and non-static versions of __invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.I hope these issues can be discussed and maybe addressed before a
final 5.3 release. I'm willing to do patches for all three concerns if
I sense a positive feeling towards this.Regards,
--
Etienne Kneuss
http://www.colder.chMen never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
After looking deeper into it, I noticed that this interface brings a
lot of problems:
- With the interface, the prototype is fixed.
Which means that the following are no longer possible:
Class A {
public function &__invoke(&$a, $b, $c) { return $a; }
}
$a = new A; $e =& $a($b,$c, $d);
- __invoke($args) seems more consistent, and would give a consistent
prototype, but
2.1) references are no longer possible (1)
2.2) __invoke of actual closures/lambdas needs to map parameters for
$a = function($b,$c){}; to work properly. I don't believe $cl =
function($args){..} is something we want
So, with those counter-concerns in mind, this Invokable interface is
no longer implementable, IMO.
However, I'd still like to make closures more flexible and
internals-friendly by implementing zend_get_closure as a handler.
The only (tiny) issue here is that we export a bit more
closure-material in the engine, and it's no longer so much
self-contained in zend_closures.
Patches:
http://patches.colder.ch/Zend/zend_get_closure_handler_53.patch?markup
http://patches.colder.ch/Zend/zend_get_closure_handler_HEAD.patch?markup
ps: this patches also expose the __invoke method for reflection. (Or
is there an actual reason behind not exposing it? )
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
Hello Etienne,
Monday, August 4, 2008, 12:03:01 AM, you wrote:
Hello,
Hi,
this is probably not the best time to raise concerns about __invoke
(closures) now that alpha1 is already realeased, but I believe it's
worth it.
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:function foo(Invokable $obj) {
$obj();
}if ($foo instanceof Invokable) $foo();
etc..
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.
class A { public function __invoke($arg) {var_dump($arg); }} $a = new
A; $a(1,2); // int(1), currently. IMHO it should be array(1,2)
- Do we really want to allow both static and non-static versions of __invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.I hope these issues can be discussed and maybe addressed before a
final 5.3 release. I'm willing to do patches for all three concerns if
I sense a positive feeling towards this.Regards,
--
Etienne Kneuss
http://www.colder.chMen never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
After looking deeper into it, I noticed that this interface brings a
lot of problems:
- With the interface, the prototype is fixed.
Which means that the following are no longer possible:
Class A {
public function &__invoke(&$a, $b, $c) { return $a; }
}
$a = new A; $e =& $a($b,$c, $d);
- __invoke($args) seems more consistent, and would give a consistent
prototype, but
2.1) references are no longer possible (1)
2.2) __invoke of actual closures/lambdas needs to map parameters for
$a = function($b,$c){}; to work properly. I don't believe $cl =
function($args){..} is something we want
So, with those counter-concerns in mind, this Invokable interface is
no longer implementable, IMO.
However, I'd still like to make closures more flexible and
internals-friendly by implementing zend_get_closure as a handler.
The only (tiny) issue here is that we export a bit more
closure-material in the engine, and it's no longer so much
self-contained in zend_closures.
Patches:
http://patches.colder.ch/Zend/zend_get_closure_handler_53.patch?markup
http://patches.colder.ch/Zend/zend_get_closure_handler_HEAD.patch?markup
Looks good to me.
ps: this patches also expose the __invoke method for reflection. (Or
is there an actual reason behind not exposing it? )
Nope.
Best regards,
Marcus
Hi!
- With the interface, the prototype is fixed.
That definitely would not work. Interface could leave __invoke
undefined, though then it'd be more of documentation/attribute purpose
than enforcing having __invoke. But it can be workable.
However, I'd still like to make closures more flexible and
internals-friendly by implementing zend_get_closure as a handler.
Hmm... it may work, at least at the first glance I don't see any trouble
with it.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hello Stanislav,
Monday, August 4, 2008, 7:06:59 AM, you wrote:
Hi!
- With the interface, the prototype is fixed.
That definitely would not work. Interface could leave __invoke
undefined, though then it'd be more of documentation/attribute purpose
than enforcing having __invoke. But it can be workable.
We have this for Traversable and because that one has no functions but
rather is an internal and external tag it cannot be implemented by user
classes directly. Instead the user must implement Iterator(Aggregate).
In this case we probably do not want Invokable and InvokableReference
though and simply combine with the magic function name.
However, I'd still like to make closures more flexible and
internals-friendly by implementing zend_get_closure as a handler.
Hmm... it may work, at least at the first glance I don't see any trouble
with it.
Best regards,
Marcus
Hi Etienne,
In general the patch looks fine.
The only thing I don't like is explicit declaration of Closure::__invode
method. It won't have proper arg_info.
Thanks. Dmitry.
Etienne Kneuss wrote:
Hello,
Hi,
this is probably not the best time to raise concerns about __invoke
(closures) now that alpha1 is already realeased, but I believe it's
worth it.
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:function foo(Invokable $obj) {
$obj();
}if ($foo instanceof Invokable) $foo();
etc..
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.
class A { public function __invoke($arg) {var_dump($arg); }} $a = new
A; $a(1,2); // int(1), currently. IMHO it should be array(1,2)
- Do we really want to allow both static and non-static versions of __invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.I hope these issues can be discussed and maybe addressed before a
final 5.3 release. I'm willing to do patches for all three concerns if
I sense a positive feeling towards this.Regards,
--
Etienne Kneuss
http://www.colder.chMen never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- PascalAfter looking deeper into it, I noticed that this interface brings a
lot of problems:
- With the interface, the prototype is fixed.
Which means that the following are no longer possible:Class A {
public function &__invoke(&$a, $b, $c) { return $a; }
}
$a = new A; $e =& $a($b,$c, $d);
- __invoke($args) seems more consistent, and would give a consistent
prototype, but
2.1) references are no longer possible (1)
2.2) __invoke of actual closures/lambdas needs to map parameters for
$a = function($b,$c){}; to work properly. I don't believe $cl =
function($args){..} is something we wantSo, with those counter-concerns in mind, this Invokable interface is
no longer implementable, IMO.However, I'd still like to make closures more flexible and
internals-friendly by implementing zend_get_closure as a handler.
The only (tiny) issue here is that we export a bit more
closure-material in the engine, and it's no longer so much
self-contained in zend_closures.Patches:
http://patches.colder.ch/Zend/zend_get_closure_handler_53.patch?markup
http://patches.colder.ch/Zend/zend_get_closure_handler_HEAD.patch?markupps: this patches also expose the __invoke method for reflection. (Or
is there an actual reason behind not exposing it? )
Hi Christan,
Could you please look into this patch.
I'm not sure if explicit declaration of Closure::__invoke() is good
idea. As it cannot provide proper argument information.
May be the patch which you propose already solves this problem for
reflection. (I didn't have time to look into it).
Thanks. Dmitry.
Etienne Kneuss wrote:
Hello,
Hi,
this is probably not the best time to raise concerns about __invoke
(closures) now that alpha1 is already realeased, but I believe it's
worth it.
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:function foo(Invokable $obj) {
$obj();
}if ($foo instanceof Invokable) $foo();
etc..
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.
class A { public function __invoke($arg) {var_dump($arg); }} $a = new
A; $a(1,2); // int(1), currently. IMHO it should be array(1,2)
- Do we really want to allow both static and non-static versions of __invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.I hope these issues can be discussed and maybe addressed before a
final 5.3 release. I'm willing to do patches for all three concerns if
I sense a positive feeling towards this.Regards,
--
Etienne Kneuss
http://www.colder.chMen never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- PascalAfter looking deeper into it, I noticed that this interface brings a
lot of problems:
- With the interface, the prototype is fixed.
Which means that the following are no longer possible:Class A {
public function &__invoke(&$a, $b, $c) { return $a; }
}
$a = new A; $e =& $a($b,$c, $d);
- __invoke($args) seems more consistent, and would give a consistent
prototype, but
2.1) references are no longer possible (1)
2.2) __invoke of actual closures/lambdas needs to map parameters for
$a = function($b,$c){}; to work properly. I don't believe $cl =
function($args){..} is something we wantSo, with those counter-concerns in mind, this Invokable interface is
no longer implementable, IMO.However, I'd still like to make closures more flexible and
internals-friendly by implementing zend_get_closure as a handler.
The only (tiny) issue here is that we export a bit more
closure-material in the engine, and it's no longer so much
self-contained in zend_closures.Patches:
http://patches.colder.ch/Zend/zend_get_closure_handler_53.patch?markup
http://patches.colder.ch/Zend/zend_get_closure_handler_HEAD.patch?markupps: this patches also expose the __invoke method for reflection. (Or
is there an actual reason behind not exposing it? )
Hello,
Hi Christan,
Could you please look into this patch.
I'm not sure if explicit declaration of Closure::__invoke() is good idea. As
it cannot provide proper argument information.May be the patch which you propose already solves this problem for
reflection. (I didn't have time to look into it).
After discussing it with Dmitry, I removed the reflection part from
the patch, giving full reflection info on Closures seems like a better
idea, even if it requires patching Reflection itself.
Regards
Thanks. Dmitry.
Etienne Kneuss wrote:
Hello,
Hi,
this is probably not the best time to raise concerns about __invoke
(closures) now that alpha1 is already realeased, but I believe it's
worth it.
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:function foo(Invokable $obj) {
$obj();
}if ($foo instanceof Invokable) $foo();
etc..
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.
class A { public function __invoke($arg) {var_dump($arg); }} $a = new
A; $a(1,2); // int(1), currently. IMHO it should be array(1,2)
- Do we really want to allow both static and non-static versions of
__invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.I hope these issues can be discussed and maybe addressed before a
final 5.3 release. I'm willing to do patches for all three concerns if
I sense a positive feeling towards this.Regards,
--
Etienne Kneuss
http://www.colder.chMen never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- PascalAfter looking deeper into it, I noticed that this interface brings a
lot of problems:
- With the interface, the prototype is fixed.
Which means that the following are no longer possible:Class A {
public function &__invoke(&$a, $b, $c) { return $a; }
}
$a = new A; $e =& $a($b,$c, $d);
- __invoke($args) seems more consistent, and would give a consistent
prototype, but
2.1) references are no longer possible (1)
2.2) __invoke of actual closures/lambdas needs to map parameters for
$a = function($b,$c){}; to work properly. I don't believe $cl =
function($args){..} is something we wantSo, with those counter-concerns in mind, this Invokable interface is
no longer implementable, IMO.However, I'd still like to make closures more flexible and
internals-friendly by implementing zend_get_closure as a handler.
The only (tiny) issue here is that we export a bit more
closure-material in the engine, and it's no longer so much
self-contained in zend_closures.Patches:
http://patches.colder.ch/Zend/zend_get_closure_handler_53.patch?markup
http://patches.colder.ch/Zend/zend_get_closure_handler_HEAD.patch?markupps: this patches also expose the __invoke method for reflection. (Or
is there an actual reason behind not exposing it? )
--
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
Hello,
Hi Christan,
Could you please look into this patch.
I'm not sure if explicit declaration of Closure::__invoke() is good idea. As
it cannot provide proper argument information.May be the patch which you propose already solves this problem for
reflection. (I didn't have time to look into it).After discussing it with Dmitry, I removed the reflection part from
the patch, giving full reflection info on Closures seems like a better
idea, even if it requires patching Reflection itself.
I'm confused. What exactly is the problem you solved?
-Hannes
Hello,
On Mon, Aug 4, 2008 at 7:59 PM, Hannes Magnusson
hannes.magnusson@gmail.com wrote:
Hello,
Hi Christan,
Could you please look into this patch.
I'm not sure if explicit declaration of Closure::__invoke() is good idea. As
it cannot provide proper argument information.May be the patch which you propose already solves this problem for
reflection. (I didn't have time to look into it).After discussing it with Dmitry, I removed the reflection part from
the patch, giving full reflection info on Closures seems like a better
idea, even if it requires patching Reflection itself.I'm confused. What exactly is the problem you solved?
Since no Invokable interface can sanely be implemented, it won't get
implemented. However, my patch adds flexibility for future internal
classes willing to use $x(); by defining get_closure as a handler.
Regards
-Hannes
--
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
Hello,
On Mon, Aug 4, 2008 at 7:59 PM, Hannes Magnusson
hannes.magnusson@gmail.com wrote:Hello,
Hi Christan,
Could you please look into this patch.
I'm not sure if explicit declaration of Closure::__invoke() is good idea. As
it cannot provide proper argument information.May be the patch which you propose already solves this problem for
reflection. (I didn't have time to look into it).After discussing it with Dmitry, I removed the reflection part from
the patch, giving full reflection info on Closures seems like a better
idea, even if it requires patching Reflection itself.I'm confused. What exactly is the problem you solved?
Since no Invokable interface can sanely be implemented, it won't get
implemented. However, my patch adds flexibility for future internal
classes willing to use $x(); by defining get_closure as a handler.
If committed, can we put in our CS that internal classes cannot use it?
I can almost not imagine more confusing things.
-Hannes
Hi!
If committed, can we put in our CS that internal classes cannot use it?
I can almost not imagine more confusing things.
I wouldn't say cannot, but maybe should not. For regular classes it
indeed doesn't make much sense, but if representing callable things for
bridges to other languages etc., there might be some use.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hi!
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:
We can have Invokable and even have Closure implement it, if there's
need, I see no problem with it.
However, I'm not sure we should require interface membership for
__invoke to work - I do not see any added value in this.
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.
More "consistent" with what? __call is different from __invoke - __call
is global interceptor (takes any function), __invoke is not. And you can
easily convert it to array with function_get_args().
- Do we really want to allow both static and non-static versions of __invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.
I don't see how static __invoke may be useful. Anyone has a use case?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hello,
Hello,
Hi!
- I don't believe that having it thrown as another of those magic
method is a good idea. Rather, I'd like to have it represented by an
interface: Invokable. That way, type hints/checks can be done in user
land in a sane matter:We can have Invokable and even have Closure implement it, if there's need, I
see no problem with it.
However, I'm not sure we should require interface membership for __invoke
to work - I do not see any added value in this.
I'm not sure I understand what you mean? Either the interface covers
__invoke and "$obj instanceof Invokable" is a safe check to know if we
can $obj();, or it doesn't and we know nothing.
- Do we really want __invoke's argument to be mapped to caller
arguments. Providing an array of arguments, ala __call(Static) sounds
more consistent.More "consistent" with what? __call is different from __invoke - __call is
global interceptor (takes any function), __invoke is not. And you can easily
convert it to array with function_get_args().
I agree, it's a feature that works "similarly" as __construct, and we
don't have __construct($args);
Additionally, it would require more work to distinguish:
$a = function($b,$c) { ... };
$a(1,2);
from
class A {
public function __invoke($args) {
}
}
$a = new A;
$a(1,2);
as we certainly don't want function($args){}.
In overall, there is no need to discuss that Interface much, as it
causes more problems than it solves.
But please check out the get_closure handler.
- Do we really want to allow both static and non-static versions of
__invoke ?
class A { public static function __invoke($args) { .. }} $a = new A;
$a(); being a static call to __invoke doesn't make much sense to me.I don't see how static __invoke may be useful. Anyone has a use case?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
--
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
Hello,
But please check out the get_closure handler.
Scratch that, I didn't see the other mails ;)
Regards,
--
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
Hi!
I'm not sure I understand what you mean? Either the interface covers
__invoke and "$obj instanceof Invokable" is a safe check to know if we
can $obj();, or it doesn't and we know nothing.
Well, if you put it this way, it's not going to work. However, I thought
there's middle ground - i.e. you can mark class as being "invokable" and
barring some extremely forgetful programmer not using good tools, that'd
mean it's safe to call since it was intended to be called. It's not 100%
proof, but it gives you some structure. Note that "safety" is very
relative here, since PHP is dynamic - as I explained in topics about
typehints, typehint would not exactly make your code "safe" anyway - it
would just shift the place where the trouble happens.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com