Skip to content

Instantly share code, notes, and snippets.

@royopa
Last active August 29, 2015 14:26
Show Gist options
  • Save royopa/5f0935e800b228610052 to your computer and use it in GitHub Desktop.
Save royopa/5f0935e800b228610052 to your computer and use it in GitHub Desktop.
New translation language/generators.xml - Rodrigo Prado de Jesus <[email protected]>
Index: language/generators.xml
===================================================================
--- language/generators.xml (revision 0)
+++ language/generators.xml (working copy)
@@ -0,0 +1,488 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- EN-Revision: 330587 Maintainer: royopa Status: ready --><!-- CREDITS: royopa -->
+<chapter xml:id="language.generators" xmlns="http://docbook.org/ns/docbook">
+ <title>Generators</title>
+
+ <sect1 xml:id="language.generators.overview">
+ <title>Generators - Visão Geral</title>
+ <?phpdoc print-version-for="generators"?>
+
+ <para>
+ Os generators fornecem uma maneira fácil de implementar simples
+ <link linkend="language.oop5.iterations">iterators</link> sem a
+ sobrecarga ou complexidade de criar uma classe que implemente
+ a interface <classname>Iterator</classname>.
+ </para>
+
+ <para>
+ Um generator permite que você escreva código que use &foreach; para iterar
+ em um conjunto de dados sem precisar construir um array em memória, o que
+ pode fazer com que o limite de memória seja ultrapassado ou exigir uma
+ quantidade considerável de tempo de processamento para a geração. Em vez
+ disso, você pode escrever uma função generator, que é o mesmo que uma
+ <link linkend="functions.user-defined">função</link> normal, exceto que
+ ao invés do <link linkend="functions.returning-values">retorno</link> ocorrer
+ única vez, um generator pode entregar o resultado quantas vezes forem
+ necessárias para permitir que os valores sejam iterados.
+ </para>
+
+ <para>
+ Um exemplo simples para isso é reimplementar a função
+ <function>range</function>. A função <function>range</function> padrão
+ tem que gerar um array com cada valor dentro dele e retorná-lo, o que pode
+ resultar em grandes arrays: por exemplo, chamando
+ <command>range(0, 1000000)</command> irá resultar numa utilização de memória
+ de mais de 100 MB.
+ </para>
+
+ <para>
+ Como alternativa, nós podemos implementar um generator
+ <literal>xrange()</literal>, que só precisará de memória suficiente para
+ criar um objeto <classname>Iterator</classname> e acompanhar o estado atual
+ do generator internamente, que utiliza menos de 1 kilobyte de memória.
+ </para>
+
+ <example>
+ <title>Implementando <function>range</function> como um generator</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function xrange($start, $limit, $step = 1) {
+ if ($start < $limit) {
+ if ($step <= 0) {
+ throw new LogicException('Step must be +ve');
+ }
+
+ for ($i = $start; $i <= $limit; $i += $step) {
+ yield $i;
+ }
+ } else {
+ if ($step >= 0) {
+ throw new LogicException('Step must be -ve');
+ }
+
+ for ($i = $start; $i >= $limit; $i += $step) {
+ yield $i;
+ }
+ }
+}
+
+/*
+ * Note that both range() and xrange() result in the same
+ * output below.
+ */
+
+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 ";
+}
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+Single digit odd numbers from range(): 1 3 5 7 9
+Single digit odd numbers from xrange(): 1 3 5 7 9
+]]>
+ </screen>
+ </example>
+ </sect1>
+
+ <sect1 xml:id="language.generators.syntax">
+ <title>Sintaxe do Generator</title>
+
+ <para>
+ Uma função generator se parece com uma função normal, exceto que ao invés
+ de retornar um valor, um generator pode entregar o resultado quantas vezes
+ forem necessárias.
+ </para>
+
+ <para>
+ Quando uma função generator é chamada, ela retorna um objeto que pode ser
+ iterado. Quando você itera através desse objeto (por exemplo, por um loop
+ &foreach;), o PHP irá chamar a função generator toda vez que precisar de
+ um valor, em seguida salva o estado do generator quando o valor é produzido,
+ de modo que possa ser retomado quando o próximo valor for necessário.
+ </para>
+
+ <para>
+ Uma vez que não há mais valores a serem produzidos, a função generator pode
+ simplesmente sair, e a chamada de código continua como se um array tivesse
+ executado os valores.
+ </para>
+
+ <note>
+ <para>
+ Um generator não pode retornar um valor: isso resultará num erro de
+ compilação. Um <command>retorno</command> vazio é uma sintaxe válida e
+ fará com que o generator seja encerrado.
+ </para>
+ </note>
+
+ <sect2 xml:id="control-structures.yield">
+ <title>A palavra chave <command>yield</command></title>
+
+ <para>
+ O coração de uma função generator é a palavra chave
+ <command>yield</command>.
+ Na sua forma mais simples, uma declaração yield se parece muito com um
+ retorno, exceto que em vez de parar a execução da função e retornar, o
+ yield fornece um valor para o código de loop sobre o generator e pausa a
+ execução da função do generator.
+ </para>
+
+ <example>
+ <title>Um exemplo simples de valores yield</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function gen_one_to_three() {
+ for ($i = 1; $i <= 3; $i++) {
+ // Note that $i is preserved between yields.
+ yield $i;
+ }
+}
+
+$generator = gen_one_to_three();
+foreach ($generator as $value) {
+ echo "$value\n";
+}
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+1
+2
+3
+]]>
+ </screen>
+ </example>
+
+ <note>
+ <para>
+ Internamente, chaves inteiras sequenciais serão pareadas com os valores
+ entregues, assim como um array não associativo.
+ </para>
+ </note>
+
+ <caution>
+ <para>
+ Se você usar um yield em um contexto da expressão (por exemplo, a direita
+ de uma atribuição), você deve colocar a declaração yield entre parênteses.
+ Por exemplo, isso é válido:
+ </para>
+
+ <informalexample>
+ <programlisting role="php">
+<![CDATA[
+ $data = (yield $value);
+]]>
+ </programlisting>
+ </informalexample>
+
+ <para>
+ Mas isso não é válido terá como resultado um parse error:
+ </para>
+
+ <informalexample>
+ <programlisting role="php">
+<![CDATA[
+ $data = yield $value;
+]]>
+ </programlisting>
+ </informalexample>
+
+ <para>
+ A sintaxe pode ser usada em conjunto com o método
+ <methodname>Generator::send</methodname>.
+ </para>
+ </caution>
+
+ <sect3 xml:id="control-structures.yield.associative">
+ <title>Produzindo valores com chaves</title>
+
+ <para>
+ O PHP suporta arrays associativos e generators não são diferentes. Além
+ do produzir valores simples, como mostrado acima, você também pode produzir
+ uma chave ao mesmo tempo.
+ </para>
+
+ <para>
+ A sintaxe para preparar um par de chave/valor é muito semelhante ao
+ utilizado para definir um array associativo, como mostrado abaixo.
+ </para>
+
+ <example>
+ <title>Produzindo um par de chave/valor</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+/*
+ * The input is semi-colon separated fields, with the first
+ * field being an ID to use as a key.
+ */
+
+$input = <<<'EOF'
+1;PHP;Likes dollar signs
+2;Python;Likes whitespace
+3;Ruby;Likes blocks
+EOF;
+
+function input_parser($input) {
+ foreach (explode("\n", $input) as $line) {
+ $fields = explode(';', $line);
+ $id = array_shift($fields);
+
+ yield $id => $fields;
+ }
+}
+
+foreach (input_parser($input) as $id => $fields) {
+ echo "$id:\n";
+ echo " $fields[0]\n";
+ echo " $fields[1]\n";
+}
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+1:
+ PHP
+ Likes dollar signs
+2:
+ Python
+ Likes whitespace
+3:
+ Ruby
+ Likes blocks
+]]>
+ </screen>
+ </example>
+
+ <caution>
+ <para>
+ Da mesma forma como acontece com o yield de valores simples mostrados
+ anteriormente, produzir um par de chave/valor num contexto da expressão
+ requer que a declaração do yield esteja entre parênteses:
+ </para>
+
+ <informalexample>
+ <programlisting role="php">
+<![CDATA[
+ $data = (yield $key => $value);
+]]>
+ </programlisting>
+ </informalexample>
+ </caution>
+ </sect3>
+
+ <sect3 xml:id="control-structures.yield.null">
+ <title>Produzindo valores nulos</title>
+
+ <para>
+ O yield pode ser chamado sem um argumento para produzir um valor &null;
+ com uma chave automática.
+ </para>
+
+ <example>
+ <title>Produzindo valores &null;os</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function gen_three_nulls() {
+ foreach (range(1, 3) as $i) {
+ yield;
+ }
+}
+
+var_dump(iterator_to_array(gen_three_nulls()));
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+array(3) {
+ [0]=>
+ NULL
+ [1]=>
+ NULL
+ [2]=>
+ NULL
+}
+]]>
+ </screen>
+ </example>
+ </sect3>
+
+ <sect3 xml:id="control-structures.yield.references">
+ <title>Produzindo valores por referência</title>
+
+ <para>
+ Funções generator são capazes de produzir valores por referência bem como
+ por valor. Isso é feito da mesma forma que
+ <link linkend="functions.returning-values">retornar referências de funções</link>:
+ incluindo um &amp; no início do nome da função.
+ </para>
+
+ <example>
+ <title>Produzindo valores por referência</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function &gen_reference() {
+ $value = 3;
+
+ while ($value > 0) {
+ yield $value;
+ }
+}
+
+/*
+ * Note that we can change $number within the loop, and
+ * because the generator is yielding references, $value
+ * within gen_reference() changes.
+ */
+foreach (gen_reference() as &$number) {
+ echo (--$number).'... ';
+}
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+2... 1... 0...
+]]>
+ </screen>
+ </example>
+ </sect3>
+ </sect2>
+
+ <sect2 xml:id="language.generators.object">
+ <title>Objetos <classname>Generator</classname></title>
+ <para>
+ Quando uma função é chamada pela primeira vez, um objeto da classe interna
+ <classname>Generator</classname> é retornado. Esse objeto implementa
+ a interface <classname>Iterator</classname> da mesma forma como um objeto
+ iterator que se move só para frente faria.
+ </para>
+ </sect2>
+
+ </sect1>
+
+ <sect1 xml:id="language.generators.comparison">
+ <title>Comparando generators com objetos <classname>Iterator</classname></title>
+
+ <para>
+ A principal vantagem dos generators é a sua simplicidade. Muito menos código
+ clichê tem de ser reescrito em comparação com a implementação de uma classe
+ <classname>Iterator</classname>, e o código geralmente é muito mais legível.
+ Por exemplo, a seguinte função e classe são equivalentes:
+ </para>
+
+ <informalexample>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function getLinesFromFile($fileName) {
+ if (!$fileHandle = fopen($fileName, 'r')) {
+ return;
+ }
+
+ while (false !== $line = fgets($fileHandle)) {
+ yield $line;
+ }
+
+ fclose($fileHandle);
+}
+
+// versus...
+
+class LineIterator implements Iterator {
+ protected $fileHandle;
+
+ protected $line;
+ protected $i;
+
+ public function __construct($fileName) {
+ if (!$this->fileHandle = fopen($fileName, 'r')) {
+ throw new RuntimeException('Couldn\'t open file "' . $fileName . '"');
+ }
+ }
+
+ public function rewind() {
+ fseek($this->fileHandle, 0);
+ $this->line = fgets($this->fileHandle);
+ $this->i = 0;
+ }
+
+ public function valid() {
+ return false !== $this->line;
+ }
+
+ public function current() {
+ return $this->line;
+ }
+
+ public function key() {
+ return $this->i;
+ }
+
+ public function next() {
+ if (false !== $this->line) {
+ $this->line = fgets($this->fileHandle);
+ $this->i++;
+ }
+ }
+
+ public function __destruct() {
+ fclose($this->fileHandle);
+ }
+}
+?>
+]]>
+ </programlisting>
+ </informalexample>
+
+ <para>
+ No entanto essa flexibilidade tem um custo: os generators somente movem-se
+ para frente e não podem ser rebobinados após a iteração ter sido iniciada.
+ Isso também significa que o generator não pode ser iterado múltiplas vezes:
+ o generator precisará ser reconstruído chamando a função generator novamente,
+ ou clonado usando a palavra chave <link linkend="language.oop5.cloning">clone</link>.
+ </para>
+ </sect1>
+</chapter>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+indent-tabs-mode:nil
+sgml-parent-document:nil
+sgml-default-dtd-file:"~/.phpdoc/manual.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+vim600: syn=xml fen fdm=syntax fdl=2 si
+vim: et tw=78 syn=sgml
+vi: ts=1 sw=1
+-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment