Hi,
Sorry to bring that up again!
Quick summary for people that didn't follow it: LSB was implemented,
and it was decided that "explicit calls" ( ClassName::method() )
wouldn't pass the caller info if no fallbacks occured. Some people
that were looking forward to having LSB were disappointed as it meant
that it wouldn't be possible to sanely overwrite a static method,
without loosing info on the caller.
Quick POC:
class A { public static function test() { echo get_called_class()
; }}
class B extends A { public static function test() { echo
get_called_class()
; parent::test(); }
class C extends B;
C::test(); // will output CA
To be able to pass information, it was decided to implement a
call_user_func-like function that passed the caller info:
forward_static_call(_array).
Back then, I was for that solution, but with some time I realized that
it would probably be one of those decisions that would bite us back
afterward.
To sum up key points about each possibilities:
- forward_static_call
- no need to affect the engine
- slow, painful
- parent:: carries the info while ParentClassName:: doesn't
- convenient
- no functionnality lost
- introduces a difference between parent:: and classname::, but
restricted to LSB so no BC break
It really seems like (2) is the most PHP way of doing things, while
(1) is more of a hack that we will regret later.
The only problem about (2) is that difference, but I really feel (and
experienced in the multiple help channels that I'm in) that people
already see (wrongly for now) classname:: and parent:: as slightly
different. So introducing it as of 5_3 wouldn't be too much of a
shock. The point is that: people who uses LSB will be aware of that
difference and will use parent:: vs classname:: carefully, while
others will be able to ignore it
So, I really would like to revert that foward_static_call stuff and
implement the parent:: patch instead, while it's still possible.
thoughts?
--
Etienne Kneuss
http://www.colder.ch
Men never do evil so completely and cheerfully as
when they do it from a religious conviction.
-- Pascal
To sum up key points about each possibilities:
- forward_static_call
- no need to affect the engine
- slow, painful
- parent:: carries the info while ParentClassName:: doesn't
- convenient
- no functionnality lost
- introduces a difference between parent:: and classname::, but
restricted to LSB so no BC breakIt really seems like (2) is the most PHP way of doing things, while
(1) is more of a hack that we will regret later.
The only problem about (2) is that difference, but I really feel (and
experienced in the multiple help channels that I'm in) that people
already see (wrongly for now) classname:: and parent:: as slightly
different. So introducing it as of 5_3 wouldn't be too much of a
shock. The point is that: people who uses LSB will be aware of that
difference and will use parent:: vs classname:: carefully, while
others will be able to ignore itSo, I really would like to revert that foward_static_call stuff and
implement the parent:: patch instead, while it's still possible.thoughts?
I am all for it.
that would be "intuitive" way of doing things, like I already stated before
--
Alexey Zakhlestin
http://blog.milkfarmsoft.com/
Hi!
So, I really would like to revert that foward_static_call stuff and
implement the parent:: patch instead, while it's still possible.thoughts?
Didn't we discuss that already? Adding magic to parent:: is not a good
idea, it's very basic language construct and should work simple. LSB is
an advanced feature, which probably would be used deep inside library
guts and thus can use more elaborate syntax.
On top of that, by making parent:: forward called class name, you remove
the possibility of doing non-forwarding call to the parent class.
As for it being slow - how slow it is? Does it really so slow that it
makes real-life application that otherwise would be fast to be slow? Or
it's just "couple more CPU cycles" slow? I suspect the latter - and thus
I don't think speed optimizations belong there.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
On top of that, by making parent:: forward called class name, you remove
the possibility of doing non-forwarding call to the parent class.
why would anyone need that?
"parent" is related to inheritance and it is logical, that it retains
call-chain.
if you just want to call "method of some class", you call it by class's name.
--
Alexey Zakhlestin
http://blog.milkfarmsoft.com/
Hi!
why would anyone need that?
To use function that does use static without dependence on in which
context if was called (or, explaining it other way, when your chain of
inheritance serves multiple purposes):
class ActiveRecord {
static function getRow($condition) {
$table = new Table(get_called_class());
return $table->find($condition);
}
}
class Users extends ActiveRecord {
}
class DepartmentUsers extends Users {
static function find($user) {
if(self::user_in_department($user)) {
return parent::getRow("user=$user");
}
return false;
}
}
$user = DepartmentUsers::find("bob");
Now in this case if your way is implemented, ActiveRecord would try to
find table for DepartmentUsers, which probably does not exist. You would
have to name Users by name there to do what this code wants to do, which
leads us back to "why we have parent:: at all" argument.
"parent" is related to inheritance and it is logical, that it retains
call-chain.
It is "logical" if you look at it with the narrow point of view of what
you need for your particular application. However, there are other use
cases. Automatic forwarding may become very awkward if you have multiple
levels of inheritance not all of them used for the same thing.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hi!
why would anyone need that?
To use function that does use static without dependence on in which context
if was called (or, explaining it other way, when your chain of inheritance
serves multiple purposes):class ActiveRecord {
static function getRow($condition) {
$table = new Table(get_called_class());
return $table->find($condition);
}
}class Users extends ActiveRecord {
}class DepartmentUsers extends Users {
static function find($user) {
if(self::user_in_department($user)) {
return parent::getRow("user=$user");
}
return false;
}
}$user = DepartmentUsers::find("bob");
Now in this case if your way is implemented, ActiveRecord would try to find
table for DepartmentUsers, which probably does not exist. You would have to
name Users by name there to do what this code wants to do, which leads us
back to "why we have parent:: at all" argument.
in my ActiveRecord, table for DepartmentUsers would actually exist ;)
"parent" is related to inheritance and it is logical, that it retains
call-chain.It is "logical" if you look at it with the narrow point of view of what you
need for your particular application. However, there are other use cases.
Automatic forwarding may become very awkward if you have multiple levels of
inheritance not all of them used for the same thing.
I am just looking for consistency. I am expecting get_called_class()
to work as a static analog of get_class(this)
--
Alexey Zakhlestin
http://blog.milkfarmsoft.com/
Hi!
in my ActiveRecord, table for DepartmentUsers would actually exist ;)
Even worse. All the data is in the Users table, DepartmentUsers is just
a functionality extension. So you'll be operating on wrong data.
I am just looking for consistency. I am expecting
get_called_class()
to work as a static analog of get_class(this)
Can we PLEASE stop using "consistency" to mean "do as I say"? What
"consistency" is in changing way parent:: worked for years, making
parent:: and class:: work differently and disabling non-forwarding call?
Consistency with what - with your wishes?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
<?php
class A
{
function mA()
{
echo get_class($this);
}
static function mB()
{
echo `get_called_class()`;
}
}
class B extends A
{
function mA()
{
parent::mA();
}
static function mB()
{
parent::mB();
}
}
$obj = new B();
$obj->mA();
B::mB();
Currently, this will output BA. You can't tell me, that it is consistent.
Currently, this will output BA. You can't tell me, that it is consistent.
Sure, it's very inconsistent. Also, when you do 2+3, the result is 5,
and when you do 2*3, result is 6. It's very inconsistent too. Let's
change + to do multiplication, so it'd be "consistent". Why on earth
different functions, created for different purposes, used in different
contexts, should always give you the same result? What idea of
"consistency" is that?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
<?php
class A
{
function mA()
{
$this->nA();
}
static function mB()
{
self::nB();
}
}
class B extends A
{
function mA()
{
parent::mA();
}
static function mB()
{
parent::mB();
}
function nA()
{
echo 'A';
}
function nB()
{
echo 'B';
}
}
$obj = new B();
$obj->mA();
B::mB();
?>
Most people will think, that it will output AB. But currently in PHP
5.2 (I don't have PHP 5.3 to test it) it will output:
A
Fatal error: Call to undefined method A::nb() in
Z:\localhost\testLSB.php on line 11
User that sees this, doesn't have any idea where is the problem and
how to find some information about it.
Hi!
Most people will think, that it will output AB. But currently in PHP
5.2 (I don't have PHP 5.3 to test it) it will output:
Most people will know (if really trying to understand and not trying to
appear as they do not understand simple things in order to advance their
point) that "self" is the same as name of the class it appears in, and
"parent" is the same as name of the parent class of the class it appears
in. So self::nB means A::nB, which does not exist. How hard is that?
User that sees this, doesn't have any idea where is the problem and
how to find some information about it.
How hard the concept of "self means this class, parent means parent
class" is to grasp? Are you really trying to argue that it is hard for
you to understand such concept?
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Janusz Lewandowski wrote:
<?php
class A
{
function mA()
{
$this->nA();
}static function mB()
{
self::nB();
}
}class B extends A
{
function mA()
{
parent::mA();
}static function mB()
{
parent::mB();
}function nA()
{
echo 'A';
}function nB()
{
echo 'B';
}
}$obj = new B();
$obj->mA();
B::mB();
?>Most people will think, that it will output AB. But currently in PHP
5.2 (I don't have PHP 5.3 to test it) it will output:
A
Fatal error: Call to undefined method A::nb() in
Z:\localhost\testLSB.php on line 11User that sees this, doesn't have any idea where is the problem and
how to find some information about it.
If I may throw my 2 cents in, if it's even worth anything anyway. This
is exactly what I would expect the output to be.
If you would want A::mB() to go back to B::nB() I would switch the
self::nB() to static::nB(), and have an abstract nB() method declared in
A. Is this not how everyone thinks it should be?
Hello,
With such example, using Users:: over parent:: actually makes sense as
your intent is to request something strictly related to Users, and
you're not expecting any inheritance.
Sure, introducing a difference is not a perfect solution, but the
general feeling is that it's the best at hand.
No need to argue over and over, I'll produce a patch based on the
(probably) outdated one done by Mike and have it committed if no new
strong feelings against it raises.
Regards,
Hi!
in my ActiveRecord, table for DepartmentUsers would actually exist ;)
Even worse. All the data is in the Users table, DepartmentUsers is just a
functionality extension. So you'll be operating on wrong data.I am just looking for consistency. I am expecting
get_called_class()
to work as a static analog of get_class(this)Can we PLEASE stop using "consistency" to mean "do as I say"? What
"consistency" is in changing way parent:: worked for years, making parent::
and class:: work differently and disabling non-forwarding call? Consistency
with what - with your wishes?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
Hi!
No need to argue over and over, I'll produce a patch based on the
(probably) outdated one done by Mike and have it committed if no new
strong feelings against it raises.
I must be missing something in this "discussion" concept. So it goes
like this: "I will make a patch and commit" - "No, please don't, it is
not good!" - argument, argument, tons of explanations why it's not good
- "OK, no need to argue, I will make patch and commit". Why bother?
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hello,
you're the only one disagreeing here, in this thread everybody is in
favor of that change except you, and your arguments are:
- this difference is bad
- no problem with functions
For which I've (along with others) already argued that:
1.1) some difference is already felt by regular users (They actually
believe that parent:: is a special construct that allows non-static
calls), I'm not saying it's OK because they're wrong, but it won't be
a shock to introduce a difference.
1.2) the difference is only relevant in some very limited cases
1.3) the ClassName:: alternative needs to be used on very very limited cases
2.1) functions shouldn't be here to solve language design problems,
especially when half of the feature is implemented as a keyword.
2.2) It's not convenient at all (c.f. references) , has WTF factors
(c.f. referencing unrelated class), confusing naming.
So yeah, if you're really the only one against it, and nobody else
speaks up to disagree, I guess it should be ok to commit it.
Regards
Hi!
No need to argue over and over, I'll produce a patch based on the
(probably) outdated one done by Mike and have it committed if no new
strong feelings against it raises.I must be missing something in this "discussion" concept. So it goes like
this: "I will make a patch and commit" - "No, please don't, it is not good!"
- argument, argument, tons of explanations why it's not good - "OK, no need
to argue, I will make patch and commit". Why bother?
--
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,
Hi!
So, I really would like to revert that foward_static_call stuff and
implement the parent:: patch instead, while it's still possible.thoughts?
Didn't we discuss that already? Adding magic to parent:: is not a good
idea, it's very basic language construct and should work simple. LSB is
an advanced feature, which probably would be used deep inside library guts
and thus can use more elaborate syntax.
It seems natural to think of LSB as a language feature, and so it
doesn't feel right to have it partly implemented as a keyword, and
then fix the problematic part as function.
We already see how call_user_func is painful to use (i.e. with methods
that use references), that same burden will be put on
forward_static_call.
On top of that, by making parent:: forward called class name, you remove
the possibility of doing non-forwarding call to the parent class.
Why would that be no longer possible ? If you want to make a
non-forwarding call to the parent class, you can use
TheParentClassName::foo();.
As for it being slow - how slow it is? Does it really so slow that it
makes real-life application that otherwise would be fast to be slow? Or
it's just "couple more CPU cycles" slow? I suspect the latter - and thus
I don't think speed optimizations belong there.
It's about 85% slower than a direct call. Sure it's not that slow when
measuring absolutely, but we're talking about a feature that will be
typically used in frameworks and libraries, so the amount of calls may
be quite big.
--
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
Etienne Kneuss schreef:
Hello,
Hi!
So, I really would like to revert that foward_static_call stuff and
implement the parent:: patch instead, while it's still possible.thoughts?
Didn't we discuss that already? Adding magic to parent:: is not a good
idea, it's very basic language construct and should work simple.
yes!
LSB is
an advanced feature, which probably would be used deep inside library guts
and thus can use more elaborate syntax.
like static::foo() or if you're really feeling brave fix 'self' so that
it does LSB like it 'should' have done from the start.
It seems natural to think of LSB as a language feature, and so it
doesn't feel right to have it partly implemented as a keyword, and
then fix the problematic part as function.
We already see how call_user_func is painful to use (i.e. with methods
that use references), that same burden will be put on
forward_static_call.
and ironically call_user_func*() is quite often used in hacks that work
round the lack of LSB. forward_static_call()
would relegate LSB to a second
rate feature, whilst 'comparable' languages treat it as a core OO feature.
I know that other languages are not the measure of things, but in the case of
LSB I believe it should be a first class feature of an OO language.
On top of that, by making parent:: forward called class name, you remove
the possibility of doing non-forwarding call to the parent class.Why would that be no longer possible ? If you want to make a
non-forwarding call to the parent class, you can use
TheParentClassName::foo();.
I certainly don't expect 'parent' to end up making a call to a method
defined in a sub-class.
Also don't we use 'parent' for much the same reason we use '__construct' ?
i.e. so we don't need to know which class is actually the parent defining
the requested method.
rewriting parent::meth() into parentClassName::meth() is like rewriting
class Foo {function __construct() {}} into class Foo {function Foo() {}}
no?
please reconsider a either a new explicit keyword (e.g. 'static') or even
making 'self' LSB. I doubt much code would be affected if the semantics of
'self' changed.
another possibility is the keyword 'child', fits in nicely with 'parent'
and 'self' and describes nicely where in the class hierarchy a search
for the method/property will begin.
As for it being slow - how slow it is? Does it really so slow that it
makes real-life application that otherwise would be fast to be slow? Or
it's just "couple more CPU cycles" slow? I suspect the latter - and thus
I don't think speed optimizations belong there.It's about 85% slower than a direct call. Sure it's not that slow when
measuring absolutely, but we're talking about a feature that will be
typically used in frameworks and libraries, so the amount of calls may
be quite big.--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hello,
Etienne Kneuss schreef:
Hello,
Hi!
So, I really would like to revert that foward_static_call stuff and
implement the parent:: patch instead, while it's still possible.thoughts?
Didn't we discuss that already? Adding magic to parent:: is not a good
idea, it's very basic language construct and should work simple.yes!
LSB is
an advanced feature, which probably would be used deep inside library
guts
and thus can use more elaborate syntax.like static::foo() or if you're really feeling brave fix 'self' so that
it does LSB like it 'should' have done from the start.
changing self:: is not an option as it would break BC.
It seems natural to think of LSB as a language feature, and so it
doesn't feel right to have it partly implemented as a keyword, and
then fix the problematic part as function.
We already see how call_user_func is painful to use (i.e. with methods
that use references), that same burden will be put on
forward_static_call.and ironically call_user_func*() is quite often used in hacks that work
round the lack of LSB.forward_static_call()
would relegate LSB to a second
rate feature, whilst 'comparable' languages treat it as a core OO feature.I know that other languages are not the measure of things, but in the case
of
LSB I believe it should be a first class feature of an OO language.On top of that, by making parent:: forward called class name, you remove
the possibility of doing non-forwarding call to the parent class.Why would that be no longer possible ? If you want to make a
non-forwarding call to the parent class, you can use
TheParentClassName::foo();.I certainly don't expect 'parent' to end up making a call to a method
defined in a sub-class.Also don't we use 'parent' for much the same reason we use '__construct' ?
i.e. so we don't need to know which class is actually the parent defining
the requested method.rewriting parent::meth() into parentClassName::meth() is like rewriting
class Foo {function __construct() {}} into class Foo {function Foo() {}}no?
not really, for now, parent is simply an alias of the parent class.
please reconsider a either a new explicit keyword (e.g. 'static') or even
making 'self' LSB. I doubt much code would be affected if the semantics of
'self' changed.another possibility is the keyword 'child', fits in nicely with 'parent'
and 'self' and describes nicely where in the class hierarchy a search
for the method/property will begin.
static::foo() is already implemented in HEAD and 5_3, it references
the class found with runtime information.
child is not a good keyword as LSB may not be to the direct child, it
can go through multiple childs in the inheritance branch, or it can
also reference the current class if no fallbacks occurred.
As for it being slow - how slow it is? Does it really so slow that it
makes real-life application that otherwise would be fast to be slow? Or
it's just "couple more CPU cycles" slow? I suspect the latter - and thus
I don't think speed optimizations belong there.It's about 85% slower than a direct call. Sure it's not that slow when
measuring absolutely, but we're talking about a feature that will be
typically used in frameworks and libraries, so the amount of calls may
be quite big.--
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
Etienne Kneuss schreef:
Hello,
Etienne Kneuss schreef:
Hello,
Hi!
So, I really would like to revert that foward_static_call stuff and
implement the parent:: patch instead, while it's still possible.thoughts?
Didn't we discuss that already? Adding magic to parent:: is not a good
idea, it's very basic language construct and should work simple.
yes!LSB is
an advanced feature, which probably would be used deep inside library
guts
and thus can use more elaborate syntax.
like static::foo() or if you're really feeling brave fix 'self' so that
it does LSB like it 'should' have done from the start.changing self:: is not an option as it would break BC.
and the same is not true of parent::? besides which I doubt any same code
would actually break if the semantics of self:: changed, much less than
if parent:: changed at any rate.
It seems natural to think of LSB as a language feature, and so it
doesn't feel right to have it partly implemented as a keyword, and
then fix the problematic part as function.
We already see how call_user_func is painful to use (i.e. with methods
that use references), that same burden will be put on
forward_static_call.
and ironically call_user_func*() is quite often used in hacks that work
round the lack of LSB.forward_static_call()
would relegate LSB to a second
rate feature, whilst 'comparable' languages treat it as a core OO feature.I know that other languages are not the measure of things, but in the case
of
LSB I believe it should be a first class feature of an OO language.On top of that, by making parent:: forward called class name, you remove
the possibility of doing non-forwarding call to the parent class.
Why would that be no longer possible ? If you want to make a
non-forwarding call to the parent class, you can use
TheParentClassName::foo();.
I certainly don't expect 'parent' to end up making a call to a method
defined in a sub-class.Also don't we use 'parent' for much the same reason we use '__construct' ?
i.e. so we don't need to know which class is actually the parent defining
the requested method.rewriting parent::meth() into parentClassName::meth() is like rewriting
class Foo {function __construct() {}} into class Foo {function Foo() {}}no?
not really, for now, parent is simply an alias of the parent class.
but certainly not an alias for any child class.
please reconsider a either a new explicit keyword (e.g. 'static') or even
making 'self' LSB. I doubt much code would be affected if the semantics of
'self' changed.another possibility is the keyword 'child', fits in nicely with 'parent'
and 'self' and describes nicely where in the class hierarchy a search
for the method/property will begin.static::foo() is already implemented in HEAD and 5_3, it references
the class found with runtime information.child is not a good keyword as LSB may not be to the direct child, it
can go through multiple childs in the inheritance branch, or it can
also reference the current class if no fallbacks occurred.
I understand that, the same is true for self:: and parent:: in that they
go though multiple ancestors (starting at the current class for self::) in
the anscetral inheritance branch, so I find the argument against 'child' weak,
but at the same time not important. I can live with anyname one cares to give
it.
Is this whole discussion pointless? given that you say 'static' has already been
implemented ... doesn't that negate the requirement for forward_static_call()
and
also the need to repurpose parent::?
As for it being slow - how slow it is? Does it really so slow that it
makes real-life application that otherwise would be fast to be slow? Or
it's just "couple more CPU cycles" slow? I suspect the latter - and thus
I don't think speed optimizations belong there.
It's about 85% slower than a direct call. Sure it's not that slow when
measuring absolutely, but we're talking about a feature that will be
typically used in frameworks and libraries, so the amount of calls may
be quite big.--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
and the same is not true of parent::? besides which I doubt any same code
would actually break if the semantics of self:: changed, much less than
if parent:: changed at any rate.
The behavior of the parent:: as it relates to "existing" code is not
changing. The only change of behavior is as it relates to the usage of
static:: when parent:: is called on a method. That is why making this
decision is now. Once 5.3 is released the behavior of parent:: will be
locked in much the same way self:: was in 5.0
Is this whole discussion pointless? given that you say 'static' has already
been
implemented ... doesn't that negate the requirement for
forward_static_call()
and
also the need to repurpose parent::?
static:: has been implemented for quite some time and the reason why
forward_static_call was created and the reason why we want to change
parent:: have been discussed at some length on this list. I'm mildly
suprised you haven't seen it.
Try reading:
http://www.digitalsandwich.com/archives/65-Late-static-binding....sorta.htmlIt
gives a pretty good description of what I disagreed with in the
current
patch. Then
http://www.ds-o.com/archives/68-Late-Static-Binding-Changes-to-parent.htmlintroduces
three patches to potentially resolve my issues. The three patches
are really standalone (save a mistake I made when creating the forwarding
patch that caused me to include forward_static_call()
). forward_static_call
patch has been implemented already. While this addresses my concerns I think
it does so in a far less than optimal way. The first patch is what Etienne
is talking about implementing which I am totally in favor for. The second
patch is really is the same as the first, it just introduces a new keyword
(which I do not think is needed.)
Hi!
It seems natural to think of LSB as a language feature, and so it
doesn't feel right to have it partly implemented as a keyword, and
then fix the problematic part as function.
There's nothing wrong with functions - call_user_* are functions too,
and func_get_args()
, etc.
We already see how call_user_func is painful to use (i.e. with methods
that use references), that same burden will be put on
forward_static_call.
If we have problem with using call_user_* with references, that should
be fixed (do we have description of what exactly is missing - like bug
report or RFC or something?) But it won't be fixed by changing parent::,
so how it's relevant here?
Why would that be no longer possible ? If you want to make a
non-forwarding call to the parent class, you can use
TheParentClassName::foo();.
Why having parent:: at all then? You could always use the class name,
right? But for some reason we do have parent:: - and that reason is that
using explicit class name is not a good style in this context, it both
obscures the intent and makes unnecessary dependencies in the code. Now
imagine on top of that we have name:: and parent:: work differently, so
you don't have choice but using name:: for certain things.
It's about 85% slower than a direct call. Sure it's not that slow when
measuring absolutely, but we're talking about a feature that will be
typically used in frameworks and libraries, so the amount of calls may
be quite big.
I do not think extra CPU instruction or two is really the factor here.
We are talking about high-level language, not assembly language.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hello,
Hi!
It seems natural to think of LSB as a language feature, and so it
doesn't feel right to have it partly implemented as a keyword, and
then fix the problematic part as function.There's nothing wrong with functions - call_user_* are functions too, and
func_get_args()
, etc.
Sure, there are nothing wrong with functions, my point is that LSB is
implemented partly with a keyword and partly with a function. Which is
IMO a bad idea. Why use static:: in the first place ? We could have
used call_called_class_method("method"), oh right: it's ugly as hell.
We already see how call_user_func is painful to use (i.e. with methods
that use references), that same burden will be put on
forward_static_call.If we have problem with using call_user_* with references, that should be
fixed (do we have description of what exactly is missing - like bug report
or RFC or something?) But it won't be fixed by changing parent::, so how
it's relevant here?
sure, the "fix" is
$args = array($byval, &$byref);
forward_static_call_array(array('parent', 'foo'), $args);
instead of:
parent::foo($byval, $byref);
I guess its quite obvious to see which way will be prefered.
Why would that be no longer possible ? If you want to make a
non-forwarding call to the parent class, you can use
TheParentClassName::foo();.Why having parent:: at all then? You could always use the class name, right?
But for some reason we do have parent:: - and that reason is that using
explicit class name is not a good style in this context, it both obscures
the intent and makes unnecessary dependencies in the code. Now imagine on
top of that we have name:: and parent:: work differently, so you don't have
choice but using name:: for certain things.
yes parent:: is convenient, that's why it's there.
Here is the possible scenarios:
- you don't use any LSB in your static method => you use parent::
without caring - you use LSB in the method of the parent class, and you need to
overwrite that static method, but still call it from the child method,
2.1) you use parent:: as usual
2.2) you need to lie to the parent class by telling that the method
was directly called.
Now, 2.1 seems to be oviously more frequent than 2.2. I can't even
think of a decent reason to need 2.2 (do you have any example of
"certain things" ?). Which means that when the difference between
parent:: and ParentClassName:: is relevant, parent:: will be used more
often.
Additionally, forward_static_call allows to do calls to unrelated
methods, (without passing the caller info) which increases the WTF
factor. parent::foo on the other hand is well defined.
It's about 85% slower than a direct call. Sure it's not that slow when
measuring absolutely, but we're talking about a feature that will be
typically used in frameworks and libraries, so the amount of calls may
be quite big.I do not think extra CPU instruction or two is really the factor here. We
are talking about high-level language, not assembly language.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
Hi Stas,
Am Montag, den 23.06.2008, 09:57 -0700 schrieb Stanislav Malyshev:
[...]
Why having parent:: at all then? You could always use the class name,
right? But for some reason we do have parent:: - and that reason is
that using explicit class name is not a good style in this context, it
both obscures the intent and makes unnecessary dependencies in the
code. Now imagine on top of that we have name:: and parent:: work
differently, so you don't have choice but using name:: for certain
things.
An wide-spreaded usage example for non-forwarding calls is? I would
estimate, that in 70% percent, it doesn't matter, what kind of call
strategy is choosen, 29% percent will be forwarding calls and only 1%
are non-forwarding.
cu, Lars
On Monday 23 June 2008 3:21:54 pm Lars Strojny wrote:
Hi Stas,
Am Montag, den 23.06.2008, 09:57 -0700 schrieb Stanislav Malyshev:
[...]Why having parent:: at all then? You could always use the class name,
right? But for some reason we do have parent:: - and that reason is
that using explicit class name is not a good style in this context, it
both obscures the intent and makes unnecessary dependencies in the
code. Now imagine on top of that we have name:: and parent:: work
differently, so you don't have choice but using name:: for certain
things.An wide-spreaded usage example for non-forwarding calls is? I would
estimate, that in 70% percent, it doesn't matter, what kind of call
strategy is choosen, 29% percent will be forwarding calls and only 1%
are non-forwarding.cu, Lars
I implemented a task-specific ORM last fall where the lack of late static
binding really bit me, resulting in the need to duplicate code. I'll see
about sending it to the list tomorrow from work as a practice example we can
kick around. :-) (At least I think it's an LSB issue; if it isn't, I'm sure
I'll get flamed for being off topic. <g>)
--
Larry Garfield
larry@garfieldtech.com
Didn't we discuss that already?
It was discussed but there was never any kind of agreement nor was there
ever any kind of vote. The only reason the discussion stopped is that I
wanted to be sure SOME way of forwarding the called name was in 5.3 core. I
am fairly confident that when it comes right down to it you are in the
minority in this opinion about parent and that combined with the fact that
there was never any kind of vote (that I am aware of) is enough to warrant
bringing up this discussion again.
Adding magic to parent:: is not a good
idea, it's very basic language construct and should work simple. LSB is
an advanced feature, which probably would be used deep inside library guts
and thus can use more elaborate syntax.
On top of that, by making parent:: forward called class name, you remove
the possibility of doing non-forwarding call to the parent class.
The possibility is not removed. You can always call the parent class
explicitly. Hell, we could always right a function to call parent methods
without forwarding tihe called class :P.
As for it being slow - how slow it is? Does it really so slow that it
makes real-life application that otherwise would be fast to be slow? Or
it's just "couple more CPU cycles" slow? I suspect the latter - and thus
I don't think speed optimizations belong there.
I agree with you in that I don't think the speed really matters much in this
case (though maybe I am wrong?). I am looking at this issue purely from the
usability and expectation standpoint.
--
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
Hi Etienne,
Am Freitag, den 20.06.2008, 18:04 +0200 schrieb Etienne Kneuss:
[...]
- parent:: carries the info while ParentClassName:: doesn't
- convenient
- no functionnality lost
- introduces a difference between parent:: and classname::, but
restricted to LSB so no BC break
Thanks for bringing this on topic again. I would like to see 2)
implemented, as the current behaviour looks unpredictable to strangers.
Stas, you argued, that non-forward static calls would no longer be
possible? Doesn't the con argument in Etiennes list solve that issue or
do I miss something? If you want non-forwarding calls, use
<classname>::method()?
cu, Lars
To sum up key points about each possibilities:
- forward_static_call
- no need to affect the engine
- slow, painful
- parent:: carries the info while ParentClassName:: doesn't
- convenient
- no functionnality lost
- introduces a difference between parent:: and classname::, but
restricted to LSB so no BC breakIt really seems like (2) is the most PHP way of doing things, while
(1) is more of a hack that we will regret later.
I'd go for 2 too.
regards,
Derick
--
Derick Rethans
http://derickrethans.nl | http://ezcomponents.org | http://xdebug.org