>> at runtime namespace resolution, static code analysis is now very hard
> In general case, it always was so. Think of $foo->$bar()

Maybe I was too strong about the term "general case". What I though
about is that although variable calls have always been there, they are
both statistically rare and their real variability is most often very
limited, so analyzing the code won't go very wrong. With namespaced
functions, this: rare variability => quite good understandability is
reversed to: large variability (any function call is potentially a
source of variability) => much lower understandability (much higher
risk of going completely wrong).

>> 1. Remove namespaced functions and constants at all
> This won't happen, for obvious BC reasons.

I agree with that, please forget about this part. The idea came up
while writing the mail but that was not my first idea, expressed in
the other parts of my message...

Going back on static call analysis, given that namespaced functions
and constants exists, the next step to analyzing them correctly is for
me to add some heuristics to the parser - for example: if function
exists in the global space assume is has not been overwritten. This
can go wrong but will work most of the time. Maybe enough for some
rough analysis. If I want to go further, I do have to inform the
analyser of some coding convention, to enhance it's capability to know
were functions are defined. My RFC for namespace initializers helps on
this part : giving a path for developers on where to put these
definitions, exactly as autoload does for classes.

> Autoloading for functions/constancs don't seem to have enough benefit

I agree, autoloading functions for the sake of autoloading functions
isn't worth the pain. As you've understood, I mostly don't use
functions, so personnaly I'm ok with the current state of PHP on this
point. But my proposal isn't restricted solely to solving function
autoloading.

To sum up my point, it tries to address 3 points :
1. functions and constants autoloading
2. helping static code analyzers
3. cluster functions, constants, classes and interfaces autoloading

If you don't care for one point, maybe one of the other two may be enough ?

Personally : I don't really care for 1. but I read that others may be
interested - I do code analysis so 2. is good - and 3. seems good for
performance, because it reduces autoload overhead and helps opcode
caches concerning this NOP vs. FETCH_CLASS optimization (thinking
about this: http://sb2.info/alternative-php-cache-and-autoload-interoperability/
- not sure for this opcode part - am I wrong ?)

So, to get back on the second part of my RFC, taking quotes from Larry
Garfield's answer :

>> 2. At runtime, when a namespaced identifier is used, take the namespace
>> part of the identifier and if any, autoload it as if it were a class
>  Are you suggesting that:
>
> use Stuff\Things as Bar;
> $foo = new Bar\Baz\Foo()
>
> should trigger:
> autoload('Stuff\Things\Baz\Foo');
> AND
> autoload('Stuff\Things\Baz')?

Well, yes, but I was thinking about autoloading the namespace before the class.
To be more precise, I was thinking about this :

>when (_class/interface_ Ns\Foo is need)
>{
>    // clustered Ns autoloading
>    autoload('Ns', true)
>
>    // like today
>    if (class/interface Ns\Foo still not exists) autoload('Ns\Foo', null)
>
>    if (class/interface Ns\Foo still not exists) fatal_error
>}
>when (_function/constant_ Ns\Foo is need)
>{
>    // clustered Ns autoloading
>    autoload('Ns', true)
>
>    if (function/constant Ns\Foo still not exists) fatal_error
>}

A second parameter to autoload would be need for coders to decide
between clustered autoload and regular class. This is necessary to be
able to handle nested namespace and clustered autoload recursivity (it
being wanted or not wanted by implementations).

This led me too this reflexion:
this "Ns" then "Ns\Foo" order has one side effect: "Ns\Foo" isn't
available while loading "Ns". This may be seen as a BC break because
code needing this will get a fatal error. Unlikely is practice ? I
don't know.
The benefit for autoloading Ns before Ns\Foo is that we give a
guarantee to developers: "Ns" is always initialized before any usage
of any Ns\Foo. This is the reason I choose this loading order in the
first place - and never really though about the reverse order... But
this guarantee comes at a price: autoload is now called more often:
one more time per namespace.

So thinking seriously about the reverse order : autoloading "Ns\Foo" then "Ns".
I see it a little bit more complicated, but really interesting, with
this algorithm :

>// as today:
>when (_class/interface_ Ns\Foo is need)
>{
>    autoload('Ns\Foo', null)
>
>    // clustered Ns autoloading, before today's fatal error
>    if (class/interface Ns\Foo still not exists) autoload('Ns', true)
>
>    if (class/interface Ns\Foo still not exists) fatal_error
>}
>when (_function/constant_ Ns\Foo is need)
>{
>    // clustered Ns autoloading
>    autoload('Ns', true)
>
>    if (function/constant Ns\Foo still not exists) fatal_error
>}

This algo doesn't have the previous guarantee but as it plugs before
current fatal errors, it is exempt from any BC break, event in term of
performance, existing code won't trigger a single more autoload call.

Personally, I now prefer this second approach!

What about you ?

--
Nicolas Grekas
http://pa.tchwork.com/

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

Reply via email to