What is the use for the argument block in anonymous functions - php

In this example:
$foo = function () use (){
// ^---------^ what is the use?
}
Aside this from being a function that we can use the use () part to import a data into the function, just like a regular function as in:
function bar ($foo){
}
but I don't understand what the function () part can be used for?

e.g:
$a = 1;
$foo = function ($b, $c) use ($a)
{
echo $a . PHP_EOL;
echo $b . PHP_EOL;
echo $c . PHP_EOL;
};
$foo(2, 3);
$a = 5;
$foo(7, 8);
Would output:
1
2
3
1
7
8
$b, $c - would be parameters you pass on execution.
$a is bound/imported on creation. So if you change it after $foo definition it would not change.

The parameter block is for inputting parameters. So if I define
$foo = function($bar) use ($baz) {
return $bar + $baz;
}
and then I, say, pass $foo to another function or bind it to another class, I can do like
function bonk($bar, $foo) {
$baz = 4;
return $foo($bar);
}
and somewhere else call
// Returns 7
bonk(3, $foo);
One allows you to get the variable from context while the other must be passed in. For example, I have $baz available to me in the class that defines $bonk so I pass it in, but I don't yet know what $bar is going to be until it bonk gets called somewhere else with $bar passed in.
So ok let's say I'm a class called Cats and I have an object SiameseCat available to me. I have a method called doTheThing that takes a function and a parameter. It tells the cat what to do and optionally what to do it to. So it always has the same cat but depending on where I call it from, I can have the siamese cat do different verbs to different nouns, but I know it's my cat doing it because that's where I defined the cat.

Related

Why is the use language construct in php unable to see changes in the value of a variable?

I have got to the chapter of anonymous functions in php manuel. In the earlier chapter two methods of passing variables to a function are explained, namely, pass by value and pass by reference. Being a javascript developer, it was very unconfortable to see that functions do not have the access to the variables defined in the parent scope. Anyways, now they have come up with a third method to pass variables to a function -- by the use language construct. Please consider the following example:
$message = "hello";
$example = function () use ($message) {
var_dump($message);
};
$example(); //prints hello, as expected.
$message = 'world';
$example(); //prints hello -- not world.
The last call to $example should print "world", but it prints the older value of $message. Why is that? Instead if we had used either pass-by-value or pass-by-reference, the last function call would have printed world.
The use language construct captures/copies the passed variable at the time the anonymous function is defined. If you change that variable after the function definition, the function will not notice it:
$foo = 'baz';
$f1 = function() use ($foo) {
echo $foo;
};
$foo = 'boo';
$f1(); // baz
However, if the variable is an object, this rule doesn't apply, as PHP passes objects by reference*, always (* read Jeto's comment below for a more accurate description):
$foo = new StdClass();
$foo->bar = 'baz';
$f2 = function() use ($foo) {
echo $foo->bar;
};
$foo->bar = 'boo';
$f2(); // boo
I think the reason PHP has use is for partial function application:
function get_multiplier($factor) {
return function($num) use ($factor) {
return $num * $factor;
};
}
$multiply_by_4 = get_multiplier(4);
echo $multiply_by_4(5); // 20

use() statement on anonymous functions

Is it a bad practice to use it?
Because people say that global variables are bad practice and the use thing brings variables from outside into the functions, so it's like global
This is how it looks
$a = 1;
$func = function() use($a){
print $a;
};
Any arguments defined in the "use" arguments for an anonymous function use the value at the time when the anonymous function is defined; so they must exist at that point; but they don't need to be passed (or even exist in the caller scope) when the function is called.
function myFunctionCreator() {
$a = 1; // Must exist for the `use` clause
$func = function() use($a){
echo $a, PHP_EOL;
};
return $func;
}
$myFunc = myFunctionCreator();
$a = 2;
$myFunc(); // echoes 1 (value of $a at the point where the function was created)
As you can see from the above example, $a has a value of 1 at the point where the function is defined, and even though a variable with the same name exists at the point when the function called, it is the original $a (with the value 1) that is used in the function call.
Arguments defined in the main argument definition need not exist when the function is defined, but the values must be passed as arguments to the function at the point when it is called.
function myFunctionCreator() {
$a = 1; // Need not exist, and will be ignored
$func = function($a) {
echo $a, PHP_EOL;
};
return $func;
}
$myFunc = myFunctionCreator();
$value = 2;
$myFunc($value); // echoes 2 (value of $a explicitly passed to the function call
// at the time it is executed)
So the behaviour of the two types is quite different, and their purpose when combined provides a degree of flexibility that is quite different
As Rizier123 has mentioned in his comment, arguments passed to an anonymous function as "standard" can have defaults, typehints, etc, whereas "use" arguments cannot.
function myFunctionCreator() {
$func = function(array $dataset = [1,2,3]) {
foreach($dataset as $value) {
echo $value, PHP_EOL;
}
};
return $func;
}
$myFunc = myFunctionCreator();
$value = ['a','b','c'];
$myFunc($value);
$myFunc();
$myFunc(['x','y','z']);
Or (as the third call shows, arguments can be passed directly.
Andy of these applied to a "use" argument will result in a parse error

Why must I pass as reference the anonymous function in recursive anonymous functions in PHP?

Works:
$t = function($x,$y) use (&$t){
...
}
Does not work:
$t = function($x,$y) use ($t){
...
}
Why must I pass the function itself as reference?
Maybe this will help:
$f = 42;
$f = function() use ($f)
{
var_dump($f);
};
$f();
That outputs 42.
The use() is hit before the function is defined and assigned to $f. So if you don't pass by reference, you are accessing the variable as it was before the function was created. In this case, 42. In your case, NULL.
By passing a reference, you'll get $f's value at the time the function is called, which will be the anonymous function as you are expecting (assuming you haven't reassigned $f).
Passing Reference variable means you are accessing same variable within that scope.
Reference variable points to the same variable that were previously created.
Example
<?php
$a = 10;
$b = &$a;
function change_b($pass)
{
$b = $pass++;
}
echo $b."<br />";
change_b(&$a);
echo $b;
?>
above code will output 10 and then 11.
Recursive function has to access the same resource over and over again and that is much more efficient than copying values.

`static` keyword inside function?

I was looking at the source for Drupal 7, and I found some things I hadn't seen before. I did some initial looking in the php manual, but it didn't explain these examples.
What does the keyword static do to a variable inside a function?
function module_load_all($bootstrap = FALSE) {
static $has_run = FALSE
It makes the function remember the value of the given variable ($has_run in your example) between multiple calls.
You could use this for different purposes, for example:
function doStuff() {
static $cache = null;
if ($cache === null) {
$cache = '%heavy database stuff or something%';
}
// code using $cache
}
In this example, the if would only be executed once. Even if multiple calls to doStuff would occur.
Seems like nobody mentioned so far, that static variables inside different instances of the same class remain their state. So be careful when writing OOP code.
Consider this:
class Foo
{
public function call()
{
static $test = 0;
$test++;
echo $test . PHP_EOL;
}
}
$a = new Foo();
$a->call(); // 1
$a->call(); // 2
$a->call(); // 3
$b = new Foo();
$b->call(); // 4
$b->call(); // 5
If you want a static variable to remember its state only for current class instance, you'd better stick to a class property, like this:
class Bar
{
private $test = 0;
public function call()
{
$this->test++;
echo $this->test . PHP_EOL;
}
}
$a = new Bar();
$a->call(); // 1
$a->call(); // 2
$a->call(); // 3
$b = new Bar();
$b->call(); // 1
$b->call(); // 2
Given the following example:
function a($s){
static $v = 10;
echo $v;
$v = $s;
}
First call of
a(20);
will output 10, then $v to be 20. The variable $v is not garbage collected after the function ends, as it is a static (non-dynamic) variable. The variable will stay within its scope until the script totally ends.
Therefore, the following call of
a(15);
will then output 20, and then set $v to be 15.
Static works the same way as it does in a class. The variable is shared across all instances of a function. In your particular example, once the function is run, $has_run is set to TRUE. All future runs of the function will have $has_run = TRUE. This is particularly useful in recursive functions (as an alternative to passing the count).
A static variable exists only in a
local function scope, but it does not
lose its value when program execution
leaves this scope.
See http://php.net/manual/en/language.variables.scope.php
To expand on the answer of Yang
If you extend a class with static variables, the individual extended classes will hold their "own" referenced static that's shared between instances.
<?php
class base {
function calc() {
static $foo = 0;
$foo++;
return $foo;
}
}
class one extends base {
function e() {
echo "one:".$this->calc().PHP_EOL;
}
}
class two extends base {
function p() {
echo "two:".$this->calc().PHP_EOL;
}
}
$x = new one();
$y = new two();
$x_repeat = new one();
$x->e();
$y->p();
$x->e();
$x_repeat->e();
$x->e();
$x_repeat->e();
$y->p();
outputs:
one:1
two:1
one:2
one:3 <-- x_repeat
one:4
one:5 <-- x_repeat
two:2
http://ideone.com/W4W5Qv
static variable in a function means that no matter how many times you call the function, there's only 1 variable.
<?php
class Foo{
protected static $test = 'Foo';
function yourstatic(){
static $test = 0;
$test++;
echo $test . "\n";
}
function bar(){
$test = 0;
$test++;
echo $test . "\n";
}
}
$f = new Foo();
$f->yourstatic(); // 1
$f->yourstatic(); // 2
$f->yourstatic(); // 3
$f->bar(); // 1
$f->bar(); // 1
$f->bar(); // 1
?>
Inside a function, static means that the variable will retain its value each time the function is called during the life of the page load.
Therefore in the example you've given, if you call a function twice, if it set $has_run to true, then the function would be able to know that it had previously been called because $has_run would still be equal to true when the function starts the second time.
The usage of the static keyword in this context is explained in the PHP manual here: http://php.net/manual/en/language.variables.scope.php

Is it possible to access outer local variable in PHP?

Is it possible to access outer local varialbe in a PHP sub-function?
In below code, I want to access variable $l in inner function bar. Declaring $l as global $l in bar doesn't work.
function foo()
{
$l = "xyz";
function bar()
{
echo $l;
}
bar();
}
foo();
You could probably use a Closure, to do just that...
Edit : took some time to remember the syntax, but here's what it would look like :
function foo()
{
$l = "xyz";
$bar = function () use ($l)
{
var_dump($l);
};
$bar();
}
foo();
And, running the script, you'd get :
$ php temp.php
string(3) "xyz"
A couple of note :
You must put a ; after the function's declaration !
You could use the variable by reference, with a & before it's name : use (& $l)
For more informations, as a reference, you can take a look at this page in the manual : Anonymous functions
You must use the use keyword.
$bar = function() use(&$l) {
};
$bar();
In the very very old PHP 5.2 and earlier this didn't work. The syntax you've got isn't a closure, but a definition of a global function.
function foo() { function bar() { } }
works the same as:
function foo() { include "file_with_function_bar.php"; }
If you execute function foo twice, PHP will complain that you've tried to re-define a (global) function bar.
You can read default value by:
function(){
return preg_match(
"yourVar = \d+"
, str_file_get_contents(functionFile)
, arrayToPutFieldsValue
);
}
If You would use two functons in the same time - it's like someone's using a spoon and You want to take a food from that spoon - You'll waste a food or some of You will starv.
Anyway - You would have to set a pointer somehow in a hard way.
It's impossible to get any field from other function or class without calling it to life.
Functions/methods are instance-like - they need to be called.
Share the common fields by accessing a global fields with synchronized functions.
function a()
{
function val1($arg=null)
{
static $a;
if ($arg !== null) $a = $arg;
else return $a;
}
function b()
{
val1('1234');
echo val1() . '<br>'; // shows: 1234
val1('my custom data');
echo val1() . '<br>'; // shows: my custom data
}
b();
}
a();
Used val1('my custom data') to set my value
Used val1() to get my value

Categories