FAQ
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

Search Discussions

  • Stas Malyshev at Aug 30, 2013 at 4:57 am
    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
  • Stas Malyshev at Aug 30, 2013 at 4:58 am
    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
  • Laruence at Aug 30, 2013 at 5:36 am

    On Fri, Aug 30, 2013 at 12:58 PM, Stas Malyshev wrote:
    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

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


    --
    Laruence Xinchen Hui
    http://www.laruence.com/
  • Sara Golemon at Aug 30, 2013 at 6:51 am

    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
  • Stas Malyshev at Aug 30, 2013 at 7:02 am
    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
  • Sara Golemon at Aug 30, 2013 at 7:08 am

    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
  • Sebastian Krebs at Aug 30, 2013 at 7:22 am
    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

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

    --
    github.com/KingCrunch
  • Stas Malyshev at Aug 30, 2013 at 5:10 pm
    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
  • Nikita Popov at Aug 30, 2013 at 5:38 pm

    On Fri, Aug 30, 2013 at 7:10 PM, Stas Malyshev 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
  • Stas Malyshev at Aug 30, 2013 at 5:54 pm
    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
  • Vartolomei Nicolae at Aug 31, 2013 at 8:43 am
    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 Friday, August 30, 2013 at 8:38 PM, Nikita Popov wrote:

    On Fri, Aug 30, 2013 at 7:10 PM, Stas Malyshev (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
  • Sebastian Krebs at Aug 31, 2013 at 6:03 pm
    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,
    nvartolomei

    On Friday, August 30, 2013 at 8:38 PM, Nikita Popov wrote:

    On Fri, Aug 30, 2013 at 7:10 PM, Stas Malyshev (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

    --
    github.com/KingCrunch
  • Vartolomei Nicolae at Aug 31, 2013 at 9:57 pm

    On Saturday, August 31, 2013 at 9:03 PM, Sebastian Krebs wrote:

    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
  • Ferenc Kovacs at Aug 31, 2013 at 10:33 pm

    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
  • Vartolomei Nicolae at Aug 31, 2013 at 10:36 pm
    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
  • Florin Patan at Aug 31, 2013 at 11:05 pm

    On Sun, Sep 1, 2013 at 12:36 AM, Vartolomei Nicolae 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
  • Anthony Ferrara at Aug 31, 2013 at 11:11 pm
    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 Sat, Aug 31, 2013 at 7:04 PM, Florin Patan wrote:

    On Sun, Sep 1, 2013 at 12:36 AM, Vartolomei Nicolae
    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
  • Florin Patan at Sep 1, 2013 at 9:13 am

    On Sun, Sep 1, 2013 at 1:11 AM, Anthony Ferrara wrote:
    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
  • Stas Malyshev at Sep 2, 2013 at 8:11 pm
    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
  • Nicolas Grekas at Sep 1, 2013 at 3:27 pm
    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.
  • Anthony Ferrara at Sep 1, 2013 at 8:30 pm
    Nicolas,
    On Sun, Sep 1, 2013 at 11:27 AM, Nicolas Grekas 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
  • Stas Malyshev at Sep 2, 2013 at 7:34 am
    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
  • Anthony Ferrara at Sep 2, 2013 at 12:58 pm
    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
  • Stas Malyshev at Sep 2, 2013 at 8:03 pm
    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 have `use 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
  • Anthony Ferrara at Sep 2, 2013 at 9:57 pm
    Stas,

    On Mon, Sep 2, 2013 at 4:02 PM, Stas Malyshev wrote:

    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 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.

    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 have `use 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...
  • Stas Malyshev at Sep 2, 2013 at 10:18 pm
    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
  • Pierre Joye at Sep 3, 2013 at 5:32 am
    hi!
    On Tue, Sep 3, 2013 at 12:17 AM, Stas Malyshev wrote:
    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
  • Levi Morrison at Sep 3, 2013 at 4:04 pm

    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?
  • Pierre Joye at Sep 3, 2013 at 4:54 pm

    On Tue, Sep 3, 2013 at 6:04 PM, Levi Morrison 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 :).

    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
  • Levi Morrison at Sep 3, 2013 at 5:04 pm

    On Tue, Sep 3, 2013 at 10:54 AM, Pierre Joye wrote:
    On Tue, Sep 3, 2013 at 6:04 PM, Levi Morrison 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.
  • Sebastian Krebs at Sep 5, 2013 at 8:24 am
    2013/9/3 Levi Morrison <morrison.levi@gmail.com>
    On Tue, Sep 3, 2013 at 10:54 AM, Pierre Joye wrote:

    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.


    --
    github.com/KingCrunch
  • Pierre Joye at Sep 5, 2013 at 8:51 am

    On Thu, Sep 5, 2013 at 10:23 AM, Sebastian Krebs 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 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
  • Nikita Popov at Sep 5, 2013 at 9:35 am

    On Thu, Sep 5, 2013 at 10:51 AM, Pierre Joye wrote:
    On Thu, Sep 5, 2013 at 10:23 AM, Sebastian Krebs 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
  • Pierre Joye at Sep 5, 2013 at 10:32 am

    On Thu, Sep 5, 2013 at 11:34 AM, Nikita Popov wrote:
    On Thu, Sep 5, 2013 at 10:51 AM, Pierre Joye wrote:

    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
  • Christopher Jones at Sep 11, 2013 at 3:00 pm

    On 9/5/13 3:32 AM, Pierre Joye wrote:
    On Thu, Sep 5, 2013 at 11:34 AM, Nikita Popov wrote:
    On Thu, Sep 5, 2013 at 10:51 AM, Pierre Joye wrote:

    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
  • Nicolas Grekas at Sep 2, 2013 at 12:48 pm

    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
  • Anthony Ferrara at Sep 2, 2013 at 1:23 pm
    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
  • Ferenc Kovacs at Aug 31, 2013 at 11:27 pm

    On Sun, Sep 1, 2013 at 12:36 AM, Vartolomei Nicolae 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?
    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
  • Michael Dowling at Aug 31, 2013 at 10:39 pm
    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
    On Aug 31, 2013, at 2:57 PM, Vartolomei Nicolae wrote:
    On Saturday, August 31, 2013 at 9:03 PM, Sebastian Krebs wrote:

    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


    --
    PHP Internals - PHP Runtime Development Mailing List
    To unsubscribe, visit: http://www.php.net/unsub.php
  • Nikita Popov at Sep 1, 2013 at 8:05 am

    On Sat, Aug 31, 2013 at 11:57 PM, Vartolomei Nicolae wrote:
    On Saturday, August 31, 2013 at 9:03 PM, Sebastian Krebs wrote:

    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.
  • Sebastian Krebs at Aug 30, 2013 at 6:02 pm
    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


    --
    github.com/KingCrunch
  • Stas Malyshev at Aug 30, 2013 at 6:14 pm
    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
  • Zeev Suraski at Sep 1, 2013 at 9:38 am

    -----Original Message-----
    From: Sebastian Krebs
    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 autoloading

    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).
    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
  • Daniel Macedo at Sep 1, 2013 at 4:23 pm
    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!
  • Mark Tomlin at Dec 30, 2013 at 4:18 pm

    Daniel Macedo wrote:
    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!
    From a user land developer, having the option of doing something is always
    better then not. You guys are doing a lot of great work for us mere
    mortals, why not also give us this option? It's been stated that thanks to
    a function short circuit that it would not cost performance and would add
    functionally. To me that seems like a win, win.

    --
    Thank You For Your Time.
  • Sebastian Krebs at Aug 30, 2013 at 7:30 am
    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

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

    --
    github.com/KingCrunch
  • Nikita Popov at Aug 30, 2013 at 9:42 am

    On Fri, Aug 30, 2013 at 6:57 AM, Stas Malyshev wrote:

    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
  • Anthony Ferrara at Aug 30, 2013 at 11:17 am
    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
  • Stas Malyshev at Aug 30, 2013 at 5:19 pm
    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
  • Anthony Ferrara at Aug 30, 2013 at 5:36 pm
    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

Related Discussions

People

Translate

site design / logo © 2018 Grokbase