Is PHP 5.3 Terminal? Well, It’s Getting One For Namespaces
By Edgar Hassler
On October 27th, 2008
A language lives and dies by how easy it is for a person to express something within that language. But the ease in expression is much like the type I and type II error rate in a statistical test: as you adjust one to be nearer to where you want it to be, the other gets farther away. So the architects of a language have to choose between adding more keywords and constructs or having longer, but simpler sequences of existing ones.
PHP is a very easy language to learn and use because it has a syntax that is a simplified sampling from C++/Java and Perl. People who use these languages pick up PHP fast, and people who haven’t used any languages often learn PHP with as much ease as they would learn Perl.
A bit about namespaces
Most languages have namespaces in one form or another. A namespace is a lot like a class: it is a named entity that houses functions and classes, whereas a class is a named entity that houses properties and methods. Namespaces are found, in one form or another, in most popular languages. In C++ there are explicit namespaces and the namespace
keyword. In Java, since you are allowed to have classes nested within classes, classes act as namespaces. Namespaces make it easier to organize and call your code. If you have a bunch of classes that work together to do something you might name them in a similar way. For example, we here at the Studios sometimes use the following classes:
Canopy_Xml_Document
Canopy_Xml_Document_CDataSection
Canopy_Xml_Document_NodeList
Canopy_Xml_IWritable
Canopy_Xml_Exception
With namespaces, we could define a namespace Canopy
, add to it a namespace Xml
, and then add classes Document
, Exception
and interface IWritable
. We could also add a Document
namespace and add classes CDataSection
and NodeList
. Then we could just tell PHP that we want to refer to things in a certain namespace. We would simply write:
use Canopy::Xml;
$D = new Document(); //$D is equivalent to a Canopy_Xml_Document
In the beta builds of PHP 5.3, the terminal “::” called the scope resolution operator (SRO) is used to denote namespaces. So, in the same way that one would write Class::staticMethod()
one could write NamespaceA::NamespaceB::functionInNamespace()
. This is the same operator used in C++, and it is intuitive since it refines a name to a scope where that name belongs.
PHPs SRO problem
Recently, PHP has had to abandon using the SRO, forego the syntax of other languages and has had to make up their own way of denoting a namespace. One reason for this is that bare words in PHP can have multiple meanings. For example, in PHP you can do:
const('A','constant');
function A() { return 'function'; }
class A(){ public _toString(){ return 'class'; } }
such that
echo A; // constant
echo A(); // function
echo new A(); // class
all do what you’d expect. But in namespaces, there’s some ambiguity introduced. Consider rather A::B::C()
is namespace A
, class B
, static method C
, or namespace A::B
, function C
. In C++ you’re not allowed to have a symbol like A
, B
, or C
represent multiple types of things, so using the SRO does not arrive at ambiguity there. (Instead, you get an error.) But since PHP does allow for that type of thing, the internals team had to choose between:
- Not allowing namespaces to have functions, but rather only classes, thus raising the ire of the community.
- Using some terrible terrible other operator to indicate namespaces, thus raising the ire of the community. (Quoth internals team member: <@CelloG> % is also possible but holy god almighty it is fugly
- Put off namespaces until (or if) something decent can be figured out, thus raising the ire of the community.
The team decided on 2, going with the \ character.
What’s that mean for the language?
The discussion was concerned with preventing unanticipated behavior from just making a rule to disambiguate rather a function or static method is called. I feel that throwing an error (or warning and choosing one) whenever that situation arises would be a perfectly acceptable solution. I would also have been happy to see them further follow Java’s lead and allow classes to be nested. Then there is no ambiguity between a static method and a function because they are the same. This would probably require much more work and you would have to allow class definitions across multiple files, but I feel this is a better option than ‘\’. To that end I would have enjoyed option 1 over option 2.
The most cited complaints about PHP is how there is little consistency in function names and in argument order. This new ‘\’ operator adds to the “weird-factor” which makes it more difficult for people to read and use the language. It further marginalizes PHP, adding to a series of minor but obnoxious issues proponents are embarrassed by.
The language is adrift with little direction, trying to address the wants of its developers, and adding a terminal is payment for a lack of planning and a general stubbornness of the internals list to consider namespaces back when the 5 changes were initially being discussed. On one hand I feel like this has ominous portents for PHP, but on the other, I’m really happy to have namespaces. For our domain, it still doesn’t make sense to jump ship to Groovy or Python, and it would take a lot of new terminals to push us over the edge. And while it’d be nice to see PHP not give more ammo to detractors, however menial, the discussion log makes it clear what issues they were struggling with.
Frederik Holmström points out another flaw with the backslash, as well, but many commenters note that the internals team knew there was no perfect solution here.
Tagged with: c#, code, computer science, constructs, Development, java, language, namespaces, php, programming, syntax, terminals
Posted in: Articles, Development
\ is for escape characters. No one uses it for anything else, anywhere.
namespace budgets;
class nightlyTasks;
budgets\nightlyTasks::staticMethod();
Are they fucking stupid or are they fucking stupid? I’ve been using PHP for a long time now, and this is the dumbest thing they’ve done to date.
The justifications for it hold about the same amount of weight as well, nothing. Nothing at all. There is no valid, logical, reasonable justification for having the BACKSLASH as a separator. It will confuse text processors, it will confuse windows users, and it will confuse anyone who has to use PHP after using another language.
Namespace::class::staticMethod()
There is no ambiguity there at all, none. You know what it all is.
Time to take a serious look at Ruby now.
I agree with your “I feel that throwing an error (or warning and choosing one) whenever that situation arises would be a perfectly acceptable solution.” as a way to determine whether A::B is function B in namespace A or method B in class A in case there are both.
Solution: Disallow classes with the same name as namespaces. (Like in java, but not exactly. Just use the same namespace (pardon) for namespaces and classes)
IE:
//File1.php
//File2.php
//index.php
//End IE
This should be simple to implement, and not risk the ire of the community! :D
It would seem the example code got scrubbed from my previous comment. Bugger. Let’s have another try:
Solution: Disallow classes with the same name as namespaces. (Like in java, but not exactly. Just use the same namespace (pardon) for namespaces and classes)
IE:
//File1.php
namespace foo;
function bar()
{
return “Broken”;
}
//File2.php
class foo
{
public static function bar()
{
return “Damaged”;
}
}
//index.php
include “file1.php”; //A-Ok!
include “file2.php”; //Fatal Error: Cannot redeclare namespace (foo) with class
echo foo::bar(); //Should have failed before getting here.
//In php 5.3.0, will output “Damaged”
//End IE
This should be simple to implement, and not risk the ire of the community! :D
I agree with ‘i_ate_god’. Using the backslash is without doubt the stupidest thing I’ve seen. It looks fucking ugly, difficult to read. I’m off to the Python camp.. bye bye Zend and PHP.