rfc:closures

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
rfc:closures [2009/03/17 14:27]
scottmac Note $this isn't available any more
rfc:closures [2009/12/15 22:41]
rquadling Fix list numbering
Line 16: Line 16:
  
 Closures and lambda functions can make programming much easier in several ways: Closures and lambda functions can make programming much easier in several ways:
- 
 ==== Lambda Functions ==== ==== Lambda Functions ====
  
 Lambda functions allow the quick definition of throw-away functions that are not used elsewhere. Imagine for example a piece of code that needs to call preg_replace_callback(). Currently, there are three possibilities to achieve this: Lambda functions allow the quick definition of throw-away functions that are not used elsewhere. Imagine for example a piece of code that needs to call preg_replace_callback(). Currently, there are three possibilities to achieve this:
- +  - Define the callback function elsewhere. This distributes code that belongs together throughout the file and decreases readability. 
-   - Define the callback function elsewhere. This distributes code that belongs together throughout the file and decreases readability. +  - Define the callback function in-place (but with a name). In that case one has to use function_exists() to make sure the function is only defined once. Here, the additional if() around the function definition makes the source code difficult to read. Example code:<code php>
- +
-   - Define the callback function in-place (but with a name). In that case one has to use function_exists() to make sure the function is only defined once. Here, the additional if() around the function definition makes the source code difficult to read. Example code: +
- +
-<code php>+
    function replace_spaces ($text) {    function replace_spaces ($text) {
      if (!function_exists ('replace_spaces_helper')) {      if (!function_exists ('replace_spaces_helper')) {
Line 35: Line 30:
    }    }
 </code> </code>
- +  - Use the present create_function() in order to create a function at runtime. This approach has several disadvantages: First of all, syntax highlighting does not work because a string is passed to the function. It also compiles the function at run time and not at compile time so opcode caches can't cache the function.
-   - Use the present create_function() in order to create a function at runtime. This approach has several disadvantages: First of all, syntax highlighting does not work because a string is passed to the function. It also compiles the function at run time and not at compile time so opcode caches can't cache the function. +
 ==== Closures ==== ==== Closures ====
  
 Closures provide a very useful tool in order to make lambda functions even more useful. Just imagine you want to replace 'hello' through 'goodbye' in all elements of an array. PHP provides the array_map() function which accepts a callback. If you don't want to hard-code 'hello' and 'goodbye' into your sourcecode, you have only four choices: Closures provide a very useful tool in order to make lambda functions even more useful. Just imagine you want to replace 'hello' through 'goodbye' in all elements of an array. PHP provides the array_map() function which accepts a callback. If you don't want to hard-code 'hello' and 'goodbye' into your sourcecode, you have only four choices:
- +  - Use create_function(). But then you may only pass literal values (strings, integers, floats) into the function, objects at best as clones (if var_export() allows for it) and resources not at all. And you have to worry about escaping everything correctly. Especially when handling user input this can lead to all sorts of security issues. 
-   - Use create_function(). But then you may only pass literal values (strings, integers, floats) into the function, objects at best as clones (if var_export() allows for it) and resources not at all. And you have to worry about escaping everything correctly. Especially when handling user input this can lead to all sorts of security issues. +  - Write a function that uses global variables. This is ugly, non-reentrant and bad style. 
- +  - Create an entire class, instantiate it and pass the member function as a callback. This is perhaps the cleanest solution for this problem with current PHP but just think about it: Creating an entire class for this extremely simple purpose and nothing else seems overkill. 
-   - Write a function that uses global variables. This is ugly, non-reentrant and bad style. +  - Don't use array_map() but simply do it manually (foreach). In this simple case it may not be that much of an issue (because one simply wants to iterate over an array) but there are cases where doing something manually that a function with a callback as parameter does for you is quite tedious.
- +
-   - Create an entire class, instantiate it and pass the member function as a callback. This is perhaps the cleanest solution for this problem with current PHP but just think about it: Creating an entire class for this extremely simple purpose and nothing else seems overkill. +
- +
-   - Don't use array_map() but simply do it manually (foreach). In this simple case it may not be that much of an issue (because one simply wants to iterate over an array) but there are cases where doing something manually that a function with a callback as parameter does for you is quite tedious.+
  
 Note: str_replace also accepts arrays as a third parameter so this example may be a bit useless. But imagine you want to do a more complex operation than simple search and replace. Note: str_replace also accepts arrays as a third parameter so this example may be a bit useless. But imagine you want to do a more complex operation than simple search and replace.
- 
 ===== Common misconceptions ===== ===== Common misconceptions =====
  
    - Lambda functions / closures are **not** a way of dynamically extending classes by additional methods at runtime. There are several other possibilities to do this, including the already present _ _call semantic.    - Lambda functions / closures are **not** a way of dynamically extending classes by additional methods at runtime. There are several other possibilities to do this, including the already present _ _call semantic.
- 
    - PHP's notion of scope is quite different than the notion of scope other languages define. Combine this with variable variables ($$var) and it becomes clear that automatically detecting which variables from the outer scope are referenced inside are closure is impossible. Also, since for example global variables are not visible inside functions either by default, automatically making the parent scope available would break with the current language concept PHP follows.    - PHP's notion of scope is quite different than the notion of scope other languages define. Combine this with variable variables ($$var) and it becomes clear that automatically detecting which variables from the outer scope are referenced inside are closure is impossible. Also, since for example global variables are not visible inside functions either by default, automatically making the parent scope available would break with the current language concept PHP follows.
  
rfc/closures.txt · Last modified: 2017/09/22 13:28 (external edit)