在 php 中有生成器这个东西。 官方的描述是
1 2
| 生成器提供了一种更容易的方法来实现简单的对象迭代,相比较定义类实现 Iterator 接口的方式,性能开销和复杂性大大降低。 生成器允许你在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间。相反,你可以写一个生成器函数,就像一个普通的自定义函数一样, 和普通函数只返回一次不同的是, 生成器可以根据需要 yield 多次,以便生成需要迭代的值。
|
以及官方提供的改造range的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <?php function xrange($start, $limit, $step = 1) { if ($start <= $limit) { if ($step <= 0) { throw new LogicException('Step must be positive'); }
for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } else { if ($step >= 0) { throw new LogicException('Step must be negative'); }
for ($i = $start; $i >= $limit; $i += $step) { yield $i; } } }
echo 'Single digit odd numbers from range(): '; foreach (range(1, 9, 2) as $number) { echo "$number "; } echo "\n";
echo 'Single digit odd numbers from xrange(): '; foreach (xrange(1, 9, 2) as $number) { echo "$number "; }
|
在我第一次看到的时候并没有思考为什么叫生成器这个东西。所以在一段时间内产生了迷惑。其实用官方编写的函数样本赋值给变量var_dump
出来的结果会是一个对象,而其生成器的名字是因为其可以通过foreach
在循环的每次成产出结果。所以可以看以下代码,来感受以下yield
解决了什么问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <?php function xrange($start, $limit, $step = 1) { if ($start <= $limit) { if ($step <= 0) { throw new LogicException('Step must be positive'); }
for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } else { if ($step >= 0) { throw new LogicException('Step must be negative'); }
for ($i = $start; $i >= $limit; $i += $step) { yield $i; } } }
$xarr = xrange(0,9,1);
foreach($xarr as $v){ echo $v; }
for($i = 0 ;$i<10;$i++){ echo $i; }
$arr = range(0,9,1); foreach($arr as $v){ echo $v; }
|
以及更好看的文件读取编码方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function readTxt() { $handle = fopen("./test.txt", 'rb');
while (feof($handle)===false) { yield fgets($handle); }
fclose($handle); }
foreach (readTxt() as $key => $value) { echo $value.'<br />'; }
|
所以在某种程度,我更倾向于,这是一个特殊写法的语法糖。可以在某些方式上以优雅的形式去实现代码。