Request for Comments: Namespaces with curly braces
- Version: 1.0
- Date: 2008-08-31
- Author: Marcus Boerger helly@php.net, Felipe Pena felipe@php.net
- Status: Under Discussion
- First Published at: http://wiki.php.net/rfc/namespacecurlies
- Initial mails: 2008.08.28 2008.08.03 (and lots more)
This RFC deals with the open questions in regards to namespaces that came up during the alpha release of PHP 5.3.
Introduction
During alpha phase of PHP 5.0 there was a namespace implementation that was very close to the one of C++. Because an inconsistency between namespace separator '::' and ternary operator's ':' could not be solved, namespace were finally removed. Durning development of PHP 5.3 namespace came up again and a solution for the conflict was found. The implementation did undergo several steps and small changes and finally settled down with support for multiple namespaces per file using the keyword 'namespace' in a simple statement that would be closed by a ';' and changed all name lookup in the code that follows.
The following issues have been identified:
- The keyword 'namespace'.
- Namespace as kind of labels versus namespaces as blocks.
- Statements outside namespaces.
- Nested namespace support.
The keyword 'namespace'
The keyword has been discussed several times and even though a real explanation has not been found the agreement is that we think of namespaces literally. Furthermore the names are in no way related to the file system structure as is with Java packages for instance. The immediate conclusion is that we stick to the keyword. This also has the advantage that many people have seen namespace as a reserved keyword even when it was not a reserved keyword. This part is thus not open for discussion.
Namespace as kind of labels versus namespaces as blocks
We need to describe how we think of namespaces. Right now the PHP runtime treats namespaces as simple text replacements. That is the runtime will only resolve names in the current and global namespace. With this in mind it does not matter whether we do namespaces as blocks or labels. This difference comes from experience, comparison to existing implementations, expectation and consistency.
- Experience:
- PHP has labels and blocks.
- Labels do not influence the code after the label.
- PHP also offers alternative syntax for control structures. This looks like 'if (true): echo “then”;'. This alternative syntax is being avoided by most developers today. In fact every once in a while people ask to remove support for it.
- Some people require to indent anything within curly braces (often because of their editor settings).
- Nearly all C++ editors are set to not indent on namespaces.
- Comparison:
- Java and C++ are the closest, wide spread languages that support namespaces.
- C++ uses the keywords 'namespace' and 'use' and only allows blocks. Nesting and multiple namespaces are allowed.
- Java uses the keywords 'package' and 'import' and requires the file system to reflect what is defined in the code. Packages are defined in a single statement and only one package is allowed per file.
- Expectation:
- Usually PHP tries to be close to an existing implementation.
- Many developers were expecting to simply implement what was done during PHP 5.0 alpha phase (namespace as in C++).
- With the new implementation and no blocks, many people expected one namespace per file.
- Since fewer files means faster execution, many people simply concatenate PHP scripts. Their expectation is to be able to do this for code that uses namespaces as well.
- PHP will add Phar archive support and thus does not really require source concatenation any longer.
- Consistency:
- The common syntax is using blocks for anything that influences following code.
- The alternative is to use 'namespace name:' rather than 'namespace name; /*...*/ endnamespace;' is done for all other alternate forms.
- Only control structures can be followed by a statement without either ';' or ':', however they only allow a single statement.
- Issues:
- When concatenating a file with a namespace and one without a namespace, the second file gets pulled into the namespace unless the namespace used curly braces.
Statements outside namespaces
PHP needs to support compiler caches and their way of name resolution. This is at the moment bound to filenames and as a consequence we cannot allow any code that potentially requires name lookup. This means we could only allow statements outside namespaces that either never do name lookup or we need special forms of those that disallow name lookup outside namespaces. In fact this seems only relevant to define() and include/require.
Include as well as require do not carry over namespace information. This is a problematic as it allows for functions with mixed inner namespace resolution:
--foo.php
namespace foo; function test{} { echo __NAMESPACE__ . "\n"; include 'bar.php'; echo __NAMESPACE__ . "\n"; }
--bar.php
// namespace bar; echo __NAMESPACE__ . "\n";
The above shows 'foo', '', 'foo'. Further more the namespace statement in bar.php is legal and leads to 'foo', 'bar', foo'. It also means we kind of allow nested namespaces. The reason we need to allow include/require inside functions/methods is to support the common way of dynamic module loading.
We do not want to add special forms of require/include that do or not do carry over the current namespace and disallow namespace declarations if carried over.
This leaves us with define() as well as with require and include without carrying over the current namespace. For define we clearly allow name resolution:
$> php -r 'class C { const c = 42; } define(“F”, C::c);'
This in some way also applies to require and include because the both allow constants and variables. However define is a function and does not allow special treatment in the parser. Require and include on the other hand are parser states and take single expression as parameter. This expression can easily be turned into two different things. A full expression and a string only. The string only version can be allowed outside namespaces.
Nested namespace support
PHP uses simple text replacement for namespace resolution and thus can easily allow nested namespaces without any technical issue whatsoever.
Proposal and Patch
We propose to add namespaces as block structures and drop 'namespace foo;' in favor of 'namespace foo: ; endnamespace;', as in this patch. The tests are provided in a second patch.
In a second step nesting namespaces should be supported. This can easily be done by simply removing the corresponding error messages.