X
X

Generators Yielding DataTypes

Now lets review what datatypes can be yielded back. Just before we do, lets review how we can invoke the generator function. Lets say I want a self driving car that’ll continue at each stop sign until it reaches the final destination or the end of the execution context.

Take for example the following code that executes the generator context…

function satNav( ){
	yield 'string';
	yield 100;
	yield 100.11;
	yield true;
}

… Here we have four stop or yield sign’s before our generator’s execution context is finished. So now we could invoke the function creating the control object…

$control = satNav( );

… Now we can start to invoke the generator function and then continue at each stop sign with the next method like so …

echo $control->current();
$control->next();
$control->next();
$control->next();

… Not forgetting that the next method doesn’t return the yielded value. So we’d need to use the current method to retrieve each value…

echo $control->current();
$control->next();
echo $control->current();
$control->next();
echo $control->current();
$control->next();
echo $control->current();

But is there a better way than this? The simple answer is yes, if we had even 20 stop signs in a generator function this would be impractical. So instead we can use a foreach loop in PHP to iterate over all the yield statement’s within our function. We can think of this as a self driving car that continually presses the accelerator pedal for you and retrieves the value automating the next and current methods.

This foreach loop needs the control object to automatically push the accelerator pedal, AKA giving the foreach loop the ability to control the generators execution context. So we pass in the control object and then each yielded value will be assigned to the $value variable in our case.

foreach( $control as $value ){
	echo '<br>' . $value;
}

…. When executed we have a self driving car that’ll produce the following output…

String
100
100.11
1

Now lets analyse the datatypes we’ve just yielded. Here are all the basic primitive datatypes you can yield back such as a string, integer, floating point number and a boolean. Note that the boolean true value is polymorphed into the integer one.

So those where the primitive datatypes. But what about the other datatypes you could yield? So for example an array, associative array or a standard object. This is possible take a look at the following example…

class MyObj {  }

function satNav(  ){
	yield [ 100, 200, 300 ];
	yield array( "assoc" => "array", "key" => "value" );
	yield new MyObj;
}

… Here we have an array [ 100, 200, 300 ] then an associative array array( “assoc” => “array”, “key” => “value” ) and finally an object new MyObj that’s created from the class MyObj. All of these object types can be yielded just the same as if you where to use these objects in a return statement.

Note we’re not echoing out whole objects so we need to convert them into a visual string otherwise we’ll get an error…

foreach( $control as $value ){
	echo '<br>' . json_encode( $value, JSON_PRETTY_PRINT );
}

… Which’ll produce …

[ 100, 200, 300 ]
{ "assoc": "array", "key": "value" }
{ }

But we have traversable objects. Traversable just means we can travel across or through something in any direction. For example a building is traversable vertically by an elevator or stairwell and on each floor we can travel across. Likewise we have traversable objects such as arrays and associative arrays which can be travelled through or across.

Not all objects however are traversable for example objects that come from classes are not. Classes can create objects that have private or protected members AKA properties or method’s. This means some rooms or floors of this type of building are completely locked off to anything outside of the object; AKA not traversable. Traversable objects can ONLY be arrays or associative arrays. All of their members are public and cannot be hidden; unlike objects that come from classes.

We can perform special actions on traversable objects within a generator function. By using the yield from statement we can now create a stop sign for each value within the array or associative array…

function satNav(  ){
	yield from [ 100, 200, 300 ];
}

… This will produce the output…

100
200
300

… You can see instead of printing out the array as a string it yielded each value within the array. So we don’t get…

[ 100, 200, 300 ]

… Instead we got …

100
200
300

… Likewise with associative arrays we could use yield from

function satNav(  ){
	yield from array( "assoc" => "array", "key" => "value" );
}

… This will produce the output…

array
value

… Note that only the values got printed out of the associative array and not the key names.

That’s it, you know that you can yield any datatype from primitive to all types of objects that PHP has to offer. Traversable objects are arrays and associative arrays and can have each value yielded by using the yield from statement. However all of this was available in PHP5.5 and in the next lecture we’ll look at what’s new with generators in PHP7.

Latest Posts