An introduction to
in PHP
							
							By @JeroenDeDauw
							
							
								www.EntropyWins.wtf
							
						
Use "page down" and "page up" to navigate
function doStuff(array $things) {
    foreach ($things as $thing) {
        /* ... */
    }
}
					
function doStuff(Iterator $things) {
    foreach ($things as $thing) {
        /* ... */
    }
}
					
function findFileWithNyanCat(string $path): ?string {
    foreach (glob($path . '*.txt') as $file) {
        $fileContent = file_get_contents($file);
        if (in_string('~=[,,_,,]:3', $fileContent)) {
            return $fileContent;
        }
    }
    return null;
}
					
function getContentsOfTextFiles($path): array {
    // glob and file_get_contents
}
function findTextWithNyanCat(array $texts): ?string {
    foreach ($texts as $text) {
        if (in_string('~=[,,_,,]:3', $text)) {
            return $text;
        }
    }
    return null;
}
findTextWithNyanCat(getContentsOfTextFiles($path));
					
class TextFileIterator implements Iterator {
    /* ... */
    public function current() {
        // return file_get_contents
    }
    /* ... */
}
					
function findTextWithNyanCat(Iterator $texts): ?string {
    foreach ($texts as $text) {
        if (in_string('~=[,,_,,]:3', $text)) { /*...*/ }
    }
    return null;
}
findTextWithNyanCat(new TextFileIterator($path));
					
findTextWithNyanCat(new DatabaseIterator(/*...*/));
findTextWithNyanCat(new ArrayIterator(['test text', '~=[,,_,,]:3']));
					
function newNyanGenerator(): Generator {
    yield '~=[,,_,,]:3';
    yield 'Nyan!';
}
$generator = newNyanGenerator();
foreach ($generator as $text) {
    echo $text . ' ';
}
// ~=[,,_,,]:3 Nyan!
					IteratorAggregate + Generator = <3
function newNyanGenerator(): Generator {
    yield '~=[,,_,,]:3';
    yield 'Nyan!';
}
$generator = newNyanGenerator();
foreach ($generator as $text) {
    echo $text;
}
foreach ($generator as $text) {
    echo $text; // BOOM!
}
					
interface IteratorAggregate extends Traversable {
    public function getIterator(): Traversable;
}
					
class NyanNyan implements IteratorAggregate {
    public function getIterator(): Traversable {
        yield '~=[,,_,,]:3';
        yield 'Nyan!';
    }
}
$traversable = new NyanNyan();
foreach ($traversable as $text) {
    echo $text;
}
foreach ($traversable as $text) {
    echo $text; // works fine
}
					
private function getMailTemplatesOnDisk(array $mailTemplatePaths): array {
    $mailTemplatesOnDisk = [];
    foreach ($mailTemplatePaths as $path) {
        $mailFilesInFolder = glob($path . '/Mail_*');
        array_walk($mailFilesInFolder, function(&$filename) {
            $filename = basename($filename);
        });
        $mailTemplatesOnDisk = array_merge($mailTemplatesOnDisk, $mailFilesInFolder);
    }
    return $mailTemplatesOnDisk;
}
					
class MailTemplateFilenameTraversable implements \IteratorAggregate {
    public function __construct(array $mailTemplatePaths) {
        $this->mailTemplatePaths = $mailTemplatePaths;
    }
    public function getIterator() {
        foreach ($this->mailTemplatePaths as $path) {
            foreach (glob( $path . '/Mail_*') as $fileName) {
                yield basename($fileName);
            }
        }
    }
}
					Generators also can...
yield "Iterators" => "are useful";
yield "Generators" => "are awesome";
// ["Iterators" => "are useful",
// "Generators" => "are awesome"]
						
yield from [1, 2, 3];
yield from new ArrayIterator([4, 5]);
// 1, 2, 3, 4, 5
						
// Flattens iterable[] into Generator
foreach ($collections as $collection) {
    yield from $collection;
}	
class SeriousBiznessTest extends PHPUnitSomething {
    public function testContainsNyan(string $text) {
        $this->assertContains('~=[,,_,,]:3', $text);
    }
    public function nyanTextProvider(): array {
         return [
             [ 'Foo ~=[,,_,,]:3' ],
             [ 'Bar ~=[,,_,,]:3' ],
             [ 'message' => 'Baz ~=[,,_,,]:3' ],
         ];
    }
}
						
public function nyanTextProvider(): iterable {
    yield [ 'Foo ~=[,,_,,]:3' ];
    yield [ 'Bar ~=[,,_,,]:3' ];
    yield [ 'message' => 'Baz ~=[,,_,,]:3' ];
}
						
function doStuff(iterable $things) {
    foreach ($things as $thing) {
        /* ... */
    }
}
					
function doStuff(iterable $things) {
    foreach (array_chunk($things, 2) as $twoThings) {
        /* ... */
    }
}
					
function iterable_to_array(iterable $iterable): array {
    if (is_array($iterable)) {
        return $iterable;
    }
    return iterator_to_array($iterable);
}
					iterable → Iterator
function iterable_to_iterator(iterable $iterable): Iterator {
    if ($iterable instanceof Iterator) {
        return $iterable;
    }
    if (is_array($iterable)) {
        return new ArrayIterator($iterable);
    }
    // TODO: IteratorAggregate case
}
					
    return new IteratorIterator($iterable);
					
interface IteratorAggregate extends Traversable {
    public function getIterator();
}
					
    return new \WMDE\TraversableIterator\TraversableIterator($iterable);
						github.com/wmde/iterable-functions
Questions?
www.EntropyWins.wtf
@JeroenDeDauw