In the **php5.5.0** version, a new generator * (generators) * feature was added to simplify the complexity of implementing an Iterator interface * (Iterator) * To create a simple iterator.
With the generator, we can easily use foreach to iterate over a series of data without having to pre-build the objects in memory to be iterated, greatly reducing memory overhead.
When the generator function is called, it returns an iterative object, and when the object is iterated, PHP will call the generator function when needed, and save the state inside the iterator when the generator uses the New keyword yield to generate a value for the user. When the iterator does not have a new value to generate, the generator function can exit directly and the external function continues execution.
Note that in a generator function, you cannot return a value using the return statement, and return a value using return produces a compiler error. However, it is possible to use an empty return, which causes the iterator to terminate.
The generator function is the same as the normal function, and the yield keyword is used within the unique difference function. The yield statement can be said to be the core of the generator function, in a nutshell, yield is like a return statement, the difference is that the return statement returns after the function is finished, and after using yield return, just pause the function execution, go to the external function to continue execution, the next time the generator function is called , continue executing the code inside the generator function.
A simple example-the range function of the generator version
A simple example is using the return value of the foreach Iteration function range, which consumes more than 100M of memory if the range (0, 1000000) is called. Using the generator, you may only need to consume 1KB of memory.
$end) { throw new RuntimeException ("The starting value cannot be greater than the cutoff value"); } for ($i = $start; $i <= $end; $i + = 1) { //using the yield keyword, each time the function returns the value of $i, and control is given to the external function to continue the yield $i;} } foreach (Xrange (1, 9) as $number) { echo "$number";}
The above example output is as follows:
In the example above, we have created a function named Xrange that uses yield to produce the return value continuously, while calling Xrange (1, 9) will create a generator object. We can modify the foreach line to print out the Xrange object and see
... $xrange _res = xrange (1, 9); Var_dump ($xrange _res); foreach ($xrange _res as $number) {...
Output
As you can see, the execution of xrange (1, 9) did return a generator object.
Use the Send method of the Generator object
In the example above, we use the yield statement as a separate line of statements, that is, the yield statement produces the result to the outside, then there is no way in the iterative process from the outside of the generator function to get the value?
There is always a way, because the call to the generator function returns a generator object, so we can pass a value externally to the generator function by calling the Send method of the object, and after calling the Send method, yield receives the value sent by the Send function.
" . $ret); $ret = (yield ' yield2 '); Var_dump ("--". $ret);} $gen = Gen (), Var_dump ($gen->current ()), Var_dump ($gen->send (' Ret1 ')), Var_dump ($gen->send (' Ret2 '));
Output:
Here we first create a generator object called Gen, and then print the return value of the $gen->current () method, which is the current value produced by the first iteration of the iterator, and therefore outputs the yield1.
Next we call the $gen->send (' ret ') method, at which point the first yield statement in the generator returns the value passed by the method Ret1, so the value of $ret is Ret1.
Then, because the generator internally executes to the third statement $ret = (yield ' yield2 '), the external second var_dump outputs the yield2. The last Call to $gen->send (' Ret2 ') is similar to the first, but this time the generator has no yield after invoking yield, so it returns NULL.
Note that the $ret = (yield ' yield2 ') statement here uses parentheses to include the yield ' yield2 ' statement, which is required, and if yield is used in the context of an expression, yield must be placed in parentheses, otherwise an error will be made.
Returns an associative array
In the previous example, we used the yield keyword to return always a single value, in fact PHP also provides support for returning associative arrays, the basic syntax:
Yield key = Val
Use this syntax format to return the same results as the traversal management array when foreach is used.
' MYLXSW ', ' site ' = ' http://aicode.cc ' ]; foreach ($array as $key = + $val) { yield $key = = $val; }} foreach (Gen2 () as $key = = $val) { var_dump ($key. ' : '. $val);}
Output:
Using references
We can also have the generator return data as a reference, so that the values of the generator's internal data can be modified directly outside the generator.
0) { yield $value; }} foreach (Gen_reference () as & $number) { echo (--$number). ' ... ';}
In the above example, it is important to note that the generator functions are defined and traversed using the & $number.
Finally, the generator and the custom iterator object are not exactly the same, and once the generator starts iterating, it can no longer be rewind, and can only be iterated forward until the iteration is complete. If you want to iterate over a generator object multiple times, you can call the generator function multiple times to create a new generator object or use the Clone keyword.
Reference:
Cooperative multitasking using coroutines (in php!) Generators