Edit report at https://bugs.php.net/bug.php?id=61790&edit=1
ID: 61790 Updated by: ahar...@php.net Reported by: thegreatall at gmail dot com Summary: Feature Request for create_closure() function -Status: Open +Status: Wont fix Type: Feature/Change Request Package: *Programming Data Structures Operating System: N/A PHP Version: Irrelevant Block user comment: N Private report: N New Comment: I think Nikita's covered this well. create_function() is just eval() in a slight cloak anyway, and given that the two are generally discouraged, I don't think there's much reason to add another function in the same ilk when it can be emulated in userspace at the cost of slightly polluting the global function table. Previous Comments: ------------------------------------------------------------------------ [2012-04-20 19:46:16] ni...@php.net I'm not sure I understand your issue. create_function() is just a wrapper around eval(). The evils of eval() are also the evils of create_function(). And, as you showed, this is trivial to implement in userland. I really wouldn't like PHP to add further functions encouraging bad coding style. ------------------------------------------------------------------------ [2012-04-20 15:55:53] thegreatall at gmail dot com Description: ------------ As I am sure many of you know of the create_function() function, but this actually creates a named function in the global scope. This can be undesirable if a user is creating an unknown number of functions because it fills memory with named execution points but once the variable looses it's references it should be cleaned up by the garbage collector. I am asking for a create_closure() function to do the same thing that create_function does, but return a closure instead of a string containing the name to a newly created named function. You can simulate a function like this using eval, but we all know the evils of eval. An example of why someone would like to do this: A developer creates a framework which handles classes to records in the database. When records get updated/created/pulled it has a "hooks" on the record level that allows custom "hooks" to be installed on the record and executed on the specific records. The code for the hook is not accessible/modifiable by the user only the developers that have database access, but each user may install that hook on a specific record. So if we had a hook that IMs users when specific records are modified in the database and 5000 users want this hook installed on that record it installs 5000 hooks on this record and creates 5000 named functions but each function would only be executed once and can/should be cleaned by the garbage collector. (I know there is a more optimal way to achieve this specific example, but if I need to change the list of arguments it has to recompile the function creating a new named function. This is not an issue with closures because they are not named functions and the garbage collector cleans them up after they are de-referenced. Test script: --------------- <?php // Example 1 function create_fn($i){ return eval('return function ($g){ echo "'.$i.' - $g\n"; };'); } for($i=0;$i<100000;$i++){ $fn = create_fn($i); if($i % 10000 == 0) $fn(memory_get_usage(true)); } <?php // Example 2 function create_fn($i){ return function ($g) use ($i){ echo "$i - $g\n"; }; } for($i=0;$i<100000;$i++){ $fn = create_fn($i); if($i % 10000 == 0) $fn(memory_get_usage(true)); } <?php // Example 1 function create_fn($i){ return create_function('$g', 'echo "'.$i.' - $g\n";'); } for($i=0;$i<100000;$i++){ $fn = create_fn($i); if($i % 10000 == 0) $fn(memory_get_usage(true)); } Expected result: ---------------- Result 1: (slower than 2, does NOT snowball memory) count - memory ----------------------- 0 - 262144 10000 - 4194304 20000 - 4194304 30000 - 4194304 40000 - 4194304 50000 - 4194304 60000 - 4194304 70000 - 4194304 80000 - 4194304 90000 - 4194304 Result 2: (really fast consumes very little memory) count - memory ----------------------- 0 - 262144 10000 - 262144 20000 - 262144 30000 - 262144 40000 - 262144 50000 - 262144 60000 - 262144 70000 - 262144 80000 - 262144 90000 - 262144 Result 3: count - memory (slow and consumes tons of memory and snowballs memory) ----------------------- 0 - 262144 10000 - 8126464 20000 - 16515072 30000 - 24641536 40000 - 31981568 50000 - 39583744 60000 - 47185920 70000 - 54525952 80000 - 62128128 90000 - 69730304 ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=61790&edit=1