Lukas Kahwe Smith wrote: > > On 04.11.2008, at 17:15, Gregory Beaver wrote: > >> In other words, it is perfectly all right to have a different name >> resolution for classes than we have for functions and constants because >> of this different expectation. It is dangerous to fallback for classes >> prior to autoload, but it is not at all dangerous for >> functions/constants because the expectation is different. > > To me the key question is do we want to let people overload global > classes easily or are we mostly talking about convinience? Class names > are typed quite seldom (and even in a few years down the road the bulk > of PHP's features will be provided via functions), so I would not think > that we really need to focus on convenience here.
OK, taking a step back. Let's distill the two problems we're trying to solve 1) namespaces provide encapsulation - a safe way to name things without worrying about whether it will conflict with external code 2) accessing internal functionality - the most used stuff in PHP should still be easy to use in namespaces. #1 means that when using our code inside namespaces, when there is ambiguity we want it to look for namespaced stuff first and foremost. #2 means we want to be able to access stuff like strlen() and array_map() without any monkey business. The largest conflict between #1 and #2 happens with classes because of autoload. __autoload() is expensive from a performance standpoint, and should not be called unnecessarily. I posit that the most used stuff in PHP are internal functions (not global userspace functions, not internal classes, not userspace classes) and so this needs to be a priority. In addition, there is already confusion over things like: <?php // which of these is a function? $a = 1; unset($a); $a = key(array('hi' => 1)); include('oops.php'); ?> so requiring a prefix for functions will lead to parse errors in user code like: <?php \include('oops.php'); ?> so the best resolution for functions is: 1) ns\function 2) internal function Classes are different (TM). if we do: 1) ns\class 2) autoload ns\class 3) internal class then this code has hidden performance hits: <?php namespace foo; include 'external_autoload.php'; // __autoload must be declared unnamespaced $a = new ArrayObject(array('hi')); // calls autoload unnecessarily ?> if we really mean the "ArrayObject" class and not the "foo\ArrayObject" class. Thus, the convenience of internal fallback has disadvantages (major performance problems) that do not exist with functions or constants. Notifying the user via E_NOTICE/E_STRICT/E_WHATEVER simply adds annoyance, and introduces potential for behavior change. For instance, if a user decides to start using some external library that defines an autoload when they didn't have it before, suddenly all of their code throws E_NOTICEs every time an internal class name is referenced. Or, without the E_NOTICE, performance suddenly slows way down and the user blames the external library. If we do: 1) ns\class 2) internal class 3) autoload ns\class then our code example fails in a more subtle way. The ambiguity of "ArrayObject" resolves always in favor of internal class ArrayObject, which means that users have to always explicitly import namespaced classes to avoid this problem. Why is it a problem? Let's say we're doing our own userspace implementation of PDO with a few extensions, for a system where PDO is disabled: <?php namespace Myproject; class PDO {} // userspace implementation of PDO ?> now in another file: <?php namespace Myproject; $a = new PDO(...); ?> [note: this implementation depends on __autoload existing] Now, if PDO extension is disabled, the above code will successfully autoload Myproject\PDO. Imagine that on an upgrade, PDO is enabled. Now, the object instantiated is of class PDO, not Myproject\PDO. Suddenly, there are subtle logic errors that creep in (not a fatal error), but the code continues to operate normally. This resolution is very dangerous, and is a clear violation of the primary purpose of namespaces. If we do this: 1) ns\class 2) autoload ns\class we get a "stronger" E_NOTICE (fatal E_ERROR) when an internal class is used without explicit import. This is robust, easy to debug, and forces good code without much pain. Our example user above has no problems with the external library, and changes need not be made after initial coding. By doing the resolution I've suggested (and Stas, incidentally, was the first to suggest this): classes: 1) ns\class 2) autoload ns\class 3) FAILBOAT functions/constants: 1) ns\func or ns\const 2) internal func\const 3) FAILBOAT We get the best of #1 and the best of #2, and it makes coding easier in the long run. Greg -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php