rfc:closure_apply

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
rfc:closure_apply [2014/07/30 00:30] – v0.2, changed name from ::apply to ::call ajfrfc:closure_apply [2014/08/17 19:31] – Opened vote ajf
Line 1: Line 1:
 ====== PHP RFC: Closure::call ====== ====== PHP RFC: Closure::call ======
-  * Version: 0.2 +  * Version: 0.2.1 
-  * Date: 2014-07-29+  * Date: 2014-07-29, put to internals 2014-08-03, latest 2014-08-17
   * Author: Andrea Faulds, ajf@ajf.me   * Author: Andrea Faulds, ajf@ajf.me
-  * Status: Draft+  * Status: In Voting
   * First Published at: http://wiki.php.net/rfc/closure_apply   * First Published at: http://wiki.php.net/rfc/closure_apply
  
 ===== Introduction ===== ===== Introduction =====
  
-PHP has had Closures since 5.3, and since 5.4 has had ''Closure::bind'' (static method) and ''Closure::bindTo'' (method) to allow creating new closures that have ''$this'' bound to a specific method. However, it has not been possible to bind at call-time without creating a new closure, making binding to different objects and calling for multiple objects cumbersome and inefficient (at least two statements are needed, and a new closure must be created and immediately disposed of for each).+PHP has had Closures since 5.3, and since 5.4 has had ''Closure::bind'' (static method) and ''Closure::bindTo'' (method) to allow creating new closures that have ''$this'' bound to a specific method. However, it has not been possible to bind at call-time, and you must instead create temporary new closure, making calling bound to multiple objects cumbersome and inefficient (at least two statements are needed, and a new closure must be created and immediately disposed of for each).
  
 ===== Proposal ===== ===== Proposal =====
Line 40: Line 40:
 </code> </code>
  
-My function referencing as closures proposal similarly relaxes the requirement for a scoped closure to be bound or static out of necessity, and ''->call'' would be highly useful to that proposal, so this RFC can be considered a prerequisite to it.+My [[rfc:function_referencing|Function Referencing as Closures]] proposal similarly relaxes the requirement for a scoped closure to be bound or static out of necessity, and ''->call'' would be highly useful to that proposal, so this RFC can be considered a prerequisite to it. 
 + 
 +''call'' would be useful in many cases where ''bindTo'' is used (e.g. [[https://github.com/search?l=php&p=34&q=bindTo&ref=cmdform&type=Code|search of GitHub for bindTo]]). A search on GitHub reveals [[https://github.com/search?q=bindTo+call_user_func&type=Code&ref=searchresults|many using bindTo and immediately calling with call_user_func]], which would now not be necessary as they could just use ''call''
 + 
 +===== Performance ===== 
 + 
 +While not the sole benefit of this RFC, it can provide a performance improvement in some applications. 
 + 
 +We use two test scripts, ''a.php'' using bindTo and ''b.php'' using call. 
 + 
 +<file php a.php> 
 +$a = function () { 
 +    return $this->x; 
 +}; 
 +class FooBar { 
 +    private $x = 3; 
 +
 +$foobar = new FooBar; 
 +for ($i = 0; $i < 100000; $i++) { 
 +    $x = $a->bindTo($foobar, "FooBar"); 
 +    $x(); 
 +
 +</file> 
 + 
 +<file php b.php> 
 +$a = function () { 
 +    return $this->x; 
 +}; 
 +$a = $a->bindTo(NULL, "FooBar", true); 
 +class FooBar { 
 +    private $x = 3; 
 +
 +$foobar = new FooBar; 
 +for ($i = 0; $i < 100000; $i++) { 
 +    $a->call($foobar); 
 +
 +</file> 
 + 
 +When run for 100000 iterations, ''b.php'' shows a 2x improvement over ''a.php'': 
 + 
 +<code> 
 +andreas-air:php-src ajf$ time sapi/cli/php a.php 
 +  
 +real 0m0.259s 
 +user 0m0.208s 
 +sys 0m0.012s 
 +  
 +andreas-air:php-src ajf$ time sapi/cli/php b.php 
 +  
 +real 0m0.100s 
 +user 0m0.094s 
 +sys 0m0.005s 
 +</code> 
 +  
 +If we up the iterations by 10x, the result is the same: 
 + 
 +<code> 
 +andreas-air:php-src ajf$ time sapi/cli/php a.php 
 +  
 +real 0m1.966s 
 +user 0m1.959s 
 +sys 0m0.005s 
 +  
 +andreas-air:php-src ajf$ time sapi/cli/php b.php 
 +  
 +real 0m0.962s 
 +user 0m0.897s 
 +sys 0m0.015s 
 +</code>
  
 ===== Backward Incompatible Changes and RFC Impact ===== ===== Backward Incompatible Changes and RFC Impact =====
Line 54: Line 122:
 Partial application (where a new closure is returned that pre-fills the first X arguments) is a possibly worthwhile (though more difficult to implement) addition. Partial application (where a new closure is returned that pre-fills the first X arguments) is a possibly worthwhile (though more difficult to implement) addition.
  
-===== Proposed Voting Choices =====+===== Vote =====
  
 This is not a language change, so a straight 50%+1 Yes/No vote can be held. This is not a language change, so a straight 50%+1 Yes/No vote can be held.
 +
 +Voting started 2014-08-17 and ends 2014-08-24.
 +
 +<doodle title="Merge Closure::call() patch into master?" auth="ajf" voteType="single" closed="false">
 +   * Yes
 +   * No
 +</doodle>
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
  
 A branch which implements this (with a test) based on the current master can be found here: https://github.com/TazeTSchnitzel/php-src/tree/Closure_apply A branch which implements this (with a test) based on the current master can be found here: https://github.com/TazeTSchnitzel/php-src/tree/Closure_apply
 +
 +There is a pull request for review purposes here: https://github.com/php/php-src/pull/775
  
 ===== References ===== ===== References =====
  
-  * As aforementioned, my [[rfc:function_referencing|Function Referencing as Closures]] RFC has this RFC as a prerequisite+  * As previously mentioned, my [[rfc:function_referencing|Function Referencing as Closures]] RFC has this RFC as a prerequisite
  
 ===== Changelog ===== ===== Changelog =====
  
 +  * v0.2.1 - Added performance section
   * v0.2 - ''Closure::apply'' renamed to ''Closure::call'' for consistency with JavaScript (former takes an array in JS à la ''call_user_func_array'', latter bare parameters)   * v0.2 - ''Closure::apply'' renamed to ''Closure::call'' for consistency with JavaScript (former takes an array in JS à la ''call_user_func_array'', latter bare parameters)
   * v0.1 - Initial version   * v0.1 - Initial version
rfc/closure_apply.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1