Electronics & Programming

develissimo

Open Source electronics development and programming

  • You are not logged in.
  • Root
  • » PHP
  • » [PHP-DEV] RFC - Namespace initializers [RSS Feed]

#1 Dec. 31, 2010 19:05:25

Larry G.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] RFC - Namespace initializers


On Friday, December 31, 2010 7:56:39 am Nicolas Grekas wrote:
> Dear all,
>
> this RFC started by me having a problem on these subjects (not only me
> I think) :
> - namespaced functions and constants loading, or rather not-autoloading,
> - interfaces loading (this time, autoloading).

<snip>

> So, my first proposal for namespaced functions and constants is :
> 1. Remove namespaced functions and constants at all - promote
> namespaced public static methods and class consts instead.
>
> This would fix static code analysis, and the discussion about how to
> autoload (I may say "how to package") namespaced functions and
> constants would vanish. About backward compatibility, who as written
> code relying on namespaced functions or constants? They are useless!

Dear god no! Functions are already close to being second-class citizens in
PHP at this point. The project I work on (Drupal) is currently debating how
to leverage function namespaces for our next version and there are several
ways that we could do so effectively; mostly they come down to module ==
namespace, and then a "hook" (magic function callback) can be placed within a
namespace. That would actually make for clearer code than our current model.

Class == namespace is wrong. Plain and simple. It is a broken assumption
based on broken understanding and the use of them that way is broken. That
approach is utterly useless if you want any sort of flexibility.

> My second proposal is :
> 2. At runtime, when a namespaced identifier is used (lets say
> \my\sub\ns\class_interface_constant_or_function), take the namespace
> part of the identifier and if any, autoload it as if it were a class,
> do not generate any error if the given class name is not found. (ie,
> trigger something like class_exists('my\sub\ns', true);).

I am not entirely sure I follow. 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')?

In the current approach I don't know how you'd properly resolve the "namespace
portion" of the extended class/function/whatever name. Honestly, combined
with the previous proposal(s) for function autoloading (which I support in
general) it seems to me that we need to have separate but parallel pathways
for autoloading different things; that could lead to better performance, too.
If we can properly separate them I can see a use for "clustered" autoloading,
certainly, and namespace is a not-unreasonable definition of cluster.

> Cons :
> - none
> - well, one : I don't speak C, so I don"t have any patch...

I sadly have the same problem. :-)

--Larry Garfield

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

Offline

#2 Dec. 31, 2010 20:53:55

Stas M.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] RFC - Namespace initializers


Hi!About namespaced functions and constants, the fact that they are not
autoloaded makes them useless for any code that wants some good
packaging. For example I looked at the Doctrine2 code, and (tell me ifThis is not true. You can always load stuff manually - in fact, manylanguages don't have any autoloading at all and are just fine.I also have a second strong grief against namespaced functions and
constants : due to their at runtime namespace resolution, static code
analysis is now very hard, even impossible in the general case! It isIn general case, it always was so. Think of $foo->$bar() - what is beingcalled?So, my first proposal for namespaced functions and constants is :
1. Remove namespaced functions and constants at all - promote
namespaced public static methods and class consts instead.This won't happen, for obvious BC reasons. Please re-read thediscussions on the list about namespaced functions to know what arereasons for their existence.2. At runtime, when a namespaced identifier is used (lets say
\my\sub\ns\class_interface_constant_or_function), take the namespace
part of the identifier and if any, autoload it as if it were a class,
do not generate any error if the given class name is not found. (ie,
trigger something like class_exists('my\sub\ns', true);).Autoloading for functions/constancs don't seem to have enough benefit tojustify the complications. As for classes, you can always make youautoloader do anything you want with the name it receives.--
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

Offline

#3 Jan. 5, 2011 17:13:12

Nicolas G.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] RFC - Namespace initializers


>> 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 Grekashttp://pa.tchwork.com/--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#4 Jan. 5, 2011 18:20:50

Michael M.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] RFC - Namespace initializers


One of the first things I tried when I seriously started exploring
namespaces was the ideal of dynamic runtime loading. Consider class \A\Foo.
I have a project that has \B\Foo extends \A\Foo. For that project though I
want the autoloader to pull an unqualified request for "Foo" from \B\Foo
even if this comes up in the A namespace. That currently isn't possible -
the autoloader receives the argument "\A\Foo" from the A namespace whether
new Foo or new A\Foo or new \A\Foo was the origin code.

This leads to my second problem though - even if the autoloader gets to know
the difference and reacts accordingly, what happens if \A\Foo gets
explicitly asked for in the \A namespace after "Foo" was asked for. I don't
know how to resolve this either. So I gave up.

Anyway, My only real gripe with namespaces is that they have no affect on
variables. This I feel is a major implementation error because it runs
counter to how all other languages I've encountered handle namespaces. I've
lost count of how many people I've had to point this out to on sitepoint -
the expectation for programmers coming to PHP is that namespaces will
segregate variables.

It also means that "static" classes become the key means to keep registries
for those that use them. Coupled with the current situation with functions
that can't be autoloaded, this will lead to a lot more var/function hives in
code bases. It's not a particularly testable pattern due to the hidden
dependencies that are created, and becomes a headache over time. Encouraging
the pattern at a language level isn't the worst thing that's ever occurred
(that would be magic_quotes and register_globals) but it's almost in the
same ballpark in my opinion.

I don't see the harm in having a function autoloader and don't understand
the rationale behind the resistance to it. The resistance is futile anyway -
all that's really happening is people move to making functions members of
static classes as a kludge.

All that said, I'm not going to worry myself too much about it as it doesn't
affect my coding approach. I don't use global functions and my only static
class is a bootstrap factory which gets the rest of the code working and
isn't accessible from that code once it starts.

Offline

  • Root
  • » PHP
  • » [PHP-DEV] RFC - Namespace initializers [RSS Feed]

Board footer

Moderator control

Enjoy the 23rd of October
PoweredBy

The Forums are managed by develissimo stuff members, if you find any issues or misplaced content please help us to fix it. Thank you! Tell us via Contact Options
Leave a Message
Welcome to Develissimo Live Support