Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP Generators

PHP Generators

Introdução ao mundo dos generators.

Avatar for Thiago Soares

Thiago Soares

November 30, 2013

Other Decks in Technology

Transcript

  1. ITERADORES • Na programação de computadores, um iterador (em inglês,

    iterator) é um objeto que permite que um programador examine um container. - Wikipedia
  2. ITERADORES • Interface para iteradores externos ou objetos que podem

    ser iterados. • O PHP oferece uma série de iteradores para muitos problemas do dia a dia.
  3. PHP Iterator Interface <?php interface Iterator extends Traversable { public

    function current(); public function next(); public function key(); public function valid(); public function rewind(); }
  4. Implementando o Iterator class MyIterator implements Iterator { } •

    PHP Fatal error: Class MyIterator contains 5 abstract methods and must therefore be declared abstract or implement the remaining methods (Iterator::current, Iterator::next, Iterator::key, ...)
  5. Implementando o Iterator <?php class MyIterator implements Iterator { public

    function current() {} public function next() {} public function key() {} public function valid() {} public function rewind() {} }
  6. Sequência de Fibonacci: <?php class Fibonacci implements Iterator { private

    $previous = 0; private $current = 1; private $key = 0; public function __construct() { $this->rewind(); }
  7. Sequência de Fibonacci: // Retorna a chave do elemento atual:

    public function key() { return($this->key); } • abstract public scalar Iterator::key ( void )
  8. Sequência de Fibonacci: // Retorna o elemento atual: public function

    current() { return($this->current); } • abstract public mixed Iterator::current ( void )
  9. Sequência de Fibonacci: // Move o próximo elemento para a

    posição atual: public function next() { $number = $this->current; $this->current += $this->previous; $this->previous = $number; $this->key++; } • abstract public void Iterator::next ( void )
  10. Sequência de Fibonacci: // Verifica se a posição atual é

    valida: public function valid() { return(true); } • abstract public boolean Iterator::valid ( void )
  11. Sequência de Fibonacci: // Retorna ao primeiro elemento do Iterator:

    public function rewind() { $this->previous = 0; $this->current = 1; $this->key = 0; } • abstract public void Iterator::rewind ( void )
  12. Sequência de Fibonacci: <?php $fibonacci = new Fibonacci(); $i =

    0; foreach ($fibonacci as $number) { echo $number, PHP_EOL; if (10 === $i++) { break; } } • SAÍDA: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89.
  13. GERADORES • Na ciência da computação, um gerador (em inglês,

    generator) é um procedimento especial que pode ser usado para controlar iteradores de loops. - Wikipedia
  14. GERADORES • 1975: CLU • 1977: Icon • 1983: C++

    • 1987: Perl • 1988: Tcl • 1990: Haskell • 1994: Racket • 1995: Ruby • 1997: Java • 2000: C# • 2001: Python
  15. GERADORES • É uma função interruptível que retorna uma sequência

    de valores; • Qualquer função que chame um yield é automaticamente uma função geradora;
  16. GERADORES • Na primeira vez que o gerador é chamado

    dentro de um loop um objeto é criado; • Na próxima vez o mesmo gerador é chamado em uma iteração na sequência;
  17. GERADORES • Geradores fornecem uma maneira fácil de implementar iteradores

    sem complexidade de uma interface iterator; • Um gerador permite você iterar sobre um conjunto de dados sem construir um array em memória.
  18. Sequência de Fibonacci: <?php function fibonacci() { $previous = 0;

    $current = 1; yield 1; while(true) { $current = $previous + $current; $previous = $current - $previous; yield $current; } }
  19. Sequência de Fibonacci: $i = 0; foreach (fibonacci() as $number)

    { echo $number, PHP_EOL; if (10 === $i++) { break; } } • SAÍDA: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89.
  20. Class Generator <?php final class Generator implements Iterator { public

    function current() {} public function key() {} public function next() {} public function rewind() {} public function send($value) {} public function throw(Exception $exception) {} public function valid() {} }
  21. GERADORES • CURRENT: // Recebe o valor gerado; public mixed

    Generator::current ( void ) • $gen->current()
  22. GERADORES • KEY: // Recebe o valor da chave do

    valor gerado; public mixed Generator::key ( void ) • $gen->key();
  23. GERADORES • NEXT: // Finaliza o valor atual; public void

    Generator::next ( void ) • $gen->next();
  24. GERADORES • REWIND: // Retorna ao valor anterior. public void

    Generator::rewind ( void ) • $gen->rewind(); • Se a iteração tiver iniciado dispara uma exceção;
  25. GERADORES • SEND: // Envia um valor ao gerador. public

    mixed Generator::send ( mixed $value ) • $gen->send($value);
  26. Enviando valor ao yield. <?php function printer() { while (true)

    { $string = yield; echo $string; } } $printer = printer(); $printer->send('Hello world!'); • SAÍDA: Hello world!
  27. GERADORES • THROW: // Dispara uma exceção. public void Generator::throw

    ( Exception $exception ) • PHP Fatal error: Uncaught exception 'Exception' with message 'Cannot rewind a generator that was already run';
  28. GERADORES • VALID: // Verifica se a iteração foi realizada.

    public bool Generator::valid ( void ) • $gen->valid();
  29. Chamando métodos manualmente $gen = generateOneToTen(); echo 'K: ',$gen->key(), '

    V: ', $gen->current(); $gen->next(); echo 'K: ',$gen->key(), ' V: ', $gen->current(); $gen->next(); echo 'K: ',$gen->key(), ' V: ', $gen->current(); $gen->next(); $gen->rewind(); • SAÍDA: K: 0 V: 0K: 1 V: 1K: 2 V: 2
  30. GERADORES • Sintaxe yield // valor yield por referência: <?php

    function &gen_reference() { $value = 3; while ($value > 0) { yield $value; } }
  31. TESTES • O Nikita Popov disponibilizou um microbenchmark para testar

    a performance dos geradores. • https://gist.github.com/nikic/2975796