All,
I have created a new draft RFC implementing function and constant
autoloading in master:
https://wiki.php.net/rfc/function_autoloading
All feedback is welcome.
Thanks
Anthony
Hi!
I have created a new draft RFC implementing function and constant
autoloading in master:https://wiki.php.net/rfc/function_autoloading
All feedback is welcome.
I think it is an unnecessary complication. Classes fit autoloader
paradigm nicely, since the usual pattern is one class per one file
(actually recommended in PSR), so it is easy to establish one-to-one
automatic mapping between classes and files (also recommended in the
PSR). But for functions nobody does this. This means that to implement
function autoloader one will need to have a complicated and fragile
logic (since there's no way to ensure this logic would be in sync with
actual content of files containing multiple functions).
Moreover, since this replaces a simple hash lookup with additional two
function calls (and also other operations included in those) everywhere
in the engine, it will also have performance impact of one of the most
frequently used operations in the engine - function calls - while
providing absolutely no benefit for 100% of existing code and 99.99% of
future code.
Putting autoloading of different entities into one function makes very
little sense to me - why would the same code load both classes and
functions? How would it do that besides ugly switch that just stuffs two
completely different logic pieces into one function for no reason? The
example given in the RFC is certainly not what anybody would actually
want their autoloaders to do, so I fail to see any case for doing it and
for putting loading more than one entity into one function (that given
that autoloading function would be desirable at all, which it still
doesn't seem so for me).
It is
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
It is
Oops, clicked too soon. I wanted to conclude that I think it is too many
complications in the engine for too little gain.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
It is
Oops, clicked too soon. I wanted to conclude that I think it is too many
complications in the engine for too little gain.
I agree with Stas here.
thanks
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227--
--
Laruence Xinchen Hui
http://www.laruence.com/
I think it is an unnecessary complication. Classes fit autoloader
paradigm nicely, since the usual pattern is one class per one file
(actually recommended in PSR), so it is easy to establish one-to-one
automatic mapping between classes and files (also recommended in the
PSR). But for functions nobody does this. This means that to implement
function autoloader one will need to have a complicated and fragile
logic (since there's no way to ensure this logic would be in sync with
actual content of files containing multiple functions).I disagree on the basis that namespaced functions/constants do fit the
same autoloading paradigm.
Moreover, since this replaces a simple hash lookup with additional two
function calls (and also other operations included in those) everywhere
in the engine, it will also have performance impact of one of the most
frequently used operations in the engine - function calls - while
providing absolutely no benefit for 100% of existing code and 99.99% of
future code.Those function calls would only kick in if the function/constant wasn't
already defined, which will be the exception case, so perf isn't a strong
argument.
Putting autoloading of different entities into one function makes very
little sense to me - why would the same code load both classes and
functions? How would it do that besides ugly switch that just stuffs two
completely different logic pieces into one function for no reason? The
example given in the RFC is certainly not what anybody would actually
want their autoloaders to do, so I fail to see any case for doing it and
for putting loading more than one entity into one function (that given
that autoloading function would be desirable at all, which it still
doesn't seem so for me).That I agree with 100%.
-Sara
Hi!
I disagree on the basis that namespaced functions/constants do fit the
same autoloading paradigm.
If they're already namespaced, what prevents one to put it in a class
and use good old PSR-compatible loading?
Those function calls would only kick in if the function/constant wasn't
already defined, which will be the exception case, so perf isn't a
strong argument.
Not according to the code I see in the patch. There I see 2 func calls
(among other things) before the hash is even looked up.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
If they're already namespaced, what prevents one to put it in a class
and use good old PSR-compatible loading?Nothing, really... Just countering your specific premise.
Those function calls would only kick in if the function/constant wasn't
already defined, which will be the exception case, so perf isn't a
strong argument.Not according to the code I see in the patch. There I see 2 func calls
(among other things) before the hash is even looked up.Well, the patch needs work obviously. I'm living in a magical world where
that's already been fixed. :)
-Sara
2013/8/30 Stas Malyshev smalyshev@sugarcrm.com
Hi!
I disagree on the basis that namespaced functions/constants do fit the
same autoloading paradigm.If they're already namespaced, what prevents one to put it in a class
and use good old PSR-compatible loading?
Well, static methods aren't the same as functions.
Those function calls would only kick in if the function/constant wasn't
already defined, which will be the exception case, so perf isn't a
strong argument.Not according to the code I see in the patch. There I see 2 func calls
(among other things) before the hash is even looked up.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227--
Hi!
Well, static methods aren't the same as functions.
The big difference being?
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
On Fri, Aug 30, 2013 at 7:10 PM, Stas Malyshev smalyshev@sugarcrm.comwrote:
Hi!
Well, static methods aren't the same as functions.
The big difference being?
This seems to be the core of your argumentation in this thread: "Why don't
you just use Foo::bar() instead of foo\bar()?"
In which case, I wonder why we have functions at all. We could just use
static methods instead after all. Maybe we should deprecate function
support?
On a more serious note: If you want an actual example of how functions can
be easier to use than static methods, consider the "use function" RFC. Now
that it's in, it is possible to directly import a function foo\bar() and
use it with just bar(). Static methods allow no such thing. You always need
to write the class name.
The reason why people currently resort to using static methods instead of
functions is the fact that there is no autoloading for functions. With
autoloading, functions become a lot easier to use.
Nikita
Hi!
This seems to be the core of your argumentation in this thread: "Why
don't you just use Foo::bar() instead of foo\bar()?"In which case, I wonder why we have functions at all. We could just use
static methods instead after all. Maybe we should deprecate function
support?
Maybe we should stop strawman arguments? I never claimed functions
should be replaced with static methods or that we should deprecate
anything, please don't put words in my mouth.
What I claimed is that if you write code in a specific pattern, that
is the only pattern that makes this proposal useful and that is, as far
as I can see, in no way common among people that use functions, then in
this specific case you could as well use slightly different pattern
which would allow you to use existing facilities, and the only
difference between the two is the word "class" and using :: instead of .
On a more serious note: If you want an actual example of how functions
can be easier to use than static methods, consider the "use function"
RFC. Now that it's in, it is possible to directly import a function
foo\bar() and use it with just bar(). Static methods allow no such
thing. You always need to write the class name.
Which is a good thing. Making different thing mean the same is not a
good idea, it reduces readability. And typing 2 characters less was
never a priority.
The reason why people currently resort to using static methods instead
of functions is the fact that there is no autoloading for functions.
With autoloading, functions become a lot easier to use.
I don't accept this "resort to" - static functions is not something that
one should "resort to", it is a completely valid syntactic construct.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
So you say you will create a file for every function you want to support autoloading?
As I already asked, tell us about realworld use case, for example where this could improve say big projects like Symfony or ZF.
There is no logic to add this functionality just because we can.
kindly,
nvartolomei
On Fri, Aug 30, 2013 at 7:10 PM, Stas Malyshev <smalyshev@sugarcrm.com (mailto:smalyshev@sugarcrm.com)>wrote:
Hi!
Well, static methods aren't the same as functions.
The big difference being?
This seems to be the core of your argumentation in this thread: "Why don't
you just use Foo::bar() instead of foo\bar()?"In which case, I wonder why we have functions at all. We could just use
static methods instead after all. Maybe we should deprecate function
support?On a more serious note: If you want an actual example of how functions can
be easier to use than static methods, consider the "use function" RFC. Now
that it's in, it is possible to directly import a function foo\bar() and
use it with just bar(). Static methods allow no such thing. You always need
to write the class name.The reason why people currently resort to using static methods instead of
functions is the fact that there is no autoloading for functions. With
autoloading, functions become a lot easier to use.Nikita
2013/8/31 Vartolomei Nicolae nvartolomei@gmail.com
So you say you will create a file for every function you want to support
autoloading?
I already have create files for functions of a namespace... Closed
source.
As I already asked, tell us about realworld use case, for example where
this could improve say big projects like Symfony or ZF.
Not everything can be found in the 5 most popular frameworks.
There is no logic to add this functionality just because we can.
The lack of logic is: Why is it actually missing?
- Classes: Triggers an autoloader
- Functions: Needs manual handling
- Constants: Needs manual handling
That is at first inconsistent. The need of "require_once"s is inefficient
and error prone.
Regards,
Sebastian
kindly,
nvartolomeiOn Fri, Aug 30, 2013 at 7:10 PM, Stas Malyshev <smalyshev@sugarcrm.com(mailto:
smalyshev@sugarcrm.com)>wrote:Hi!
Well, static methods aren't the same as functions.
The big difference being?
This seems to be the core of your argumentation in this thread: "Why
don't
you just use Foo::bar() instead of foo\bar()?"In which case, I wonder why we have functions at all. We could just use
static methods instead after all. Maybe we should deprecate function
support?On a more serious note: If you want an actual example of how functions
can
be easier to use than static methods, consider the "use function" RFC.
Now
that it's in, it is possible to directly import a function foo\bar() and
use it with just bar(). Static methods allow no such thing. You always
need
to write the class name.The reason why people currently resort to using static methods instead of
functions is the fact that there is no autoloading for functions. With
autoloading, functions become a lot easier to use.Nikita
I already have create files for functions of a namespace... Closed source.
Can we take a look at them as an example? Maybe we can give you some advice
how to refactor this code :)
Not everything can be found in the 5 most popular frameworks.
Sure, but best practices usually are found there.
The lack of logic is: Why is it actually missing?
Why humans don’t have one leg more, on head?
I really want to look at an example for this. Looks like you are the only one who needs this.
Oh, is OOP that bad for you? Also constant autoloading looks so bad, I want to see an example of this too for sure.
Please don’t consider these questions like you need to prove something to me,
I’m asking them hoping that anwers will help all internals to understand problem you are trying to solve.
kindly,
nvartolomei
The lack of logic is: Why is it actually missing?
Why humans don’t have one leg more, on head?I really want to look at an example for this. Looks like you are the only
one who needs this.Oh, is OOP that bad for you? Also constant autoloading looks so bad, I
want to see an example of this too for sure.Please don’t consider these questions like you need to prove something to
me,
I’m asking them hoping that anwers will help all internals to understand
problem you are trying to solve.
the function (and constant) autoloading was brought up on the list numerous
times, so I don't think that you can say things like he is the only one in
the need of this.
php is a multiparadigm programing language, and usually you can do
everything in procedural code that you would be able to do with oop code in
php.
except the autoloading, which for some people is an oop-only feature, so
makes no sense to provide for procedural code, while for some other people
thinks that the idea of autoloading makes no sense for functions/constants
as there is no 1:1 mapping between files and autoloader calls.
personally Ithink it would be nice if we could provide a way for
const/function autoloading.
--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
personally Ithink it would be nice if we could provide a way for const/function autoloading.
So you will create files for constants? One file with a single line defining a constant?
Did I understood something wrong?
kindly,
nvartolomei
On Sun, Sep 1, 2013 at 12:36 AM, Vartolomei Nicolae
nvartolomei@gmail.com wrote:
personally Ithink it would be nice if we could provide a way for const/function autoloading.
So you will create files for constants? One file with a single line defining a constant?Did I understood something wrong?
kindly,
nvartolomei
Hi,
Yes, you understood it wrong. You can have one function / const in a
file if you want, but you can also have a bunch of them in a file
like you have today with classes. And from what I read in the RFC,
someone else who read it could confirm if I'm right or wrong, there's
no mandatory function / file to use this so you can use it like the
current autoloader for classes is working.
This will be optional to use, like the current autoloader, which is
why we don't have PSR-0 in Core (maybe we should have a thread about
this sooner or later) and I've had plenty of use cases for a feature
like this. Who knows, maybe we'll have PSR-Y Autoload Reloaded which
will cover this as well :)
Like it has been pointed out already, it also allows the language to
be complete in what's offering and help some users along the way.
Do you, or anyone else, have a real reason to be against this rather that:
- I don't like it
- I don't/won't use it
- why do we need it?
- it doesn't belong to the language
- etc.
So, my opinion as a PHP user is that it's a nice addition to the
language and even if I won't use it, as long as it won't affect the
global performance, I can live with it.
Regards,
Florin
Florin Patan
https://github.com/dlsniper
http://www.linkedin.com/in/florinpatan
All,
There has been a lot of discussion unto the merit of this feature. That's
fine.
What I'd really like to know before proposing this is what can be improved
in this RFC.
For example: someone (Stas) brought up that it was weird that all three
types (Class, Function, Constant) are served by a single register function
(and multiple can be served by a single autoloader). Personally, I see this
as a significant simplification advantage, but I can see if others don't.
If you don't, can we please try to ideate around coming up with a better
syntax?
Another example: I've received a lot of feedback that using the "php" root
namespace is weird and unexpected. Does anyone agree? Should that be
changed prior to proposing this feature?
Let's try to improve this RFC to be the best it can prior to proposing and
voting. Even if you don't think it's necessary, there are surely things you
think can be improved (and hence everyone wins).
Thanks
Anthony
On Sun, Sep 1, 2013 at 12:36 AM, Vartolomei Nicolae
nvartolomei@gmail.com wrote:personally Ithink it would be nice if we could provide a way for
const/function autoloading.
So you will create files for constants? One file with a single line
defining a constant?Did I understood something wrong?
kindly,
nvartolomeiHi,
Yes, you understood it wrong. You can have one function / const in a
file if you want, but you can also have a bunch of them in a file
like you have today with classes. And from what I read in the RFC,
someone else who read it could confirm if I'm right or wrong, there's
no mandatory function / file to use this so you can use it like the
current autoloader for classes is working.This will be optional to use, like the current autoloader, which is
why we don't have PSR-0 in Core (maybe we should have a thread about
this sooner or later) and I've had plenty of use cases for a feature
like this. Who knows, maybe we'll have PSR-Y Autoload Reloaded which
will cover this as well :)Like it has been pointed out already, it also allows the language to
be complete in what's offering and help some users along the way.Do you, or anyone else, have a real reason to be against this rather that:
- I don't like it
- I don't/won't use it
- why do we need it?
- it doesn't belong to the language
- etc.
So, my opinion as a PHP user is that it's a nice addition to the
language and even if I won't use it, as long as it won't affect the
global performance, I can live with it.Regards,
FlorinFlorin Patan
https://github.com/dlsniper
http://www.linkedin.com/in/florinpatan
All,
There has been a lot of discussion unto the merit of this feature. That's
fine.What I'd really like to know before proposing this is what can be improved
in this RFC.For example: someone (Stas) brought up that it was weird that all three
types (Class, Function, Constant) are served by a single register function
(and multiple can be served by a single autoloader). Personally, I see this
as a significant simplification advantage, but I can see if others don't.
If you don't, can we please try to ideate around coming up with a better
syntax?
I think adding two different functions and maintaining the general one
could be the way to go in this case.
The function names might look like this:
- spl_register_autoloader -> autoloader for everything
- spl_register_function_autoloader -> autoloader for functions/consts
- spl_register_class_autoloader -> current autoloader for classes only
Thinking on how PSRs work, one might register one autoloader for
classes and if they don't use any function/constant autoloading then
they don't need to take care of supporting them in the autoloader.
When a new PSR for function/constat autoloading will appear, that
loader could be registered to it's own
'spl_register_function_autoloader()'. If there'll be a special PSR
that covers both then that loader will need to call
'spl_register_autoloader()' and that's it.
I'm sure the names could be improved.
Another example: I've received a lot of feedback that using the "php" root
namespace is weird and unexpected. Does anyone agree? Should that be
changed prior to proposing this feature?
Could we have something like the global namespace for classes where
'' is the default namespace?
Or maybe alias php\ to \ namespace auto-magically?
Let's try to improve this RFC to be the best it can prior to proposing and
voting. Even if you don't think it's necessary, there are surely things you
think can be improved (and hence everyone wins).Thanks
Anthony
Those are the idea that I have in regards to this RFC. Hope they help.
Kind regards,
Florin Patan
https://github.com/dlsniper
http://www.linkedin.com/in/florinpatan
Hi!
The function names might look like this:
- spl_register_autoloader -> autoloader for everything
Given we already have spl_autoload_register that'd be pretty confusing.
Also, we usually name functions in increasing order of specificity (i.e.
spl_autoload_call/spl_autoload_spl_autoload_functions, not
spl_call_autoloader and spl_give_me_list_of_autoload_functions).
- spl_register_function_autoloader -> autoloader for functions/consts
- spl_register_class_autoloader -> current autoloader for classes only
Or maybe alias php\ to \ namespace auto-magically?
Nope. \ namespace is root namespace, it can not be magically aliased to
anything and should not be.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
My previous message didn't push the point I wanted raise: don't we have a
major problem related to at-run-time namespace resolution for functions and
constants?
Take this code: namespace foo { strlen("bar"); }
Will you trigger an autoload for foo\strlen?
I believe not because that would hurt performance too much.
But then, how will you load function foo\strlen if it exists?
Now take this code: namespace foo { bar(); }
Will you trigger autoload for "foo\bar" first, then for "bar"?
Only for "foo\bar"? But then, what if "bar" exists and just waits being
autoloaded?
I fail to see how autoloading functions is compatible with at-run-time
namespace resolution.
Nicolas,
On Sun, Sep 1, 2013 at 11:27 AM, Nicolas Grekas <
nicolas.grekas+php@gmail.com> wrote:
My previous message didn't push the point I wanted raise: don't we have a
major problem related to at-run-time namespace resolution for functions and
constants?Take this code: namespace foo { strlen("bar"); }
Will you trigger an autoload for foo\strlen?
I believe not because that would hurt performance too much.
But then, how will you load function foo\strlen if it exists?Now take this code: namespace foo { bar(); }
Will you trigger autoload for "foo\bar" first, then for "bar"?
Only for "foo\bar"? But then, what if "bar" exists and just waits being
autoloaded?I fail to see how autoloading functions is compatible with at-run-time
namespace resolution.
So, here's how it works, by example:
namespace foo {
use function biz\buz;
use foo\bar;
something(); // autoloaded as "something"
buz(); // autoloaded as "biz\buz"
bar\baz(); // autoloaded as "foo\bar\baz"
\load\execute(); // autoloaded as "load\execute"
}
So basically, if the call uses "fallback" resolution, the autoload is only
attempted at the global resolution.
Does that make sense?
Anthony
Hi!
namespace foo {
use function biz\buz;
use foo\bar;something(); // autoloaded as "something"
Wait, so it wouldn't work like class autoloader, using fully qualified
name? And autoloader would not then have any information about
namespaces, so you'd have to specify explicit imports or full namespace
names for any namespaced functions you use in your code?
That doesn't sound very practical. It's much easier to do one require
than to import manually each function in the namespace and requiring to
explicitly name all of them removes half of the usefulness of namespaces
- if you wanted all the full names, you could use
very_long_names_like_this() as before.
I think we discussed all these problems last time function autoloading
topic came up.
Also it is weird that namespace name is added to bar\baz() but not to
bar(). This is contrary to how namespaces work in other places - where
namespace name is added to everything not fully quailified.
Does that make sense?
Frankly, for me it doesn't. Now I recall namespaces resolution and
fallbacks was one of the reasons why function autoloading proposal
failed the last time. IMHO this is a pretty big problem for practical
usage of this - as pretty much the only case for function autoloading is
resting on namespaces, so if autoloader can't deal with namespaced
resolution rules, it's not good.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Stas,
namespace foo {
use function biz\buz; use foo\bar; something(); // autoloaded as "something"
Wait, so it wouldn't work like class autoloader, using fully qualified
name? And autoloader would not then have any information about
namespaces, so you'd have to specify explicit imports or full namespace
names for any namespaced functions you use in your code?
It indeed does work like the class loader in all but one case. When the
compiler knows what you're intending (via explicit use, relative or
absolute qualification), it can load the namespaced function.
The time it is different is when you don't use function
and just write
foo()
. With classes, this works fine, because there is no "fallback"
behavior. With functions, it can't, because it was decided long ago to
silently fall back to using a global function if this happens.
So the only case this effects is that you can't autoload a function from
the same namespace that you're currently in without explicitly using that
function.
That's not such a huge issue.
The bigger issue (for me) is that in 5.3+, you have code that means
different things depending on the state of the engine. In the example
above, that function call can mean "foo\something" or "something".
Having a function call that isn't obviously resolvable is...
But "fixing" that would be such a massive BC break...
That doesn't sound very practical. It's much easier to do one require
than to import manually each function in the namespace and requiring to
explicitly name all of them removes half of the usefulness of namespaces
- if you wanted all the full names, you could use
very_long_names_like_this() as before.
You would only need to explicitly use function
those in your current
namespace. Any outside (relative or absolute calls) would still work fine.
And after all, this is the exact reason we implemented use function
.
Because namespaces WERE useless for functions until last week. Now we have
the power to be explicit with our calls.
I think we discussed all these problems last time function autoloading
topic came up.Also it is weird that namespace name is added to bar\baz() but not to
bar(). This is contrary to how namespaces work in other places - where
namespace name is added to everything not fully quailified.
That's how functions (and namespaces) have always worked. Give it a try:
http://3v4l.org/S6FN8 Keep in mind, functions have been treated as second
class citizens in PHP since 5.3. They haven't played well with namespaces,
or autoloading. Today we've fixed half of that issue. This RFC attempts to
fix the other half.
Does that make sense?
Frankly, for me it doesn't. Now I recall namespaces resolution and
fallbacks was one of the reasons why function autoloading proposal
failed the last time. IMHO this is a pretty big problem for practical
usage of this - as pretty much the only case for function autoloading is
resting on namespaces, so if autoloader can't deal with namespaced
resolution rules, it's not good.
The big difference is that last time there was no mechanism to be explicit
with what you wanted your code to do without fully qualifying every call.
Today we have use function
.
Anthony
Hi!
So the only case this effects is that you can't autoload a function from
the same namespace that you're currently in without explicitly using
that function.That's not such a huge issue.
I think it is such a huge issue, because this means this functionality
can not be used for reliably loading namespaced functions without prior
declaration, and this is pretty much the use case we've been preached
about all along. So if it doesn't work in this case without prior
declarations just for it, than how it's better than require?
But "fixing" that would be such a massive BC break...
There's nothing to "fix", it was a conscious decision about how
namespaces must work. Alternative is doing \strlen each time you need
string length, which would be just silly.
You would only need to explicitly
use function
those in your current
namespace. Any outside (relative or absolute calls) would still work fine.
It's not "only" - functions in current namespace are exactly those I'm
likely to use.
And after all, this is the exact reason we implemented
use function
.
Because namespaces WERE useless for functions until last week. Now we
have the power to be explicit with our calls.
I don't think RFC proposed well before this issue was raised was
actually meant only to fix broken function autoloading proposal. I
sincerely hope it has more uses than that, otherwise it's a pretty big
mistake.
That's how functions (and namespaces) have always worked. Give it a
try: http://3v4l.org/S6FN8 Keep in mind, functions have been treated as
No it's not how it worked - function resolution rules were always "try
namespace, then global", unless alias is explicitly specified by use
(aliased name is treated as fully qualified, because this is what the
function of aliasing is). Just try to remove "use" statement and see.
The big difference is that last time there was no mechanism to be
explicit with what you wanted your code to do without fully qualifying
every call. Today we haveuse function
.
Which is the same specification, just at the beginning of the file. I'd
rather do one require then ten use functions. My opinion is producing
autoloader that is inconsistent with how language itself treats import
would only produce more WTFs and more people thinking nothing in PHP
makes sense and nobody cares about internal consistency of the language.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Stas,
On Mon, Sep 2, 2013 at 4:02 PM, Stas Malyshev smalyshev@sugarcrm.comwrote:
Hi!
So the only case this effects is that you can't autoload a function from
the same namespace that you're currently in without explicitly using
that function.That's not such a huge issue.
I think it is such a huge issue, because this means this functionality
can not be used for reliably loading namespaced functions without prior
declaration, and this is pretty much the use case we've been preached
about all along. So if it doesn't work in this case without prior
declarations just for it, than how it's better than require?
It doesn't need prior declaration. It needs either prior declaration or
qualification (absolute or relative). But more on that in a sec.
But "fixing" that would be such a massive BC break...
There's nothing to "fix", it was a conscious decision about how
namespaces must work. Alternative is doing \strlen each time you need
string length, which would be just silly.
So what your saying, if I understand you correctly, is that PHP was
intentionally designed to be non-deterministic? And it was designed that
way to save a single character?
To get why I think that's such a big deal, let's look at some sample code:
namespace Foo {
function test1($input) {
return strlen($input);
}
function test2($input) {
return strlen($input);
}
var_dump(test1("test")); // int(4)
// Simulate require
eval('namespace Foo { function strlen($input) { return 42; }}');
var_dump(test2("test")); // int(42)
var_dump(test1("test")); // int(4) on 5.4+, int(42) on 5.3
}
The eval is just there to simulate a require_once. Thanks to function
caching, NOTHING makes sense!!! http://3v4l.org/MMvFv
If you don't agree that behavior is wonky, then I'm not sure where else to
go.
You would only need to explicitly
use function
those in your current
namespace. Any outside (relative or absolute calls) would still work
fine.It's not "only" - functions in current namespace are exactly those I'm
likely to use.
Look at the code where you use classes. How many times to do use a class
from your current namespace vs another one. The code I've looked at tends
to favor other namespaces significantly...
And after all, this is the exact reason we implemented
use function
.
Because namespaces WERE useless for functions until last week. Now we
have the power to be explicit with our calls.I don't think RFC proposed well before this issue was raised was
actually meant only to fix broken function autoloading proposal. I
sincerely hope it has more uses than that, otherwise it's a pretty big
mistake.That's how functions (and namespaces) have always worked. Give it a
try: http://3v4l.org/S6FN8 Keep in mind, functions have been treated asNo it's not how it worked - function resolution rules were always "try
namespace, then global", unless alias is explicitly specified by use
(aliased name is treated as fully qualified, because this is what the
function of aliasing is). Just try to remove "use" statement and see.
It's only "try namespace, then global" in the case where there's no \
in
the function name. Compile code that does the check:
http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_compile.c#1938
The big difference is that last time there was no mechanism to be
explicit with what you wanted your code to do without fully qualifying
every call. Today we haveuse function
.Which is the same specification, just at the beginning of the file. I'd
rather do one require then ten use functions. My opinion is producing
autoloader that is inconsistent with how language itself treats import
would only produce more WTFs and more people thinking nothing in PHP
makes sense and nobody cares about internal consistency of the language.
Anthony
PS: I think it's ironic talking about internal consistency of a language in
the same reply where you justify "try namespace, then global" as a good
design feature. Just pointing that out...
Hi!
So what your saying, if I understand you correctly, is that PHP was
intentionally designed to be non-deterministic? And it was designed that
way to save a single character?
It is deterministic, there are rules for it, described in
http://us1.php.net/manual/en/language.namespaces.fallback.php. And it's
not to save single character, it is to save single character on hundreds
of thousands of function calls which otherwise all would have to be
rewritten. It's to prevent namespacing a code piece being equal to
rewriting every function call in it and making it extremely ugly on the
way.
The cost of if is that yes, if you want to override strlen (which still
escapes me why would you ever want to do something like that) you need
to load it first so the engine knows about it and resolves it correctly.
I think it is a very small cost compared to rewriting and uglifying all
your code.
It was all extensively and meticulously discussed on the list when
namespaces were designed. It is a real waste of time to repeat those
discussions now.
It's only "try namespace, then global" in the case where there's no
\
in the function name. Compile code that does the
check: http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_compile.c#1938
I know. That you for pointing me to the code I wrote. I am sorry that I
didn't just copy-paste the whole "namespace resolution rules" section, I
though it is clear from the context that I am talking about
non-fully-qualified names.
PS: I think it's ironic talking about internal consistency of a language
in the same reply where you justify "try namespace, then global" as a
good design feature. Just pointing that out...
It is a good design feature, and there are very good reasons for it.
Unless, of course, you think prepending every internal function and PHP
constant in all the existing code in PHP with \ would be better. In
which case we have very different ideas about what good design is and
would never come to any agreement on that.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
hi!
Hi!
At this point I would suggest to put the summary of the pros and cons
described (in a more or less exhaustive way) in the RFC and go for the
vote. Maybe double checks if there are any BC related issues that need
to be addressed as well, as this is something we have to avoid.
But for what I can see, this discussion is running in circle and costs
both of us too much time and energy. Cool down a bit, breath deeply
and let the RFC voting phase begins as soon as possible.
Cheers.
Pierre
@pierrejoye | http://www.libgd.org
In which case we have very different ideas about what good design
is and would never come to any agreement on that.
This is already evident in ALL of your recent "discussions" on this ML. Go
and look: you are the most active participant in each topic and you are
bickering in each one. Could you please stop dominating every discussion?
In which case we have very different ideas about what good design
is and would never come to any agreement on that.This is already evident in ALL of your recent "discussions" on this ML. Go
and look: you are the most active participant in each topic and you are
bickering in each one. Could you please stop dominating every discussion?
I'd to say it is more an attempt to understand the needs of one
feature or another. This is why this ML exists, to discuss (which may
move to arguing sometimes, so it goes). But I won't ever ask someone
to stop participating to discussions, unless it goes off topic or the
tone is not appropriate (had one recently where my tone was not the
best, I stopped :).
That being said, there is always a point in a RFC discussion where
there is nothing left to discuss or argue about, we are so far with
this one.
Cheers,
Pierre
@pierrejoye | http://www.libgd.org
On Tue, Sep 3, 2013 at 6:04 PM, Levi Morrison morrison.levi@gmail.com
wrote:In which case we have very different ideas about what good design
is and would never come to any agreement on that.This is already evident in ALL of your recent "discussions" on this ML.
Go
and look: you are the most active participant in each topic and you are
bickering in each one. Could you please stop dominating every discussion?I'd to say it is more an attempt to understand the needs of one
feature or another. This is why this ML exists, to discuss (which may
move to arguing sometimes, so it goes). But I won't ever ask someone
to stop participating to discussions, unless it goes off topic or the
tone is not appropriate (had one recently where my tone was not the
best, I stopped :).
I didn't ask him to stop participating: I asked him to stop dominating
every discussion. There is a significant difference.
That being said, there is always a point in a RFC discussion where
there is nothing left to discuss or argue about, we are so far with
this one.
We've been at this point for a while; no new arguments have been raised
despite several people asking to bring it back in focus.
2013/9/3 Levi Morrison morrison.levi@gmail.com
On Tue, Sep 3, 2013 at 6:04 PM, Levi Morrison morrison.levi@gmail.com
wrote:In which case we have very different ideas about what good design
is and would never come to any agreement on that.This is already evident in ALL of your recent "discussions" on this ML.
Go
and look: you are the most active participant in each topic and you are
bickering in each one. Could you please stop dominating every
discussion?I'd to say it is more an attempt to understand the needs of one
feature or another. This is why this ML exists, to discuss (which may
move to arguing sometimes, so it goes). But I won't ever ask someone
to stop participating to discussions, unless it goes off topic or the
tone is not appropriate (had one recently where my tone was not the
best, I stopped :).I didn't ask him to stop participating: I asked him to stop dominating
every discussion. There is a significant difference.
I must say, that I share this opinion. I follow this list quite a while now
and it is not the first time, that the discussion about a quite promising
proposal were "dominated" until one after the other leaves the discussion
-- annoyed and demotivated.
That being said, there is always a point in a RFC discussion where
there is nothing left to discuss or argue about, we are so far with
this one.We've been at this point for a while; no new arguments have been raised
despite several people asking to bring it back in focus.
That being said, there is always a point in a RFC discussion where
there is nothing left to discuss or argue about, we are so far with
this one.We've been at this point for a while; no new arguments have been raised
despite several people asking to bring it back in focus.
I totally understand your view on how such discussions go. However it
was (for what I read) about technical issues and the tones were
correct, could have been more diplomatic but that's fine imho. I am
not sure how to solve this problem as we have to discuss things deeply
and be sure that active core developers actually understand all the
impact of a given proposal will have, that's a must.
I am also relatively happy with the situation compared to other
projects (try to do it on the kernel mailing list f.e.) while we have
to put more efforts to be contributors friendly, like on the cairo
project (best ever).
Sadly Anthony took this whole thing way too personally and is leaving
php.net, I'm not sure it is a definitive choice but it is a bad move,
in many ways and for both php.net and himself. It is very common that
not everyone agree with a proposal, or do not see the needs of it,
trying to understand its impact or the reasoning behind it. If
everyone begins to leave as soon as it happens, OSS would die, right
now.
Conclusion: We are a tech group, keep that in mind :)
Cheers.
Pierre
@pierrejoye | http://www.libgd.org
On Thu, Sep 5, 2013 at 10:23 AM, Sebastian Krebs krebs.seb@gmail.com
wrote:That being said, there is always a point in a RFC discussion where
there is nothing left to discuss or argue about, we are so far with
this one.We've been at this point for a while; no new arguments have been raised
despite several people asking to bring it back in focus.I totally understand your view on how such discussions go. However it
was (for what I read) about technical issues and the tones were
correct, could have been more diplomatic but that's fine imho. I am
not sure how to solve this problem as we have to discuss things deeply
and be sure that active core developers actually understand all the
impact of a given proposal will have, that's a must.
I don't think this discussion was about technical issues. Let me summarize
the main discussion points:
- "This will make function calls slower!". Many complaints about this
change hurting performance, even though it was pointed out early on (and
detailed in the RFC) that this is not true. - "Will you put every function in it's own file?!". This has been repeated
a lot in this thread, even though again it has been pointed out early
that there are more reasonable autoloading schemes for functions (e.g.
namespace-to-file) - "Just use static methods instead". I don't need to comment on the
absurdity of this statement. - "Which function is autoloaded?" Is the namespaced version or the global
fallback loaded?
Of these, only the last point has been of any benefit to this discussion.
There has also been some minor discussion regarding the API, which is also
relevant. But why does 80% of this thread deal with performance (known
incorrect assumption), unreasonable suggestions of function-to-file
mappings (even though alternatives are known) and suggestions to just not
use functions? It's really hard to fish out the 10 relevant mails in a
discussion spanning 70 in total.
Sadly Anthony took this whole thing way too personally and is leaving
php.net, I'm not sure it is a definitive choice but it is a bad move,
in many ways and for both php.net and himself. It is very common that
not everyone agree with a proposal, or do not see the needs of it,
trying to understand its impact or the reasoning behind it. If
everyone begins to leave as soon as it happens, OSS would die, right
now.
I'm pretty sure that Anthony's reaction is not directly related to this
particular thread - rather it is an accumulation of the very same kind of
discussion we have on nearly every RFC. Discussion is always very circular,
covering issues that have already been addressed (usually even written down
in the RFCs). Typically this kind of pointless discussion happens between
just three or so people and fills the largest part of the thread. Stas is
usually one of those "three" people, though of course I will not imply
causation from correlation.
Nikita
On Thu, Sep 5, 2013 at 10:23 AM, Sebastian Krebs krebs.seb@gmail.com
wrote:That being said, there is always a point in a RFC discussion where
there is nothing left to discuss or argue about, we are so far with
this one.We've been at this point for a while; no new arguments have been raised
despite several people asking to bring it back in focus.I totally understand your view on how such discussions go. However it
was (for what I read) about technical issues and the tones were
correct, could have been more diplomatic but that's fine imho. I am
not sure how to solve this problem as we have to discuss things deeply
and be sure that active core developers actually understand all the
impact of a given proposal will have, that's a must.I don't think this discussion was about technical issues. Let me summarize
the main discussion points:
- "This will make function calls slower!". Many complaints about this
change hurting performance, even though it was pointed out early on (and
detailed in the RFC) that this is not true.- "Will you put every function in it's own file?!". This has been repeated
a lot in this thread, even though again it has been pointed out early that
there are more reasonable autoloading schemes for functions (e.g.
namespace-to-file)- "Just use static methods instead". I don't need to comment on the
absurdity of this statement.- "Which function is autoloaded?" Is the namespaced version or the global
fallback loaded?Of these, only the last point has been of any benefit to this discussion.
There has also been some minor discussion regarding the API, which is also
relevant. But why does 80% of this thread deal with performance (known
incorrect assumption), unreasonable suggestions of function-to-file mappings
(even though alternatives are known) and suggestions to just not use
functions? It's really hard to fish out the 10 relevant mails in a
discussion spanning 70 in total.
Right, it goes circular way too often. I see that in many other MLs. I
however do not see it as a reason to leave, no matter how much it
happens. I also see these questions, discussions or arguing session as
technical matters, be semantic, common sense or anything else. It is
all about being sure about what php will be after a given feature is
added.
I'm pretty sure that Anthony's reaction is not directly related to this
particular thread - rather it is an accumulation of the very same kind of
discussion we have on nearly every RFC. Discussion is always very circular,
covering issues that have already been addressed (usually even written down
in the RFCs). Typically this kind of pointless discussion happens between
just three or so people and fills the largest part of the thread. Stas is
usually one of those "three" people, though of course I will not imply
causation from correlation.
I very much respect Stas, both for his constructive attitude and the
insane amount of work he puts in PHP and the related projects. As
anyone else, he is however a human, with needs to understand a
specific point very clearly. I do not think there any evil or
domination behavior here. About the N people trying to control
everything, that's why we have RFCs. Maybe we should scan discussions
more frequently and stop them when it goes circular, ask to update the
RFC accordingly and move forward. This is something I tried to do.
Sadly I was busy with other stuff in the last couple of months and was
not able to follow each recent RFC discussions closely.
Cheers,
Pierre
@pierrejoye | http://www.libgd.org
On Thu, Sep 5, 2013 at 10:23 AM, Sebastian Krebs krebs.seb@gmail.com
wrote:That being said, there is always a point in a RFC discussion where
there is nothing left to discuss or argue about, we are so far with
this one.We've been at this point for a while; no new arguments have been raised
despite several people asking to bring it back in focus.I totally understand your view on how such discussions go. However it
was (for what I read) about technical issues and the tones were
correct, could have been more diplomatic but that's fine imho. I am
not sure how to solve this problem as we have to discuss things deeply
and be sure that active core developers actually understand all the
impact of a given proposal will have, that's a must.I don't think this discussion was about technical issues. Let me summarize
the main discussion points:
- "This will make function calls slower!". Many complaints about this
change hurting performance, even though it was pointed out early on (and
detailed in the RFC) that this is not true.- "Will you put every function in it's own file?!". This has been repeated
a lot in this thread, even though again it has been pointed out early that
there are more reasonable autoloading schemes for functions (e.g.
namespace-to-file)- "Just use static methods instead". I don't need to comment on the
absurdity of this statement.- "Which function is autoloaded?" Is the namespaced version or the global
fallback loaded?Of these, only the last point has been of any benefit to this discussion.
There has also been some minor discussion regarding the API, which is also
relevant. But why does 80% of this thread deal with performance (known
incorrect assumption), unreasonable suggestions of function-to-file mappings
(even though alternatives are known) and suggestions to just not use
functions? It's really hard to fish out the 10 relevant mails in a
discussion spanning 70 in total.Right, it goes circular way too often. I see that in many other MLs. I
however do not see it as a reason to leave, no matter how much it
happens. I also see these questions, discussions or arguing session as
technical matters, be semantic, common sense or anything else. It is
all about being sure about what php will be after a given feature is
added.I'm pretty sure that Anthony's reaction is not directly related to this
particular thread - rather it is an accumulation of the very same kind of
discussion we have on nearly every RFC. Discussion is always very circular,
covering issues that have already been addressed (usually even written down
in the RFCs). Typically this kind of pointless discussion happens between
just three or so people and fills the largest part of the thread. Stas is
usually one of those "three" people, though of course I will not imply
causation from correlation.I very much respect Stas, both for his constructive attitude and the
insane amount of work he puts in PHP and the related projects. As
anyone else, he is however a human, with needs to understand a
specific point very clearly. I do not think there any evil or
domination behavior here. About the N people trying to control
everything, that's why we have RFCs. Maybe we should scan discussions
more frequently and stop them when it goes circular, ask to update the
RFC accordingly and move forward. This is something I tried to do.
Sadly I was busy with other stuff in the last couple of months and was
not able to follow each recent RFC discussions closely.Cheers,
I agree with Pierre on all his points in this mail.
(Note I haven't done more than skim the fuss around "the post I wish I
didn't have to read" so I won't comment further, nor wish my thoughts
to be extrapolated in any related direction).
Chris
--
christopher.jones@oracle.com http://twitter.com/ghrd
Free PHP & Oracle book:
http://www.oracle.com/technetwork/topics/php/underground-php-oracle-manual-098250.html
namespace foo {
something(); // autoloaded as "something"
}
That makes sense for me for many reasons, but IMHO that's too confusing
for a wider adoption.
Because this doesn't work for function foo\strlen, the only reasonable way
to work with such an autoloader would be to avoid using dynamic namespace
resolution by always using some "use function" or "use namespace".
That's very fragile...
I order not to be the one who kills a proposal and be constructive:
Would some kind of namespace initializers be a good idea?
That could work this way:
Any time a non existing function or constant is required, a registered
namespace initializer would be loaded. The big difference being that it
would happen BEFORE fallback namespace resolution. The registered
namespace loader would be given only the namespace part of the required
symbol, and that would happen only once per namespace.
That would have a performance impact, but I would be interested in seeing
real benchmarks. May be we can find a way to make the mechanism light
enough.
For this performance reason, I would suggest having a registering function
that take the exact namespace for which the loader matches as first
argument:
spl_namespace_register($namespace[, callable $autoload_function)
$autoload_function would be called only for symbols in $namespace.
What do you think ?
Is it worth discussing that further?
Nicolas
Nicolas,
namespace foo {
something(); // autoloaded as "something"
}
That makes sense for me for many reasons, but IMHO that's too confusing
for a wider adoption.
Because this doesn't work for function foo\strlen, the only reasonable way
to work with such an autoloader would be to avoid using dynamic namespace
resolution by always using some "use function" or "use namespace".
That's very fragile...
How is it fragile? In fact, I would argue that relying on dynamic namespace
resolution (as happens today) is fragile. Because you can't know at compile
time (or before hand) what a function will resolve to. That's fine when you
want polymorphism, but when you don't (which is most of the time that
you're calling a named function) it's not much short of fragile.
This encourages explicit, one-execution-path code. I fail to see how that
makes things worse than today... In fact, I see it making this better...
I order not to be the one who kills a proposal and be constructive:
Would some kind of namespace initializers be a good idea?
That could work this way:
Any time a non existing function or constant is required, a registered
namespace initializer would be loaded. The big difference being that it
would happen BEFORE fallback namespace resolution. The registered
namespace loader would be given only the namespace part of the required
symbol, and that would happen only once per namespace.That would have a performance impact, but I would be interested in seeing
real benchmarks. May be we can find a way to make the mechanism light
enough.For this performance reason, I would suggest having a registering function
that take the exact namespace for which the loader matches as first
argument:
spl_namespace_register($namespace[, callable $autoload_function)$autoload_function would be called only for symbols in $namespace.
What do you think ?
Is it worth discussing that further?
It's an interesting thought. I think I'd rather see first-class support for
modules, but not quite sure there.
Actually, thinking about it slightly more, this appears to be trying to
hack namespaces into first-class modules.
Right now, a namespace is nothing more than compiler aided copy/paste (with
the exception of global fallback for functions and constants). It's just a
prefix added on to the construct's name.
To do this right, you could do it by parsing the name at each dispatch, and
then doing a hash table lookup to see if it's been loaded or not yet.
But if we're going down that route, why not take the next logical step and
make modules first class citizens (with a symbol table, where classes,
functions and constants are members of said module, rather than just
floating with prefixed names. That way we can attach metadata, access
permissions, events, etc around the module, and not just hack in one
additional thing.
Obviously this is a massive undertaking and quite off topic from here. But
if it's worth discussing further, let's open another thread.
Anthony
On Sun, Sep 1, 2013 at 12:36 AM, Vartolomei Nicolae
nvartolomei@gmail.comwrote:
personally Ithink it would be nice if we could provide a way for
const/function autoloading.
So you will create files for constants? One file with a single line
defining a constant?Did I understood something wrong?
yes, you did.
I never mentioned that I would use this feature, nor that I would put one
constant in a file if I would.
I suppose those who use it would use namespaces(either native namespaces or
some prefix/suffix in the name which their autoloader understands) to group
the functions/constants and when a const/func is referenced from a
namespace include the file which contains all of the funcs/consts from that
namespace.
--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
Python packages often place convenience functions (e.g., factory methods) in init.py files. There's nothing wrong with that. It would be great to be able to do something similar in PHP. Sure beats creating classes called Util.
Thanks,
Michael
I already have create files for functions of a namespace... Closed source.
Can we take a look at them as an example? Maybe we can give you some advice
how to refactor this code :)Not everything can be found in the 5 most popular frameworks.
Sure, but best practices usually are found there.The lack of logic is: Why is it actually missing?
Why humans don’t have one leg more, on head?I really want to look at an example for this. Looks like you are the only one who needs this.
Oh, is OOP that bad for you? Also constant autoloading looks so bad, I want to see an example of this too for sure.
Please don’t consider these questions like you need to prove something to me,
I’m asking them hoping that anwers will help all internals to understand problem you are trying to solve.kindly,
nvartolomei
On Sat, Aug 31, 2013 at 11:57 PM, Vartolomei Nicolae
nvartolomei@gmail.comwrote:
I already have create files for functions of a namespace... Closed
source.
Can we take a look at them as an example? Maybe we can give you some advice
how to refactor this code :)
So you will create files for constants? One file with a single line
defining a constant?
It seems like many people in this thread can't even imagine that there are
reasonable schemes for function autoloading. So let me give you a practical
autoloading scheme as an example.
I have a library (https://github.com/nikic/iter) - it's not important what
it does, just that it's function based -, which uses the namespaces iter,
iter\fn and iter\rewindable. All functions (and classes!) belonging to the
respective namespaces are stored in iter.php, iter.fn.php and
iter.rewindable.php. [*]
An autoloader for this scheme (according to current proposal) would look
like this:
php\autoload_register(function($name, $type) {
if (0 !== strpos($name, 'iter\')) return;
// extract namespace portion of name
$namespace = substr($name, 0, strrpos($name, '\\'));
require __DIR__ . '/' . str_replace('\\', '.', $namespace) . '.php';
}, php\AUTOLOAD_FUNCTION | php\AUTOLOAD_CLASS);
As you can see, this is a simple autoloader, verify similar to what you'd
write for classes. Differences being a) only the namespace is used to
locate the file, rather than the full name and b) I'm using . instead of /,
but that's really irrelevant here.
Furthermore note that the above autoloading function loads both functions
and classes with the same scheme. As such I find it useful to specify
something like FUNCTION|CLASS a the type.
So, hopefully this clarifies that autoloading does not require "every
function in its own file" or something like that. "Every namespace in its
own file" works fine. This is somewhat akin to how Python modules are
structured.
Thanks,
Nikita
[*] This is not exactly true. There are functions located in the "wrong"
file, but only due to the lack of autoloading. With autoloading it would be
no problem to put all functions in the file belonging to their namespace.
2013/8/30 Stas Malyshev smalyshev@sugarcrm.com
Hi!
Well, static methods aren't the same as functions.
The big difference being?
A function is stateless [1], a method isn't. A function operates only on
the passed parameters [1], the method operates on the parameters and the
context it inherits from the instance (non-static), or class (static and
non-static).
[1] Beside IO and "global variables"-hacks
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi!
A function is stateless [1], a method isn't. A function operates only on
the passed parameters [1], the method operates on the parameters and the
context it inherits from the instance (non-static), or class (static and
non-static).
Static method is stateless in the same meaning as unattached function
is. Both can keep state in static variables if you wish. So no
difference at all, public static method is just a namespaced function.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
-----Original Message-----
From: Sebastian Krebs [mailto:krebs.seb@gmail.com]
Sent: Friday, August 30, 2013 9:02 PM
To: Stas Malyshev
Cc: Sara Golemon; Anthony Ferrara; internals@lists.php.net
Subject: Re: [PHP-DEV] [DRAFT] [RFC] Function autoloading2013/8/30 Stas Malyshev smalyshev@sugarcrm.com
Hi!
Well, static methods aren't the same as functions.
The big difference being?
A function is stateless [1], a method isn't. A function operates only on
the
passed parameters [1], the method operates on the parameters and the
context it inherits from the instance (non-static), or class (static and
non-
static).
Static methods are equally stateless as global functions. A class state
(static members) is no different from global variables (except for a tiny
bit of lipstick in the form of encapsulation). There's no argument
methods are different from global functions, not so with static methods
which are essentially the same as global functions.
Zeev
I can accept not supporting PSR directly but implementing the class
autoloader and stating "internals believes autoload in should exist, just
doesn't specify/support any particular implementation", this makes sense,
although I like PSR and don't really see others that make (as much) sense.
This means internally we recognise an issue, resolve it in a general manner
and allow some decisions up to the developer.
Most of us developing now have the dreaded Utils class, it's an ugly hack
filled with static methods... Yes, it might be almost the same as a
namespaced bunch of classes, if you don't share states between those
methods.
Now consider this: PSR or any autoloader implementation allows for better
sharing and code reuse; AND it makes sense to allow this for OOP as well as
procedural code!
I think Anthony and Nikki can see the forest from the trees, and that the
core should support a number of use cases, not just what you currently use
(and developers miss this functionality Anthony proposes)
Having namespaced functions now allows for a function autoloader that uses
the namespace as the file: awesome, great, let's do this!
If not by looking at others code, or at Python, or at the
Class/Constants/Namespaced-Functions all needing to have and being
positively impacted by an autoloader... at least try and foresee the sense
it makes for non-oop-but-maintained-by-smart-people to have an autoloader!
Try to understand that this need exists and, it makes sense as a step into
organising and refactoring legacy applications and for structure/grouping
of classes, functions and constants, if only for the sake of organisation,
but also for code-sharing, code reuse AND less managing of 20 *_once calls
on top of every file in legacy applications! ;)
Also as a bonus, a bunch of functions/constants filled files could got
through a request never being read/included if never used, this alone
should warrant pause!
2013/8/30 Stas Malyshev smalyshev@sugarcrm.com
Hi!
I have created a new draft RFC implementing function and constant
autoloading in master:https://wiki.php.net/rfc/function_autoloading
All feedback is welcome.
I think it is an unnecessary complication. Classes fit autoloader
paradigm nicely, since the usual pattern is one class per one file
(actually recommended in PSR), so it is easy to establish one-to-one
automatic mapping between classes and files (also recommended in the
PSR).
Autoloading was introduced long before PSR-0 and PSR-0 is also only a
recommendation. So saying "class autoloading was easily introduceable,
because there was always a class<->file mapping" is somehow misleading.
But for functions nobody does this. This means that to implement
function autoloader one will need to have a complicated and fragile
logic (since there's no way to ensure this logic would be in sync with
actual content of files containing multiple functions).
This is the same complicated and fragile logik you need for class loading.
For example compared to PSR-0 functions could be implemented in a file
named after the namespace. An autoloader would be very similar to every
already existing PSR-0 class loader.
Moreover, since this replaces a simple hash lookup with additional two
function calls (and also other operations included in those) everywhere
in the engine, it will also have performance impact of one of the most
frequently used operations in the engine - function calls - while
providing absolutely no benefit for 100% of existing code and 99.99% of
future code.Putting autoloading of different entities into one function makes very
little sense to me - why would the same code load both classes and
functions? How would it do that besides ugly switch that just stuffs two
completely different logic pieces into one function for no reason? The
example given in the RFC is certainly not what anybody would actually
want their autoloaders to do, so I fail to see any case for doing it and
for putting loading more than one entity into one function (that given
that autoloading function would be desirable at all, which it still
doesn't seem so for me).
It is
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227--
On Fri, Aug 30, 2013 at 6:57 AM, Stas Malyshev smalyshev@sugarcrm.comwrote:
I think it is an unnecessary complication. Classes fit autoloader
paradigm nicely, since the usual pattern is one class per one file
(actually recommended in PSR), so it is easy to establish one-to-one
automatic mapping between classes and files (also recommended in the
PSR). But for functions nobody does this. This means that to implement
function autoloader one will need to have a complicated and fragile
logic (since there's no way to ensure this logic would be in sync with
actual content of files containing multiple functions).
For functions people do not commonly use a one-to-one mapping between a
function name and a file, that's true. But there commonly is a one-to-one
mapping between a namespace and a file. So if you have a function
foo\bar\baz it will be in the file foo/bar.php (which defines all functions
of namespace foo\bar). I think this is a rather common pattern in
functional (or function-heavy) libraries and I use this myself too.
Apart from such a namespace-to-file mapping you can also use the same
approach some people use for classes: Just pregenerate the name-to-file
mappings in an array, then loop up from there (e.g. theseer/autoload). This
is one of the rare autoloading concepts that actually properly works in PHP
(much unlike PSR-0, which fails to honor case-insensitivity).
Moreover, since this replaces a simple hash lookup with additional two
function calls (and also other operations included in those) everywhere
in the engine, it will also have performance impact of one of the most
frequently used operations in the engine - function calls - while
providing absolutely no benefit for 100% of existing code and 99.99% of
future code.
I'd assume that this isn't yet the final patch and it will be improved to
make sure that there is no significant performance regression for function
calls not making use of autoloading. This should just be a matter of
inlining the part of the function with the direct hash lookup and avoiding
a duplicate lcname call. (Maybe in the engine just keep the old if
(zend_hash_find(...)) and add an else { autoload(); }.)
Putting autoloading of different entities into one function makes very
little sense to me - why would the same code load both classes and
functions?
I don't think it makes much sense to use the same function to autoload
classes and functions, but I think it makes sense to autoload both
functions and constants with the same mechanism, because presumably both
would follow the same naming-convention (e.g. the namespace-to-file mapping
mentioned above). So I think this is a useful feature and I definitely
don't see a reason why we need to explicitly prevent it.
Anyway, I'm +1 on this :) PHP has been neglecting it's functional sides.
The "use function" RFC and this one work on improving this a bit.
Nikita
Stas,
Moreover, since this replaces a simple hash lookup with additional two
function calls (and also other operations included in those) everywhere
in the engine, it will also have performance impact of one of the most
frequently used operations in the engine - function calls - while
providing absolutely no benefit for 100% of existing code and 99.99% of
future code.
This was already directly covered in the RFC already:
https://wiki.php.net/rfc/function_autoloading#c_api_backwards_compatibility
Basically, two new macros are introduced which expand directly to hash
lookups.
#define ZEND_LOOKUP_FUNCTION_BY_NAME(name, name_length, fbc)
(zend_hash_find(EG(function_table), (name), (name_length) + 1,
(void**) (fbc)) == SUCCESS || zend_lookup_function((name),
(name_length), (fbc)) == SUCCESS)
So nothing changes from present (at all) unless a function is not defined.
Today, that's an error case. So the only performance change occurs if
zend_hash_find (which is already there) returns FAILURE. THEN the logic
which includes autoloading would run.
So no, there should be no performance impact at all to existing code thanks
to operator short circuiting.
Anthony
Hi!
So nothing changes from present (at all) unless a function is not
defined. Today, that's an error case. So the only performance change
occurs if zend_hash_find (which is already there) returns FAILURE. THEN
the logic which includes autoloading would run.
I see a number of places where hash lookup is replaced with
zend_lookup_function, not with the macro. Moreover, zend_lookup_function
for some reason copies and lowercases the argument, even though for hash
lookup it should already be lowercased.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Stas,
I see a number of places where hash lookup is replaced with
zend_lookup_function, not with the macro. Moreover, zend_lookup_function
for some reason copies and lowercases the argument, even though for hash
lookup it should already be lowercased.
There was quite literally one place I forgot to switch to the macro
expansion (in zend_API.c, zend_is_callable_check_func). I'm sorry. That has
been rectified.
As far as it being already lowercased, based on the original implementation
before refactor, I couldn't hold that as true. So I had implemented it very
similar to lookup_class.
However, after the refactor (the current state of the patch), it is
redundant. I have pushed a commit to refactor that away.
Thanks
Anthony
Stas,
On Fri, Aug 30, 2013 at 12:57 AM, Stas Malyshev smalyshev@sugarcrm.comwrote:
Hi!
I have created a new draft RFC implementing function and constant
autoloading in master:https://wiki.php.net/rfc/function_autoloading
All feedback is welcome.
I think it is an unnecessary complication. Classes fit autoloader
paradigm nicely, since the usual pattern is one class per one file
(actually recommended in PSR), so it is easy to establish one-to-one
automatic mapping between classes and files (also recommended in the
PSR). But for functions nobody does this. This means that to implement
function autoloader one will need to have a complicated and fragile
logic (since there's no way to ensure this logic would be in sync with
actual content of files containing multiple functions).
I don't think that's a fair argument. It's a bit "We don't support function
autoloading, so function autoloading doesn't make sense".
As far as complicated and fragile logic, as Nikita pointed out, you could
put all of your functions inside of a "functions,php" in a particular
namespace. Then, with use function, you can capture the missing function
call, and cut off the function name, require_once
/path/to/namespace/functions.php, and be good.
Or, alternatively, you can keep a mapping of function->filename. There's no
need or requirement for one-class, one-function or one-constant.
Furthermore, I think that's up to the community to decide how to do. They
mostly settled on a 1-class-to-1-file rule (which was not the case prior to
__autoload/spl_autoload). I am fully confident that they will find a way
that makes sense, if given the ability.
Putting autoloading of different entities into one function makes very
little sense to me - why would the same code load both classes and
functions? How would it do that besides ugly switch that just stuffs two
completely different logic pieces into one function for no reason? The
example given in the RFC is certainly not what anybody would actually
want their autoloaders to do, so I fail to see any case for doing it and
for putting loading more than one entity into one function (that given
that autoloading function would be desirable at all, which it still
doesn't seem so for me).
That's why this is a RFC which is up for discussion. That's why this is a
draft instead of a proposal. Would you rather see:
bool php\autoload_class_register($callback, $prepend))
bool php\autoload_function_register($callback, $prepend)
bool php\autoload_constant_register($callback, $prepend)
Would you rather having the single autoload regstier, but enforcing that
type must be a single type?
Would you rather see interfaces?
interface php\Autoloader {}
interface php\AutoloaderClass extends php\Autoloader {
public function loadClass($name);
}
interface php\AutoloaderFunction extends php\Autoloader {
public function loadFunction($name);
}
interface php\AutoloaderConstant extends php\Autoloader {
public function loadConstant($name);
}
bool php\autoload_register(php\Autoloader $loader, $prepend);
The syntax provided in this RFC is a proposal. It's not set in stone. If
you don't like it, let's work towards a better one!
Thanks,
Anthony
Hi!
As far as complicated and fragile logic, as Nikita pointed out, you
could put all of your functions inside of a "functions,php" in a
It's the same as making it Functions.php and a class. I don't see why we
should overhaul the autoloading in the engine and add so many complexity
just to avoid writing the word "class".
Or, alternatively, you can keep a mapping of function->filename. There's
no need or requirement for one-class, one-function or one-constant.
One-class-per-file is a very frequent usage pattern.
One-function-per-file never happens. That's the difference.
Furthermore, I think that's up to the community to decide how to do.
They mostly settled on a 1-class-to-1-file rule (which was not the case
prior to __autoload/spl_autoload). I am fully confident that they will
find a way that makes sense, if given the ability.
This sounds like a solution in search of a problem. I don't think we
should create solutions for problems that do not exist and then tell
people "now go find some problem that may fit this neat code that I've
added to the engine". We should first identify the need and only then
mess with the engine, not the other way around.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Furthermore, I think that's up to the community to decide how to do.
They mostly settled on a 1-class-to-1-file rule (which was not the case
prior to __autoload/spl_autoload). I am fully confident that they will
find a way that makes sense, if given the ability.This sounds like a solution in search of a problem. I don't think we
should create solutions for problems that do not exist and then tell
people "now go find some problem that may fit this neat code that I've
added to the engine". We should first identify the need and only then
mess with the engine, not the other way around.
The problem exists: us users need a way to better organize our procedural codebases than manually managing a million require statements. You guys have now given us importing of functions, which is a great step forward. But we still need a way to intelligently load them.
Am 30.08.2013 03:23, schrieb Anthony Ferrara:
All feedback is welcome.
Can we please get rid off the __autoload() function first before we
consider adding new functionality?
--
Sebastian Bergmann Co-Founder and Principal Consultant
http://sebastian-bergmann.de/ http://thePHP.cc/
On Fri, Aug 30, 2013 at 9:35 AM, Sebastian Bergmann sebastian@php.netwrote:
Am 30.08.2013 03:23, schrieb Anthony Ferrara:
All feedback is welcome.
Can we please get rid off the __autoload() function first before we
consider adding new functionality?
Huge +1 to start deprecating this feature, then completely remove it.
And to continue the discussion, I recall that we, as PHP contributors,
disagreed to include a PSR-0 compatible autoloader into Core.
So the argument of PSR-0 is not valid for me, as it has nothing to do with
PHP internals and actually is "just a recommandation" we didn't want to
merge into PHP.
Perhaps is it also time to talk about this subject back and finally all
agree on a default recommanded implentation of autoloading in PHP
(internally supported) ?
Julien.Pauli
Am 30.08.2013 10:42, schrieb Julien Pauli:
Perhaps is it also time to talk about this subject back and finally all
agree on a default recommanded implentation of autoloading in PHP
(internally supported) ?
The only autoloader implementation that makes sense to me is to use a
tool such as https://github.com/theseer/Autoload to generate the code.
That being said, I do not thinkthat the PHP project should recommend a
specific tool but rather the concept.
--
Sebastian Bergmann Co-Founder and Principal Consultant
http://sebastian-bergmann.de/ http://thePHP.cc/
Hi!
And to continue the discussion, I recall that we, as PHP contributors,
disagreed to include a PSR-0 compatible autoloader into Core.
This has nothing to do with PSR-0 in core. This has everything to do
with the fact that class-per-file is an accepted pattern in PHP and many
other languages, and considered by many to be the best practice.
However, nobody uses function-per-file.
Perhaps is it also time to talk about this subject back and finally all
agree on a default recommanded implentation of autoloading in PHP
(internally supported) ?
Again, it does not matter how classes are matched to files and where
the slashes are put in. What matters is that classes and files are
roughly in one-to-one correspondence (there are exceptions, but there
are just that - exceptions - and usually for classes that aren't part of
public API). So I'd like not to sidetrack the discussion into discussing
which way of putting slashes in is the best and whether PHP core should
have backslash-to-forward-slash function. It is not what it is about.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
On Fri, Aug 30, 2013 at 3:23 AM, Anthony Ferrara ircmaxell@gmail.comwrote:
All,
I have created a new draft RFC implementing function and constant
autoloading in master:https://wiki.php.net/rfc/function_autoloading
All feedback is welcome.
Just to say : one benefit of this work would be to finally have autoload
functionnality (which is a Core feature IMO) included in Zend/ and no more
in an extension.
Julien.Pauli
Just to say : one benefit of this work would be to finally have autoload
functionnality (which is a Core feature IMO) included in Zend/ and no more
in an extension.
What is the benefit, except having more stuff in the engine? SPL is part
of the core. Let's not pack the engine with stuff not needed there.
johannes
On Fri, Aug 30, 2013 at 11:46 AM, Johannes Schlüter
johannes@schlueters.de wrote:
Just to say : one benefit of this work would be to finally have autoload
functionnality (which is a Core feature IMO) included in Zend/ and no more
in an extension.What is the benefit, except having more stuff in the engine? SPL is part
of the core. Let's not pack the engine with stuff not needed there.
Can we stop this madness of considering SPL as non standard or as a
'let put everything we don't know in there' extension?
It was created to provided some standard advanced functions or
structures. SPL was then used to work around some of the limitation of
the engine, or add features not desired by some of the core devs,
because no compromise was found. This must end, either it is needed
and should be in the engine, or it is not and can go in pecl. SPL is
standard, and always enabled. It should not continue to become a 2nd
layer to the engine but to provide advanced features like what it
initially did.
--
Pierre
@pierrejoye | http://www.libgd.org
The problem I see with implementing this kind of functionality in Core is
that it relies heavily on convention; PSR-0 is specifically a configuration
of the core autoloader which allows any configuration, as it should. And
while most of the community has adopted PSR-0 (as have I), I do not think
Core is the place for it.
Bryan
-----Original Message-----
From: julienpauli@gmail.com [mailto:julienpauli@gmail.com] On Behalf Of
Julien Pauli
Sent: Friday, August 30, 2013 3:50 AM
To: Anthony Ferrara
Cc: internals@lists.php.net
Subject: Re: [PHP-DEV] [DRAFT] [RFC] Function autoloading
Just to say : one benefit of this work would be to finally have autoload
functionnality (which is a Core feature IMO) included in Zend/ and no more
in an extension.
Julien.Pauli
Having said that, I think the overall concept of function autoloading is a
useful feature and haven't seen a good argument for why it shouldn't be
supported.
Bryan
-----Original Message-----
From: Bryan C. Geraghty [mailto:bryan@ravensight.org]
Sent: Friday, August 30, 2013 8:13 AM
To: 'Julien Pauli'
Cc: 'internals@lists.php.net'
Subject: RE: [PHP-DEV] [DRAFT] [RFC] Function autoloading
The problem I see with implementing this kind of functionality in Core is
that it relies heavily on convention; PSR-0 is specifically a configuration
of the core autoloader which allows any configuration, as it should. And
while most of the community has adopted PSR-0 (as have I), I do not think
Core is the place for it.
Bryan
-----Original Message-----
From: julienpauli@gmail.com [mailto:julienpauli@gmail.com] On Behalf Of
Julien Pauli
Sent: Friday, August 30, 2013 3:50 AM
To: Anthony Ferrara
Cc: internals@lists.php.net
Subject: Re: [PHP-DEV] [DRAFT] [RFC] Function autoloading
Just to say : one benefit of this work would be to finally have autoload
functionnality (which is a Core feature IMO) included in Zend/ and no more
in an extension.
Julien.Pauli
Hi!
Just to say : one benefit of this work would be to finally have autoload
functionnality (which is a Core feature IMO) included in Zend/ and no more
in an extension.
PHP core already has autoload functionality. And I don't see how with
function autoloading (which has no natural mapping at all) it is even
possible to have any mapping worth including into core as a standard.
Most functional code I've seen isn't even namespaced, and if you already
convert old code to namespaces and need autoloading, you could as well
wrap it in a class - I don't see why it's not possible.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
All,
I have updated the RFC to include 2 new benchmarks.
For normal class loading, this proposal shows at worst no change to loading
time. At best, it may actually improve it because at least one
zend_function_call is avoided (to spl_autoload_call).
For constants and function calls, the benchmark shows that the difference
is well within the margin of error for the test (considering variances of
5% to 10% were common in my running of the tests).
So hopefully this will dispel any worry about performance regressions in
currently defined cases.
The times where performance will take a hit, is with undefined functions
and constants. Today, an undefined function will fatal error, so this
performance hit would be 0, as it would enable something that's not
possible today.
The only regression can be where autoloaders are defined, and people are
relying on the legacy undefined constant behavior (which triggers an
E_NOTICE).
Anthony
On Thu, Aug 29, 2013 at 9:23 PM, Anthony Ferrara ircmaxell@gmail.comwrote:
All,
I have created a new draft RFC implementing function and constant
autoloading in master:https://wiki.php.net/rfc/function_autoloading
All feedback is welcome.
Thanks
Anthony
Hi
The only regression can be where autoloaders are defined, and people are
relying on the legacy undefined constant behavior (which triggers an
E_NOTICE).
that makes me think about this code :
<?php namespace foo; bar(); ?>
What autoload should be triggered?
"foo\bar" or "bar"?
Both are valid isn't it?
Should autoloading functions and constants be restricted to namespaced ones
only?
Then the BC issue you spot would disappear.
For constants and function calls, the benchmark shows that the difference
is well within the margin of error for the test (considering variances of
5% to 10% were common in my running of the tests).So hopefully this will dispel any worry about performance regressions in
currently defined cases.The times where performance will take a hit, is with undefined functions
and constants. Today, an undefined function will fatal error, so this
performance hit would be 0, as it would enable something that's not
possible today.
I would assume there is actually potential for performance gain for
functions being autoloaded in larger codebases when the *_once calls are
removed that would normally load the common functions files.
For constants and function calls, the benchmark shows that the difference
is well within the margin of error for the test (considering variances of
5% to 10% were common in my running of the tests).So hopefully this will dispel any worry about performance regressions in
currently defined cases.The times where performance will take a hit, is with undefined functions
and constants. Today, an undefined function will fatal error, so this
performance hit would be 0, as it would enable something that's not
possible today.I would assume there is actually potential for performance gain for
functions being autoloaded in larger codebases when the *_once calls are
removed that would normally load the common functions files.
I just reply to this point:
No. thinking we already have opcache there. so, compiling Functions is cheap.
but if with function autoloading, function autoloading will execute every run.
thanks
--
Laruence Xinchen Hui
http://www.laruence.com/
For constants and function calls, the benchmark shows that the difference
is well within the margin of error for the test (considering variances of
5% to 10% were common in my running of the tests).So hopefully this will dispel any worry about performance regressions in
currently defined cases.The times where performance will take a hit, is with undefined functions
and constants. Today, an undefined function will fatal error, so this
performance hit would be 0, as it would enable something that's not
possible today.I would assume there is actually potential for performance gain for
functions being autoloaded in larger codebases when the *_once calls are
removed that would normally load the common functions files.
Maybe of interest:
We got a performance win from exactly this at Facebook. We have some
extensions in HHVM to autoload that allowed us to remove almost all
our *_once calls.
We have user code register an "autoload map" with the runtime at the
beginning of most requests (an array mapping class/function names to
which files to load), so we don't normally execute any user code to
figure out which file needs loading. (There's various other
optimizations to avoid autoload on top of that too.)
I don't know enough about PHP internals to know if that approach would
work as well here, though.
-Jordan
Hi!
We got a performance win from exactly this at Facebook. We have some
extensions in HHVM to autoload that allowed us to remove almost all
our *_once calls.
But autoloading does not remove require - you still have to load the
files. Only thing that can be removed is a non-loading require. Is it
that frequent that it had significant performance impact (given that
with opcode caching non-loading require is pretty much a couple of hash
lookups)?
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
2013/8/31 Stas Malyshev smalyshev@sugarcrm.com
Hi!
We got a performance win from exactly this at Facebook. We have some
extensions in HHVM to autoload that allowed us to remove almost all
our *_once calls.But autoloading does not remove require - you still have to load the
files.
But it removes many many 'require_once's.
Only thing that can be removed is a non-loading require. Is it
that frequent that it had significant performance impact (given that
with opcode caching non-loading require is pretty much a couple of hash
lookups)?
Those, who doesn't wrap anything in classes, can see this very frequently.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227--
Hi!
We got a performance win from exactly this at Facebook. We have some
extensions in HHVM to autoload that allowed us to remove almost all
our *_once calls.But autoloading does not remove require - you still have to load the
files. Only thing that can be removed is a non-loading require. Is it
that frequent that it had significant performance impact (given that
with opcode caching non-loading require is pretty much a couple of hash
lookups)?
For us it saved unnecessary loading requires due to transitive module
dependencies, as well. I'd suspect it is unlikely to matter in nearly
the same way on smaller codebases, though.
-Jordan