What is an anonymous function in PHP? Could you give me a simple example, please?
PHP.net has a manual page about Anonymous functions and on Wikipedia you can read about Anonymous functions in general.
Anonymous functions can be used to contain functionality that need not be named and possibly for short-term use. Some notable examples include closures.
Example from PHP.net
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
PHP 4.0.1 to 5.3
$foo = create_function('$x', 'return $x*$x;');
$bar = create_function("\$x", "return \$x*\$x;");
echo $foo(10);
PHP 5.3
$x = 3;
$func = function($z) { return $z *= 2; };
echo $func($x); // prints 6
PHP 5.3 does support closures but the variables must be explicitly indicated
$x = 3;
$func = function() use(&$x) { $x *= 2; };
$func();
echo $x; // prints 6
Examples taken from Wikipedia and php.net
The first results from Google gives you the answer:
http://php.net/manual/de/functions.anonymous.php
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]);
}, 'hello-world');
// outputs helloWorld
That you use a function as a parameter (in this example) is an "anonymous function". Anonymous since you don't declare the function explicit like "normally" do it.
function foo($match) {
return strtoupper($match[1]);
}
Related
I'm learning closures but I'm stuck with this:
function addPrefix($string) {
return function($prefix) use ($string) {
echo $prefix.$string;
};
}
$randomstring = "a test";
$c = addPrefix($randomstring);
echo $c("This is ");
Why is $prefix concatenated? It's not even called as an argument, I just don't get it.
Pay attention in your example there is 2 functions. addPrefix, and an anonymous function it addPrefix returns.
So, $c is this anonymous function (returned by addPrefix), which has the $prefix argument.
What is an anonymous function in PHP? Could you give me a simple example, please?
PHP.net has a manual page about Anonymous functions and on Wikipedia you can read about Anonymous functions in general.
Anonymous functions can be used to contain functionality that need not be named and possibly for short-term use. Some notable examples include closures.
Example from PHP.net
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
PHP 4.0.1 to 5.3
$foo = create_function('$x', 'return $x*$x;');
$bar = create_function("\$x", "return \$x*\$x;");
echo $foo(10);
PHP 5.3
$x = 3;
$func = function($z) { return $z *= 2; };
echo $func($x); // prints 6
PHP 5.3 does support closures but the variables must be explicitly indicated
$x = 3;
$func = function() use(&$x) { $x *= 2; };
$func();
echo $x; // prints 6
Examples taken from Wikipedia and php.net
The first results from Google gives you the answer:
http://php.net/manual/de/functions.anonymous.php
echo preg_replace_callback('~-([a-z])~', function ($match) {
return strtoupper($match[1]);
}, 'hello-world');
// outputs helloWorld
That you use a function as a parameter (in this example) is an "anonymous function". Anonymous since you don't declare the function explicit like "normally" do it.
function foo($match) {
return strtoupper($match[1]);
}
For example, if I do this:
function bar(&$var)
{
$foo = function() use ($var)
{
$var++;
};
$foo();
}
$my_var = 0;
bar($my_var);
Will $my_var be modified? If not, how do I get this to work without adding a parameter to $foo?
No, they are not passed by reference - the use follows a similar notation like the function's parameters.
As written you achieve that by defining the use as pass-by-reference:
$foo = function() use (&$var)
It's also possible to create recursion this way:
$func = NULL;
$func = function () use (&$func) {
$func();
}
NOTE: The following old excerpt of the answer (Jun 2012) was written for PHP < 7.0. As since 7.0 (Dec 2015) the semantics of debug_zval_dump() changed (different zval handling) the refcount(?) output of it differs nowadays and are not that much saying any longer (integers don't have a refcount any longer).
Validation via the output by not displaying $my_var changed (from 0) still works though (behaviour).
You can validate that on your own with the help of the debug_zval_dump function (Demo):
function bar(&$var)
{
$foo = function() use ($var)
{
debug_zval_dump($var);
$var++;
};
$foo();
};
$my_var = 0;
bar($my_var);
echo $my_var;
Output:
long(0) refcount(3)
0
A full-through-all-scopes-working reference would have a refcount of 1.
Closures are, almost by definition, closed by value, not by reference. You may "use by reference" by adding an & in the argument list:
function() use (&$var)
This can be seen in example 3 in the anonymous functions manual page.
No, they are not passed by reference.
function foo(&$var)
{
$foo = function() use ($var)
{
$var++;
};
$foo();
}
$my_var = 0;
foo($my_var);
echo $my_var; // displays 0
function bar(&$var)
{
$foo = function() use (&$var)
{
$var++;
};
$foo();
}
$my_var = 0;
bar($my_var);
echo $my_var; // displays 1
I have an anonymous function which is supposed to call itself. However, I have no variable or function name at hand, so I was hoping to find a function that could do return "this" in context of functions. Is there such a thing?
Here's an example:
$f = function() use($bar, $foo) {
// call this function again.
};
Calling like this:
call_user_func(__FUNCTION__);
Leads to this:
Warning: call_user_func() expects parameter 1 to be a valid callback,
function '{closure}' not found or invalid function name
If I try to put $f in the use-list, then it says the variable is not defined (because it is not yet).
__FUNCTION__ cannot be used in anonymous functions
Pass the variable holding the anonymous function as a reference in the 'use' clause....
$f = function() use($bar, $foo, &$f) {
$f();
};
Tip of the hat to this answer.
Okay, I found out the way to do this:
$f = function() use(&$f) {
$f();
};
$f();
The key thing is to pass $f as a reference. Thus PHP does not try to pass a value but a reference to a memory slot.
I have an anonymous function which is supposed to call itself.
I prefer to use call_user_func_array(__FUNCTION__, $params); when calling a recursive function.
As your example doesn't have any arguments then i guess call_user_func(__FUNCTION__); would be better suited.
You would expect and hope the following code would work but that would be too easy.
$bar = 10;
$foo = 0;
$f = function() use (&$bar,$foo) {
if($bar){ // condition needed to prevent infinite loop
echo $bar-- . PHP_EOL;
call_user_func(__FUNCTION__); // wont work
}
};
$f();
The __FUNCTION__ "Magic constant" is unavailable to closures so the code needs to be adapted to allow the passing of the function variable. we can make the function available by passing it as a regular argument or via the use statement.
Function passed as argument
$bar = 10;
$foo = 0;
$f = function( $__FUNCTION__ = null ) use (&$bar, $foo) {
if($__FUNCTION__ && $bar){
echo $bar-- . PHP_EOL;
call_user_func( $__FUNCTION__, $__FUNCTION__);
}
};
$f ( $f );
Function passed via use statement
$bar = 10;
$foo = 0;
$__FUNCTION__ = function() use (&$bar, $foo, &$__FUNCTION__) {
if($bar){
echo $bar-- . PHP_EOL;
call_user_func( $__FUNCTION__ );
}
};
$__FUNCTION__();
Working example, click edit-> ideone it! to re-run code.
http://www.php.net/manual/en/language.constants.predefined.php
Edit: Posted before code was given. Of course it doesn't work on anonymous functions.
call_user_func(__FUNCTION__, $param1, $param2);
call_user_func_array(__FUNCTION__, $params);
function i_dont_know() {
call_user_func(__FUNCTION__,$params);
//or
$funcname = __FUNCTION__;
$funcname($params);
}
What are the differences between closures in JS and closures in PHP? Do they pretty much work the same way? Are there any caveats to be aware of when writing closures in PHP?
One difference is how both cope with storing the context in which an anonymous function is executed:
// JavaScript:
var a = 1;
var f = function() {
console.log(a);
};
a = 2;
f();
// will echo 2;
// PHP
$a = 1;
$f = function() {
echo $a;
};
$a = 2;
$f();
// will result in a "PHP Notice: Undefined variable: a in Untitled.php on line 5"
To fix this notice you'll have to use the use syntax:
$a = 1;
$f = function() use ($a) {
echo $a;
};
$a = 2;
$f();
// but this will echo 1 instead of 2 (like JavaScript)
To have the anonymous function behave somehow like the JavaScript counterpart you'll have to use references:
$a = 1;
$f = function() use (&$a) {
echo $a;
};
$a = 2;
$f();
// will echo 2
I think this is the most striking difference between JavaScript and PHP closures.
Second difference is that every JavaScript closure has a this context available which means, that you can use this inside the closure itself (although it's often quite complicated to figure out what this actually refers to) - PHP's current stable version (PHP 5.3) does not yet support $this inside a closure, but PHP's upcoming version (PHP 5.4) will support $this binding and rebinding using $closure->bind($this) (See the Object Extension RFC for more info.)
Third difference is how both languages treat closures assigned to object properties:
// JavaScript
var a = {
b: function() {}
};
a.b(); // works
// PHP
$a = new stdClass();
$a->b = function() {};
$a->b(); // does not work "PHP Fatal error: Call to undefined method stdClass::b() in Untitled.php on line 4"
$f = $a->b;
$f(); // works though
The same is true if closures are assigned to properties in class definitions:
class A {
public $b;
public function __construct() {
$this->b = function() {};
}
public function c() {
$this->b();
}
}
$a = new A();
// neither
$a->b();
// nor
$a->c();
// do work
Fourth difference: JavaScript Closures are full fledged objects, wheres in PHP they are restricted objects. For instance, PHP Closures cannot have properties of their own:
$fn = function() {};
$fn->foo = 1;
// -> Catchable fatal error: Closure object cannot have properties
while in JavaScript you can do:
var fn = function() {};
fn.foo = 1;
fn.foo; // 1
Fifth difference: Returned closures can be immediately called upon in Javascript:
var fn = function() { return function() { alert('Hi');}}
fn()();
Not in PHP:
$fn = function() { return function() { echo('Hi');};};
$fn()(); // syntax error
The only thing I've found in PHP (that is totally cool and really handy!) is the ability to use them as getters and setters in classes which was always a nightmare to achieve before, JavaScript can be used in the same way but they do both act almost identically from what I've seen.
I'm not sure about the namespacing convention differences between the two but as #Rijk pointed out there is a section on the PHP website dedicated to them
<?php
class testing {
private $foo = 'Hello ';
public $bar = 'Bar';
#Act like a getter and setter!
public static $readout = function ($val = null) {
if (!empty($val)) {
testing::$readout = $val;
}
return testing::$readout;
}
}
They are also really great for...
Looping through items with a controller rather than a new for/each loop on the page
Great for supplying as arguments to functions/classes
Whats annoying about them is...
You can't typecast them, since they're just functions...
They do pretty much work the same way. Here's more information about the PHP implementation: http://php.net/manual/en/functions.anonymous.php
You can use a closure (in PHP called 'anonymous function') as a callback:
// return array of ids
return array_map( function( $a ) { return $a['item_id']; }, $items_arr );
and assign it to a variable:
$greet = function( $string ) { echo 'Hello ' . $string; }; // note the ; !
echo $greet('Rijk'); // "Hello Rijk"
Furthermore, anonymous function 'inherit' the scope in which they were defined - just as the JS implementation, with one gotcha: you have to list all variables you want to inherit in a use():
function normalFunction( $parameter ) {
$anonymous = function() use( $parameter ) { /* ... */ };
}
and as a reference if you want to modify the orignal variable.
function normalFunction( $parameter ) {
$anonymous = function() use( &$parameter ) { $parameter ++ };
$anonymous();
$parameter; // will be + 1
}