language/generators.xml
08e58ace7e5b538c8ed75d784a54885d5f785d30
...
...
@@ -15,16 +15,17 @@
15
15
</para>
16
16

17
17
<para>
18
-
A generator allows you to write code that uses &foreach; to iterate over a
19
-
set of data without needing to build an array in memory, which may cause
20
-
you to exceed a memory limit, or require a considerable amount of
21
-
processing time to generate. Instead, you can write a generator function,
18
+
A generator offers a convenient way to provide data to &foreach; loops without
19
+
having to build an array in memory ahead of time, which may cause the program
20
+
to exceed a memory limit or require a considerable amount of
21
+
processing time to generate. Instead, a generator function can be used,
22
22
which is the same as a normal
23
23
<link linkend="functions.user-defined">function</link>, except that instead
24
24
of
25
25
<link linkend="functions.returning-values">return</link>ing once, a
26
26
generator can &yield; as many times as it needs to in order to provide the
27
27
values to be iterated over.
28
+
Like with iterators, random data access is not possible.
28
29
</para>
29
30

30
31
<para>
...
...
@@ -49,9 +50,9 @@
49
50
<![CDATA[
50
51
<?php
51
52
function xrange($start, $limit, $step = 1) {
52
-
if ($start < $limit) {
53
+
if ($start <= $limit) {
53
54
if ($step <= 0) {
54
-
throw new LogicException('Step must be +ve');
55
+
throw new LogicException('Step must be positive');
55
56
}
56
57

57
58
for ($i = $start; $i <= $limit; $i += $step) {
...
...
@@ -59,7 +60,7 @@ function xrange($start, $limit, $step = 1) {
59
60
}
60
61
} else {
61
62
if ($step >= 0) {
62
-
throw new LogicException('Step must be -ve');
63
+
throw new LogicException('Step must be negative');
63
64
}
64
65

65
66
for ($i = $start; $i >= $limit; $i += $step) {
...
...
@@ -98,7 +99,7 @@ Single digit odd numbers from xrange(): 1 3 5 7 9
98
99
<sect2 xml:id="language.generators.object">
99
100
<title><classname>Generator</classname> objects</title>
100
101
<para>
101
-
When a generator function is called for the first time, an object of the
102
+
When a generator function is called, a new object of the
102
103
internal <classname>Generator</classname> class is returned. This object
103
104
implements the <classname>Iterator</classname> interface in much the same
104
105
way as a forward-only iterator object would, and provides methods that can
...
...
@@ -114,27 +115,27 @@ Single digit odd numbers from xrange(): 1 3 5 7 9
114
115
<para>
115
116
A generator function looks just like a normal function, except that instead
116
117
of returning a value, a generator &yield;s as many values as it needs to.
118
+
Any function containing &yield; is a generator function.
117
119
</para>
118
120

119
121
<para>
120
122
When a generator function is called, it returns an object that can be
121
123
iterated over. When you iterate over that object (for instance, via a
122
-
&foreach; loop), PHP will call the generator function each time it needs a
124
+
&foreach; loop), PHP will call the object's iteration methods each time it needs a
123
125
value, then saves the state of the generator when the generator yields a
124
126
value so that it can be resumed when the next value is required.
125
127
</para>
126
128

127
129
<para>
128
-
Once there are no more values to be yielded, then the generator function
129
-
can simply exit, and the calling code continues just as if an array has run
130
+
Once there are no more values to be yielded, then the generator
131
+
can simply return, and the calling code continues just as if an array has run
130
132
out of values.
131
133
</para>
132
134

133
135
<note>
134
136
<para>
135
-
A generator cannot return a value: doing so will result in a compile
136
-
error. An empty <command>return</command> statement is valid syntax within
137
-
a generator and it will terminate the generator.
137
+
A generator can return values, which can be retrieved using
138
+
<methodname>Generator::getReturn</methodname>.
138
139
</para>
139
140
</note>
140
141

...
...
@@ -185,43 +186,6 @@ foreach ($generator as $value) {
185
186
</para>
186
187
</note>
187
188

188
-
<caution>
189
-
<para>
190
-
If you use yield in an expression context (for example, on the right hand
191
-
side of an assignment), you must surround the yield statement with
192
-
parentheses in PHP 5. For example, this is valid:
193
-
</para>
194
-

195
-
<informalexample>
196
-
<programlisting role="php">
197
-
<![CDATA[
198
-
$data = (yield $value);
199
-
]]>
200
-
</programlisting>
201
-
</informalexample>
202
-

203
-
<para>
204
-
But this is not, and will result in a parse error in PHP 5:
205
-
</para>
206
-

207
-
<informalexample>
208
-
<programlisting role="php">
209
-
<![CDATA[
210
-
$data = yield $value;
211
-
]]>
212
-
</programlisting>
213
-
</informalexample>
214
-

215
-
<para>
216
-
The parenthetical restrictions do not apply in PHP 7.
217
-
</para>
218
-

219
-
<para>
220
-
This syntax may be used in conjunction with the
221
-
<methodname>Generator::send</methodname> method.
222
-
</para>
223
-
</caution>
224
-

225
189
<sect3 xml:id="control-structures.yield.associative">
226
190
<title>Yielding values with keys</title>
227
191

...
...
@@ -284,22 +248,6 @@ foreach (input_parser($input) as $id => $fields) {
284
248
]]>
285
249
</screen>
286
250
</example>
287
-

288
-
<caution>
289
-
<para>
290
-
As with the simple value yields shown earlier, yielding a key/value pair
291
-
in an expression context requires the yield statement to be
292
-
parenthesised:
293
-
</para>
294
-

295
-
<informalexample>
296
-
<programlisting role="php">
297
-
<![CDATA[
298
-
$data = (yield $key => $value);
299
-
]]>
300
-
</programlisting>
301
-
</informalexample>
302
-
</caution>
303
251
</sect3>
304
252

305
253
<sect3 xml:id="control-structures.yield.null">
...
...
@@ -388,7 +336,7 @@ foreach (gen_reference() as &$number) {
388
336
<title>Generator delegation via <command>yield from</command></title>
389
337

390
338
<para>
391
-
In PHP 7, generator delegation allows you to yield values from another
339
+
Generator delegation allows you to yield values from another
392
340
generator, <classname>Traversable</classname> object, or
393
341
<type>array</type> by using the <command>yield from</command> keyword.
394
342
The outer generator will then yield all values from the inner generator,
...
...
@@ -417,7 +365,7 @@ foreach (gen_reference() as &$number) {
417
365
A common case where this matters is <function>iterator_to_array</function>
418
366
returning a keyed array by default, leading to possibly unexpected results.
419
367
<function>iterator_to_array</function> has a second parameter
420
-
<parameter>use_keys</parameter> which can be set to &false; to collect
368
+
<parameter>preserve_keys</parameter> which can be set to &false; to collect
421
369
all the values while ignoring the keys returned by the <classname>Generator</classname>.
422
370
</para>
423
371

...
...
@@ -426,14 +374,14 @@ foreach (gen_reference() as &$number) {
426
374
<programlisting role="php">
427
375
<![CDATA[
428
376
<?php
429
-
function from() {
377
+
function inner() {
430
378
yield 1; // key 0
431
379
yield 2; // key 1
432
380
yield 3; // key 2
433
381
}
434
382
function gen() {
435
383
yield 0; // key 0
436
-
yield from from(); // keys 0-2
384
+
yield from inner(); // keys 0-2
437
385
yield 4; // key 1
438
386
}
439
387
// pass false as second parameter to get an array [0, 1, 2, 3, 4]
...
...
@@ -622,6 +570,16 @@ class LineIterator implements Iterator {
622
570
means that the same generator can't be iterated over multiple times: the
623
571
generator will need to be rebuilt by calling the generator function again.
624
572
</para>
573
+

574
+
<simplesect role="seealso">
575
+
&reftitle.seealso;
576
+
<para>
577
+
<simplelist>
578
+
<member><link linkend="language.oop5.iterations">Object Iteration</link></member>
579
+
</simplelist>
580
+
</para>
581
+
</simplesect>
582
+

625
583
</sect1>
626
584
</chapter>
627
585

628
586