rfc:use_function

# Differences

This shows you the differences between two versions of the page.

 rfc:use_function [2013/08/29 14:28]igorw [Vote] close the vote rfc:use_function [2017/09/22 13:28] Line 1: Line 1: - ====== PHP RFC: Importing namespaced functions ====== - * Version: 1.1.1 - * Date: 2013-05-02 - * Author: Igor Wiedler, igor@wiedler.ch - * Status: Voting - * 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/388|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