====== PHP RFC: Importing namespaced functions ====== * Version: 1.1.1 * Date: 2013-05-02 * Author: Igor Wiedler, igor@wiedler.ch * Status: Implemented (PHP-5.6) * First Published at: http://wiki.php.net/rfc/use_function ===== Introduction ===== PHP offers the ability to import namespaces and types (classes/interfaces/traits) via the **use** statement. This capability however does not exist for functions. As a result, working with namespaced functions is rather cumbersome. A function can only be referenced without fully qualifying it, if the calling code is in the same namespace as the function: namespace foo\bar { function baz() { return 'foo.bar.baz'; } } namespace foo\bar { function qux() { return baz(); } } namespace { var_dump(foo\bar\qux()); } It is possible to avoid fully qualifying the name by importing the namespace that the function is defined in. But that namespace must still be referenced when calling the function: namespace foo\bar { function baz() { return 'foo.bar.baz'; } } namespace { use foo\bar as b; var_dump(b\baz()); } You cannot import the function directly. PHP does not currently support that. ===== Proposal ===== The proposal is to combine existing keywords to a new sequence that allows importing functions into a namespace. This should make namespaced functions less of a pain to use and discourage placing them in the global namespace. Since functions and classes are in separate namespaces, it is not feasible to use the **use** keyword for both, as it would likely result in conflicts and overhead. Instead of introducing a new keyword, it would be possible to combine **use** and **function** to a sequence. This new **use function** combo would work as follows: namespace foo\bar { function baz() { return 'foo.bar.baz'; } function qux() { return baz(); } } namespace { use function foo\bar\baz, foo\bar\qux; var_dump(baz()); var_dump(qux()); } All of this applies not only to functions, but also to namespaced constants. For consistency, a **use const** sequence should also be introduced, that does the same thing for constants: namespace foo\bar { const baz = 42; } namespace { use const foo\bar\baz; var_dump(baz); } Just like classes, it should be possible to alias imported functions and constants: namespace { use function foo\bar as foo_bar; use const foo\BAZ as FOO_BAZ; var_dump(foo_bar()); var_dump(FOO_BAZ); } ===== General questions & answers ===== ==== Why not just import a namespace? ==== While it's true that you can import a namespace and alias it to a single character, this is not necessary for classes, so it makes no sense to require it for functions. There are two specific use cases where importing a function can significantly improve the readability of code. === Tiny libraries === Libraries which are just collections of functions can benefit from this. They can be namespaced under (for example) the author's name, e.g. `igorw\compose()`. This prevents namespace clashes. The users of that function don't care about who the author is, they just want `compose()`. They don't want to invent a new meaningless alias just to use the function. === Domain specific languages === Functions can be treated as an extension of the language, or to be used to create a custom meta-language. An example of this is building a HTML tree, but this could be anything, really. A HTML building DSL: use function html\div, html\p, html\em; $html = div(p('Some', em('Text'))); Avoiding noise and clutter is really important to make this usable and readable. ==== Global namespace fallback ==== Currently PHP will search for functions in the local namespace first, then fall back to the global one. For functions imported by a **use function** statement, there should be no fallback. namespace foo\bar { function strlen($str) { return 4; } } namespace { use function foo\bar\strlen; use function foo\bar\non_existent; var_dump(strlen('x')); var_dump(non_existent()); } The call to **strlen** is no longer ambiguous. **non_existent** is no longer looked up in the global namespace. ==== Why is "use function" needed instead of just "use"? ==== In PHP, functions and classes are stored in separate namespaces. A function `foo\bar` and a class `foo\bar` can co-exist, because it is possible to infer from the context if the symbol is used as a class or a function: namespace foo { function bar() {} class bar {} } namespace { foo\bar(); // function call new foo\bar(); // class instantiation foo\bar::baz(); // static method call on class } If **use** were changed to support functions as well, it would introduce BC breaks. An example: namespace { function bar() {} } namespace foo { function bar() {} } namespace { use foo\bar; bar(); } The behaviour changed, when **use** was changed. Depending on your PHP version, a different function will be called. ==== Function autoloading ==== Function autoloading is beyond the scope of this RFC. ===== Backward Incompatible Changes ===== No BC breaks. ===== Proposed PHP Version(s) ===== PHP 5.6.x ===== SAPIs Impacted ===== None. ===== Impact to Existing Extensions ===== None. ===== New Constants ===== None. ===== php.ini Defaults ===== None. ===== Open Issues ===== None yet. ===== Patches and Tests ===== There is a patch against PHP-5.6 (currently master) [[https://github.com/php/php-src/pull/526|as a GitHub pull request]]. ===== References ===== * Importing namespaces: http://php.net/manual/en/language.namespaces.importing.php ===== Rejected Features ===== - None. ===== Vote ===== The voting period is 15.08.2013 until 29.08.2013. * Yes? * No? ===== Changelog ===== * 2013-08-08 1.1.1 Added example of aliasing * 2013-07-23 1.1.0 Added support for constants with `use const` * 2013-07-22 1.0.1 FAQ "why 'use function'?" * 2013-07-19 1.0.0 First version published for discussion