Use of Anonymous Functions in PHP - php

This question may be silly. But an anonymous function does not really seem that anonymous to me. Maybe I am understanding it wrong, but an anonymous function must be stored in some variable, so it can later be referenced by this variable. If this is the case, what makes the below function so anonymous or so different than a regular function (other than the ability to store the function itself in a variable)? Or to word it differently, how is an anonymous function MORE useful than a regular function?
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
function greet($name)
{
printf("Hello %s\r\n", $name);
}
$greet('World');
$greet('PHP');
greet('World');
greet('PHP');
?>

Imagine you want to sort a list of users by username. Instead of defining a named comparison function that you're only going to use once, you can use an anonymous function:
usort($users, function($a, $b) {
return strcmp($a['username'], $b['username']);
});

The function itself has no name, as you show in your example you can still create a "real" function with the "same name". They're usually used like this as callbacks, which may seem more "anonymous":
foo(function ($bar) { ... });

One useful thing about anonymous (or lambda, if you prefer) functions is that they allow for creating your callback function inline with the code that needs it, rather than setting up a global function that will only be used in that one context. For instance:
$foo = native_function($bar, callback_function);
can be instead :
$foo = native_function($bar, function() { return $bar + 1; } );
Another handy thing about anonymous functions is that the variable you set it to calls that function every time, so it's not storing a value, but deriving it instead. This is great if a variable represents some derived value. Example:
$tax = .1;
$total = function() use (&$price, &$tax) { return $price * (1 + $tax); };
$price = 5.00;
echo $total(); // prints 5.50
$price = $price + 1;
echo $total(); // prints 6.60
$discount = $total() - 2;
echo $discount; // prints 4.60;
Instead of having to call a function like get_total and passing it $price every time, you interact with a variable that is always set to the newest value because it derives that value every time with the lambda function.

Related

Call function in the function

how to about my code i cant call function inline function
Here is my code:
function antus(){
global $vidi;
$vidi = random_int(100, 999);
}
function bntus(){
global $hexa;
antus();
$hexa = 5 * $vidi;
echo $hexa;
}
bntus();
Thank you
You're missing return in both function and no need for global
function antus(){
$vidi = random_int(100, 999);
return $vidi;
}
function bntus(){
$v = antus();
$hexa = 5 * $v;
return $hexa;
}
$a = bntus();
echo $a;
While it's poor style to use global variables instead of parameters and returns, I'll show you how you would do it.
You don't need global $hexa, since you never use that variable outside the function. But you need to put global $vidi in bntus() so that it can access that variable.
Also, the name of the function to get a random integer is rand(), not random_int().
function antus(){
global $vidi;
$vidi = rand(100, 999);
}
function bntus(){
global $vidi;
antus();
$hexa = 5 * $vidi;
echo $hexa;
}
bntus();
DEMO
First of all your code doesn't run at all because it doesn't compile. The PHP statements end with ; (but in your code it is missing in several places).
Properly formatted and without syntax errors, the code of function bntus() should look like this:
function bntus()
{
global $hexa;
antus();
$hexa = 5 * $vidi;
echo $hexa;
}
Now it runs but it doesn't produce the result you expect because the variable $vidi is not initialized.
If you think that the call to function antus() puts some random value in $vidi then you are wrong. The function antus() puts a value in the global variable $vidi. That variable is not accessible in function bntus(); it uses an uninitialized local variable with the same name.
Read about the scope of variables in PHP.
Declaring $vidi as global in function bntus() produces the expected results but using global variables is a very poor programming technique. It is out of fashion for about 40-50 years now because it makes the programs difficult to develop and maintain.
A better approach is to let the functions return the values they compute:
function antus()
{
return random_int(100, 999);
}
function bntus()
{
return 5 * antus();
}
echo(bntus());
One more thing: you didn't post the code of function random_int() but if it does what its name says then you don't need an user function for that. PHP already provides the rand() function that, when is invoked with two integer arguments, returns a random integer number from the interval bounded by the two input values (including them).
This means the call rand(100, 999) returns a random integer number $n, 100 <= $n <= 999.

Passing by reference in PHP (function definition and variables)

What's the difference between function &foo() and function foo(&$var) in PHP?
Example in code:
<?php
function foo(&$var){
$var++;
}
function &bar(){
$a= 5;
return $a;
}
foo( bar() );
The main issue here is who wants to alter or read whose variable.
In the first example you want the outer variable to be changed by the function. In example two you want the outer world to change the inner variable. And you can get changed values from the different scope.
A better use case for the second version would be:
class example {
public $test = 23;
public function &exposeTest() {
return $this->test;
}
}
$example1 = new example;
$testref = &$example1->exposeTest();
$testref++;
echo($example1->test); // 24
$example1->test++;
echo($testref); // 25
So it is not really a difference besides design issues and without OOP may not matter any way.

Filter php function return value

Lets say we have function:
function foo() {
return "bar";
}
Is it possible to add some filter to foo() function, for example to make it returning double value like "barbar" without changing the function itself.
So we would have:
foo(); //returns "bar"
function filter($&val) {
$val = $val . $val;
}
add_filter_to_function('foo','filter');
foo(); //returns "barbar"
And then anywhere foo() is used, it would return filtered value without changing code that calls foo() to something like foo() . foo() and without changing the function itself
In PHP, there is a RunKit extension (runkit_function_redefine() in particular for your question) which allow you to manipulate with code's objects (such as function or classes) on the fly.
But I think you're doing something wrong if you need to change your function's code on that way - so may be you should reconsider your goal and resolve your original problem with another tools.
If you need to call your function with some parameters in some special cases, you can use something like:
function foo($x, $y)
{
//do stuff
}
function bar($x, $y, $z)
{
//do stuff with $z?
foo($x, $y);
}
and use bar() instead of foo() then - in certain places (which you need to adjust)
You cannot internally change the return value of a function, if it's static.
If you had foo($var), you could change the state of $var, and everytime you call foo($var) lately, you would recieve the new value, but in your case it's almost not possible.
You have to call the other function everytime you need double value:
function foo() {
return 'bar';
}
function filter($func) {
return $func.$func;
}
echo filter(foo());
Turn your function into an object method and then the add_filter_to_function would add the filter to the object.
Then when you called the function it would be able to use the filters that have been assigned to the object the function belongs to.
You could simply concatenate the value on itself:
$val = foo();
$val .= $val;
or if your function really needs to have a double value returned, then you should probably look at refactoring your foo() function, because it doesn't seem to do what you want.
Either that, or accept one of the other answers that tells you to wrap foo() around another function.

PHP References: An understanding

I have seen in my journey to creaitng and building some of my php applications, the & symbol within front of vars, = and class names.
I understand that these are PHP References, but the docs i have seen and looked at seem to just not explain it in a way that i understand or confusing. How can you explain the following examples that i have seen to make them more understandable.
public static function &function_name(){...}
$varname =& functioncall();
function ($var, &$var2, $var3){...}
Much appreciated
Let's say you have two functions
$a = 5;
function withReference(&$a) {
$a++;
}
function withoutReference($a) {
$a++;
}
withoutReference($a);
// $a is still 5, since your function had a local copy of $a
var_dump($a);
withReference($a);
// $a is now 6, you changed $a outside of function scope
var_dump($a);
So, passing argument by reference allows function to modify it outside of the function scope.
Now second example.
You have a function which returns a reference
class References {
public $a = 5;
public function &getA() {
return $this->a;
}
}
$references = new References;
// let's do regular assignment
$a = $references->getA();
$a++;
// you get 5, $a++ had no effect on $a from the class
var_dump($references->getA());
// now let's do reference assignment
$a = &$references->getA();
$a++;
// $a is the same as $reference->a, so now you will get 6
var_dump($references->getA());
// a little bit different
$references->a++;
// since $a is the same as $reference->a, you will get 7
var_dump($a);
Reference functions
$name = 'alfa';
$address = 'street';
//declaring the function with the $ tells PHP that the function will
//return the reference to the value, and not the value itself
function &function_name($what){
//we need to access some previous declared variables
GLOBAL $name,$address;//or at function declaration (use) keyword
if ($what == 'name')
return $name;
else
return $address;
}
//now we "link" the $search variable and the $name one with the same value
$search =& function_name('name');
//we can use the result as value, not as reference too
$other_search = function_name('name');
//any change on this reference will affect the "$name" too
$search = 'new_name';
var_dump($search,$name,$other_search);
//will output string 'new_name' (length=8)string 'new_name' (length=8)string 'alfa' (length=4)
Usually you use the method with Objects that implemented the same interface, and you want to choose the object you want to work with next.
Passing by reference:
function ($var, &$var2, $var3){...}
I'm sure you saw the examples, so I'll just explain how and when to use it.
The basic scenario is when do you have a big logic that you want to apply to a current object/data, and you do not wish to make more copies of it (in memory).
Hope this helps.

Pass a function by reference in PHP

Is it possible to pass functions by reference?
Something like this:
function call($func){
$func();
}
function test(){
echo "hello world!";
}
call(test);
I know that you could do 'test', but I don't really want that, as I need to pass the function by reference.
Is the only way to do so via anonymous functions?
Clarification: If you recall from C++, you could pass a function via pointers:
void call(void (*func)(void)){
func();
}
Or in Python:
def call(func):
func()
That's what i'm trying to accomplish.
For what it's worth, how about giving something like this a shot? (Yes, I know it's an anonymous function which was mentioned in the post, but I was disgruntled at the abundance of replies that did not mention closures/function-objects at all so this is mostly a note for people running across this post.)
I don't use PHP, but using a closure appears to work in PHP 5.3 (but not PHP 5.2) as demonstrated here. I am not sure what the limitations, if any, there are. (For all I know the closure will eat your children. You have been warned.)
function doIt ($fn) {
echo "doIt\n";
return $fn();
}
function doMe () {
echo "doMe\n";
}
// I am using a closure here.
// There may be a more clever way to "get the function-object" representing a given
// named function, but I do not know what it is. Again, I *don't use PHP* :-)
echo doIt(function () { doMe(); });
Happy coding.
The problem with call_user_func() is that you're passing the return value of the function called, not the function itself.
I've run into this problem before too and here's the solution I came up with.
function funcRef($func){
return create_function('', "return call_user_func_array('{$func}', func_get_args());");
}
function foo($a, $b, $c){
return sprintf("A:%s B:%s C:%s", $a, $b, $c);
}
$b = funcRef("foo");
echo $b("hello", "world", 123);
//=> A:hello B:world C:123
ideone.com demo
No, functions are not first class values in PHP, they cannot be passed by their name literal (which is what you're asking for). Even anonymous functions or functions created via create_function are passed by an object or string reference.
You can pass a name of a function as string, the name of an object method as (object, string) array or an anonymous function as object. None of these pass pointers or references, they just pass on the name of the function. All of these methods are known as the callback pseudo-type: http://php.net/callback
function func1(){
echo 'echo1 ';
return 'return1';
}
function func2($func){
echo 'echo2 ' . $func();
}
func2('func1');
Result:
echo1 echo2 return1
In PHP 5.4.4 (haven't tested lower or other versions), you can do exactly as you suggested.
Take this as an example:
function test ($func) {
$func('moo');
}
function aFunctionToPass ($str) {
echo $str;
}
test('aFunctionToPass');
The script will echo "moo" as if you called "aFunctionToPass" directly.
A similar pattern of this Javascript first class function:
function add(first, second, callback){
console.log(first+second);
if (callback) callback();
}
function logDone(){
console.log('done');
}
function logDoneAgain(){
console.log('done Again');
}
add(2,3, logDone);
add(3,5, logDoneAgain);
Can be done in PHP (Tested with 5.5.9-1ubuntu on C9 IDE) in the following way:
// first class function
$add = function($first, $second, $callback) {
echo "\n\n". $first+$second . "\n\n";
if ($callback) $callback();
};
function logDone(){
echo "\n\n done \n\n";
}
call_user_func_array($add, array(2, 3, logDone));
call_user_func_array($add, array(3, 6, function(){
echo "\n\n done executing an anonymous function!";
}));
Result: 5 done 9 done executing an anonymous function!
Reference: https://github.com/zenithtekla/unitycloud/commit/873659c46c10c1fe5312f5cde55490490191e168
You can create a reference by assigning the function to a local variable when you declare it:
$test = function() {
echo "hello world!";
};
function call($func){
$func();
}
call($test);
You can say
$fun = 'test';
call($fun);
Instead of call(test);, use call_user_func('test');.
As of PHP 8.1, you can use First-class callables:
call(test(...));
You can even use methods:
call($obj->test(...));
As simple as it is.
It appears a bit unclear why do you want to pass functions by reference? Usually things are passed by reference only when the referenced data needs to be (potentially) modified by the function.
As PHP uses arrays or strings to refer functions, you could just pass an array or a string by reference and that would allow the function reference to be modified.
For example, you could do something like
<?php
$mysort = function($a, b) { return ($a < $b) ? 1 : -1; };
adjust_sort_from_config($mysort); // modifies $mysort
do_something_with_data($mysort);
where
<?php
function load_my_configuration(&$fun)
{
$sort_memory = new ...;
...
$fun = [$sort_memory, "customSort"];
// or simply
$fun = function($a, b) { return (rand(1,10) < 4 ? 1 : -1; };
}
This works because there are three ways to refer to function in PHP via a variable:
$name – the string $name contains the name of the function in global namespace that should be called
array($object, $name) – refers to method called string $name of object $object.
array($class, $name) – refers to static function string $name of class $class.
If I remember correctly, the methods and static functions pointed by these constructs must be public. The "First-class callable syntax" should improve this restriction given recent enough PHP version but it seems to be just some syntactic sugar around Closure::fromCallable().
Anonymous functions work the same behind the scenes. You just don't see the literal random names of those functions anywhere but the reference to an anonymous function is just a value of a variable, too.

Categories