What does yield mean in PHP?
I've recently stumbled over this code:
function xrange($min, $max)
{
for ($i = $min; $i <= $max; $i++) {
yield $i;
}
}
I've never seen this yield
keyword before. Trying to run the code I get
Parse error: syntax error, unexpected T_VARIABLE on line x
So what is this yield
keyword? Is it even valid PHP? And if it is, how do I use it?
What is yield
?
The yield
keyword returns data from a generator function:
The heart of a generator function is the yield keyword. In its simplest form, a yield statement looks much like a return statement, except that instead of stopping execution of the function and returning, yield instead provides a value to the code looping over the generator and pauses execution of the generator function.
What is a generator function?
A generator function is effectively a more compact and efficient way to write an Iterator. It allows you to define a function (your xrange
) that will calculate and return values while you are looping over it:
foreach (xrange(1, 10) as $key => $value) {
echo "$key => $value", PHP_EOL;
}
This would create the following output:
0 => 1
1 => 2
…
9 => 10
You can also control the $key
in the foreach
by using
yield $someKey => $someValue;
In the generator function, $someKey
is whatever you want appear for $key
and $someValue
being the value in $val
. In the question's example that's $i
.
What's the difference to normal functions?
Now you might wonder why we are not simply using PHP's native range
function to achieve that output. And right you are. The output would be the same. The difference is how we got there.
When we use range
PHP, will execute it, create the entire array of numbers in memory and return
that entire array to the foreach
loop which will then go over it and output the values. In other words, the foreach
will operate on the array itself. The range
function and the foreach
only "talk" once. Think of it like getting a package in the mail. The delivery guy will hand you the package and leave. And then you unwrap the entire package, taking out whatever is in there.
When we use the generator function, PHP will step into the function and execute it until it either meets the end or a yield
keyword. When it meets a yield
, it will then return whatever is the value at that time to the outer loop. Then it goes back into the generator function and continues from where it yielded. Since your xrange
holds a for
loop, it will execute and yield until $max
was reached. Think of it like the foreach
and the generator playing ping pong.
Why do I need that?
Obviously, generators can be used to work around memory limits. Depending on your environment, doing a range(1, 1000000)
will fatal your script whereas the same with a generator will just work fine. Or as Wikipedia puts it:
Because generators compute their yielded values only on demand, they are useful for representing sequences that would be expensive or impossible to compute at once. These include eg infinite sequences and live data streams.
Generators are also supposed to be pretty fast. But keep in mind that when we are talking about fast, we are usually talking in very small numbers. So before you now run off and change all your code to use generators, do a benchmark to see where it makes sense.
Another Use Case for Generators is asynchronous coroutines. The yield
keyword does not only return values but it also accepts them. For details on this, see the two excellent blog posts linked below.
Since when can I use yield
?
Generators have been introduced in PHP 5.5 . Trying to use yield
before that version will result in various parse errors, depending on the code that follows the keyword. So if you get a parse error from that code, update your PHP.
Sources and further reading:
yield
keyword serves for definition of "generators" in PHP 5.5. Ok, then what is a generator?
From php.net:
Generators provide an easy way to implement simple iterators without the overhead or complexity of implementing a class that implements the Iterator interface.
A generator allows you to write code that uses foreach to iterate over a set of data without needing to build an array in memory, which may cause you to exceed a memory limit, or require a considerable amount of processing time to generate. Instead, you can write a generator function, which is the same as a normal function, except that instead of returning once, a generator can yield as many times as it needs to in order to provide the values to be iterated over.
From this place: generators = generators, other functions (just a simple functions) = functions.
So, they are useful when:
you need to do things simple (or simple things);
generator is really much simplier then implementing the Iterator interface. other hand is, ofcource, that generators are less functional. compare them.
you need to generate BIG amounts of data - saving memory;
actually to save memory we can just generate needed data via functions for every loop iteration, and after iteration utilize garbage. so here main points is - clear code and probably performance. see what is better for your needs.
you need to generate sequence, which depends on intermediate values;
this is extending of the previous thought. generators can make things easier in comparison with functions. check Fibonacci example, and try to make sequence without generator. Also generators can work faster is this case, at least because of storing intermediate values in local variables;
you need to improve performance.
they can work faster then functions in some cases (see previous benefit);
simple example
<?php
echo '#start main# ';
function a(){
echo '{start[';
for($i=1; $i<=9; $i++)
yield $i;
echo ']end} ';
}
foreach(a() as $v)
echo $v.',';
echo '#end main#';
?>
output
#start main# {start[1,2,3,4,5,6,7,8,9,]end} #end main#
链接地址: http://www.djcxy.com/p/58066.html
上一篇: STRING,期待T
下一篇: PHP中的收益率意味着什么?