Req #61790 [Com]: Feature Request for create_closure() function
Edit report at https://bugs.php.net/bug.php?id=61790&edit=1
ID: 61790
Comment by: nikic@php.net
Reported by: thegreatall at gmail dot com
Summary: Feature Request for create_closure() function
Status: Open
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'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.
Previous Comments:
------------------------------------------------------------------------
[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
Thread (3 messages)