<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/language.generators.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ja',
  ),
  'this' => 
  array (
    0 => 'language.generators.syntax.php',
    1 => 'ジェネレータの構文',
    2 => 'ジェネレータの構文',
  ),
  'up' => 
  array (
    0 => 'language.generators.php',
    1 => 'ジェネレータ',
  ),
  'prev' => 
  array (
    0 => 'language.generators.overview.php',
    1 => 'ジェネレータとは',
  ),
  'next' => 
  array (
    0 => 'language.generators.comparison.php',
    1 => 'ジェネレータと Iterator オブジェクトとの比較',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ja',
    'path' => 'language/generators.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="language.generators.syntax" class="sect1">
  <h2 class="title">ジェネレータの構文</h2>

  <p class="para">
   ジェネレータ関数の見た目はふつうの関数とほぼ同じです。違うのは、値を返すのではなく、
   必要なだけ値を <a href="language.generators.syntax.php#control-structures.yield" class="link"><code class="literal">yield</code></a> することです。
   <a href="language.generators.syntax.php#control-structures.yield" class="link"><code class="literal">yield</code></a> が含まれていれば、どんな関数でもジェネレータ関数です。
  </p>

  <p class="para">
   ジェネレータ関数が呼ばれると、反復処理が可能なオブジェクトを返します。
   このオブジェクトを (<a href="control-structures.foreach.php" class="link"><code class="literal">foreach</code></a> ループなどで) 反復させると、
   値が必要になるたびに PHP がオブジェクトの反復メソッドを呼びます。
   そして、ジェネレータが値を yield した時点の状態を保存しておき、
   次に値が必要になったときにはそこから再開できるようにします。
  </p>

  <p class="para">
   yield できる値がなくなると、ジェネレータは単純に呼び出し元に制御を戻します。
   呼び出し元のコードでは、配列の要素をすべて処理し終えた後のように、そのまま処理が続きます。
  </p>

  <blockquote class="note"><p><strong class="note">注意</strong>: 
   <p class="para">
    ジェネレータは値を返すことができます。返した値は
    <span class="methodname"><a href="generator.getreturn.php" class="methodname">Generator::getReturn()</a></span> で取得することが出来ます。
   </p>
  </p></blockquote>

  <div class="sect2" id="control-structures.yield">
   <h3 class="title"><strong class="command">yield</strong> キーワード</h3>

   <p class="para">
    ジェネレータ関数の肝となるのが <strong class="command">yield</strong> キーワードです。
    最もシンプルな書きかたをすると、yield 文の見た目は return 文とほぼ同じになります。
    ただ、return の場合はそこで関数の実行を終了して値を返すのに対して、
    yield の場合はジェネレータを呼び出しているループに値を戻して
    ジェネレータ関数の実行を一時停止します。
   </p>

   <div class="example" id="example-1">
    <p><strong>例1 値を yield する単純な例</strong></p>
    <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">gen_one_to_three</span><span style="color: #007700">() {<br />    for (</span><span style="color: #0000BB">$i </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">; </span><span style="color: #0000BB">$i </span><span style="color: #007700">&lt;= </span><span style="color: #0000BB">3</span><span style="color: #007700">; </span><span style="color: #0000BB">$i</span><span style="color: #007700">++) {<br />        </span><span style="color: #FF8000">// yield を繰り返す間、$i の値が維持されることに注目しましょう<br />        </span><span style="color: #007700">yield </span><span style="color: #0000BB">$i</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$generator </span><span style="color: #007700">= </span><span style="color: #0000BB">gen_one_to_three</span><span style="color: #007700">();<br />foreach (</span><span style="color: #0000BB">$generator </span><span style="color: #007700">as </span><span style="color: #0000BB">$value</span><span style="color: #007700">) {<br />    echo </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$value</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

    <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
    <div class="example-contents screen">
<div class="cdata"><pre>
1
2
3
</pre></div>
    </div>
   </div>

   <blockquote class="note"><p><strong class="note">注意</strong>: 
    <p class="para">
     内部的には整数の連番のキーが yield する値とペアになり、
     配列と同じようになります。
    </p>
   </p></blockquote>

   <div class="sect3" id="control-structures.yield.associative">
    <h4 class="title">値とキーの yield</h4>

    <p class="para">
     PHP は、数値添字の配列だけでなく連想配列にも対応しています。ジェネレータも例外ではありません。
     先ほどの例のように単なる値を yield するだけでなく、
     値と同時にキーも yield することができます。
    </p>

    <p class="para">
     キーと値のペアを yield する構文は連想配列の定義とよく似ており、次のようになります。
    </p>

    <div class="example" id="example-2">
     <p><strong>例2 キー/値 のペアの yield</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">/*<br /> * 入力は各フィールドをセミコロンで区切ったものです<br /> * 最初のフィールドが ID となり、これをキーとして使います<br /> */<br /><br /></span><span style="color: #0000BB">$input </span><span style="color: #007700">= &lt;&lt;&lt;'EOF'<br /></span><span style="color: #DD0000">1;PHP;$が大好き<br />2;Python;インデントが大好き<br />3;Ruby;ブロックが大好き<br /></span><span style="color: #007700">EOF;<br /><br />function </span><span style="color: #0000BB">input_parser</span><span style="color: #007700">(</span><span style="color: #0000BB">$input</span><span style="color: #007700">) {<br />    foreach (</span><span style="color: #0000BB">explode</span><span style="color: #007700">(</span><span style="color: #DD0000">"\n"</span><span style="color: #007700">, </span><span style="color: #0000BB">$input</span><span style="color: #007700">) as </span><span style="color: #0000BB">$line</span><span style="color: #007700">) {<br />        </span><span style="color: #0000BB">$fields </span><span style="color: #007700">= </span><span style="color: #0000BB">explode</span><span style="color: #007700">(</span><span style="color: #DD0000">';'</span><span style="color: #007700">, </span><span style="color: #0000BB">$line</span><span style="color: #007700">);<br />        </span><span style="color: #0000BB">$id </span><span style="color: #007700">= </span><span style="color: #0000BB">array_shift</span><span style="color: #007700">(</span><span style="color: #0000BB">$fields</span><span style="color: #007700">);<br /><br />        yield </span><span style="color: #0000BB">$id </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$fields</span><span style="color: #007700">;<br />    }<br />}<br /><br />foreach (</span><span style="color: #0000BB">input_parser</span><span style="color: #007700">(</span><span style="color: #0000BB">$input</span><span style="color: #007700">) as </span><span style="color: #0000BB">$id </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$fields</span><span style="color: #007700">) {<br />    echo </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$id</span><span style="color: #DD0000">:\n"</span><span style="color: #007700">;<br />    echo </span><span style="color: #DD0000">"    </span><span style="color: #0000BB">$fields</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />    echo </span><span style="color: #DD0000">"    </span><span style="color: #0000BB">$fields</span><span style="color: #007700">[</span><span style="color: #0000BB">1</span><span style="color: #007700">]</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
1:
    PHP
    $が大好き
2:
    Python
    インデントが大好き
3:
    Ruby
    ブロックが大好き
</pre></div>
     </div>
    </div>
   </div>

   <div class="sect3" id="control-structures.yield.null">
    <h4 class="title">null 値の yield</h4>

    <p class="para">
     何も引数を渡さずに yield を呼ぶと、<strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong> 値を yield します。キーは自動的に割り振られます。
    </p>

    <div class="example" id="example-3">
     <p><strong>例3 <strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong> の yield</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">gen_three_nulls</span><span style="color: #007700">() {<br />    foreach (</span><span style="color: #0000BB">range</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">, </span><span style="color: #0000BB">3</span><span style="color: #007700">) as </span><span style="color: #0000BB">$i</span><span style="color: #007700">) {<br />        yield;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">iterator_to_array</span><span style="color: #007700">(</span><span style="color: #0000BB">gen_three_nulls</span><span style="color: #007700">()));<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
array(3) {
  [0]=&gt;
  NULL
  [1]=&gt;
  NULL
  [2]=&gt;
  NULL
}
</pre></div>
     </div>
    </div>
   </div>

   <div class="sect3" id="control-structures.yield.references">
    <h4 class="title">参照による yield</h4>

    <p class="para">
     ジェネレータ関数は、値を参照として yield することもできます。
     <a href="functions.returning-values.php" class="link">関数の結果を参照で返す</a>
     ときと同じように、関数名の前にアンパサンドを付けます。
    </p>

    <div class="example" id="example-4">
     <p><strong>例4 参照による値の yield</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function &amp;</span><span style="color: #0000BB">gen_reference</span><span style="color: #007700">() {<br />    </span><span style="color: #0000BB">$value </span><span style="color: #007700">= </span><span style="color: #0000BB">3</span><span style="color: #007700">;<br /><br />    while (</span><span style="color: #0000BB">$value </span><span style="color: #007700">&gt; </span><span style="color: #0000BB">0</span><span style="color: #007700">) {<br />        yield </span><span style="color: #0000BB">$value</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #FF8000">/*<br /> * $number をループ内で変更していることに注目しましょう。<br /> * このジェネレータは参照を yield するので、<br /> * gen_reference() 内の $value が変わります。<br /> */<br /></span><span style="color: #007700">foreach (</span><span style="color: #0000BB">gen_reference</span><span style="color: #007700">() as &amp;</span><span style="color: #0000BB">$number</span><span style="color: #007700">) {<br />    echo (--</span><span style="color: #0000BB">$number</span><span style="color: #007700">).</span><span style="color: #DD0000">'... '</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
2... 1... 0...
</pre></div>
     </div>
    </div>
   </div>

   <div class="sect3" id="control-structures.yield.from">
    <h4 class="title"><strong class="command">yield from</strong> によるジェネレータの委譲</h4>

    <p class="para">
     ジェネレーターを委譲することで、
     別のジェネレータや <span class="classname"><a href="class.traversable.php" class="classname">Traversable</a></span> オブジェクトあるいは配列から、
     <strong class="command">yield from</strong> キーワードを使って値を yield できます。
     外側のジェネレータは、内側のジェネレータ (あるいはオブジェクトや配列) から受け取れるすべての値を yield し、
     何も取得できなくなったら外側のジェネレータの処理を続行します。
    </p>

    <p class="para">
     ジェネレータに対して <strong class="command">yield from</strong> を使った場合は、
     <strong class="command">yield from</strong> 式は内側のジェネレータが返す任意の値を返します。
    </p>
    
    <div class="caution"><strong class="caution">警告</strong>
     <h1 class="title"><span class="function"><a href="function.iterator-to-array.php" class="function">iterator_to_array()</a></span> を用いた、配列への格納</h1>

      <p class="para">
       <strong class="command">yield from</strong> は配列のキーをリセットしません。
       <span class="classname"><a href="class.traversable.php" class="classname">Traversable</a></span> オブジェクトや <span class="type"><a href="language.types.array.php" class="type array">array</a></span>
       が返すキーを、そのまま利用します。つまり、別々の
       <strong class="command">yield</strong> や <strong class="command">yield from</strong>
       から取得した異なる値のキーが、重複することもありえます。
       これを配列に格納すると、後からきた値がそれまでの値を上書きします。
      </p>

      <p class="para">
       <span class="function"><a href="function.iterator-to-array.php" class="function">iterator_to_array()</a></span> を使う場合に問題になることがよくあります。
       この関数はデフォルトで数値添字配列を返すので、予期せぬ結果を引き起こす可能性があります。
       <span class="function"><a href="function.iterator-to-array.php" class="function">iterator_to_array()</a></span> には二番目のパラメータ
       <code class="parameter">preserve_keys</code> があり、これを <strong><code><a href="reserved.constants.php#constant.false">false</a></code></strong>
       にすれば、<span class="classname"><a href="class.generator.php" class="classname">Generator</a></span> が返すキーを無視してすべての値を取得できます。
      </p>
     
      <div class="example" id="example-5">
       <p><strong>例5 <strong class="command">yield from</strong> と <span class="function"><a href="function.iterator-to-array.php" class="function">iterator_to_array()</a></span></strong></p>
       <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">inner</span><span style="color: #007700">() {<br />    yield </span><span style="color: #0000BB">1</span><span style="color: #007700">; </span><span style="color: #FF8000">// キー 0<br />    </span><span style="color: #007700">yield </span><span style="color: #0000BB">2</span><span style="color: #007700">; </span><span style="color: #FF8000">// キー 1<br />    </span><span style="color: #007700">yield </span><span style="color: #0000BB">3</span><span style="color: #007700">; </span><span style="color: #FF8000">// キー 2<br /></span><span style="color: #007700">}<br />function </span><span style="color: #0000BB">gen</span><span style="color: #007700">() {<br />    yield </span><span style="color: #0000BB">0</span><span style="color: #007700">; </span><span style="color: #FF8000">// キー 0<br />    </span><span style="color: #007700">yield from </span><span style="color: #0000BB">inner</span><span style="color: #007700">(); </span><span style="color: #FF8000">// キー 0〜2<br />    </span><span style="color: #007700">yield </span><span style="color: #0000BB">4</span><span style="color: #007700">; </span><span style="color: #FF8000">// キー 1<br /></span><span style="color: #007700">}<br /></span><span style="color: #FF8000">// 二番目のパラメータに false を指定すると、結果は array [0, 1, 2, 3, 4] となります<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">iterator_to_array</span><span style="color: #007700">(</span><span style="color: #0000BB">gen</span><span style="color: #007700">()));<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
       </div>

       <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
       <div class="example-contents screen">
<div class="cdata"><pre>
array(3) {
  [0]=&gt;
  int(1)
  [1]=&gt;
  int(4)
  [2]=&gt;
  int(3)
}
</pre></div>
       </div>
      </div>
    </div>

    <div class="example" id="example-6">
     <p><strong>例6 <strong class="command">yield from</strong> の基本的な使いかた</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">count_to_ten</span><span style="color: #007700">() {<br />    yield </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />    yield </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br />    yield from [</span><span style="color: #0000BB">3</span><span style="color: #007700">, </span><span style="color: #0000BB">4</span><span style="color: #007700">];<br />    yield from new </span><span style="color: #0000BB">ArrayIterator</span><span style="color: #007700">([</span><span style="color: #0000BB">5</span><span style="color: #007700">, </span><span style="color: #0000BB">6</span><span style="color: #007700">]);<br />    yield from </span><span style="color: #0000BB">seven_eight</span><span style="color: #007700">();<br />    yield </span><span style="color: #0000BB">9</span><span style="color: #007700">;<br />    yield </span><span style="color: #0000BB">10</span><span style="color: #007700">;<br />}<br /><br />function </span><span style="color: #0000BB">seven_eight</span><span style="color: #007700">() {<br />    yield </span><span style="color: #0000BB">7</span><span style="color: #007700">;<br />    yield from </span><span style="color: #0000BB">eight</span><span style="color: #007700">();<br />}<br /><br />function </span><span style="color: #0000BB">eight</span><span style="color: #007700">() {<br />    yield </span><span style="color: #0000BB">8</span><span style="color: #007700">;<br />}<br /><br />foreach (</span><span style="color: #0000BB">count_to_ten</span><span style="color: #007700">() as </span><span style="color: #0000BB">$num</span><span style="color: #007700">) {<br />    echo </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$num</span><span style="color: #DD0000"> "</span><span style="color: #007700">;<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
1 2 3 4 5 6 7 8 9 10
</pre></div>
     </div>
    </div>

    <div class="example" id="example-7">
     <p><strong>例7 <strong class="command">yield from</strong> の返す値</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">count_to_ten</span><span style="color: #007700">() {<br />    yield </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />    yield </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br />    yield from [</span><span style="color: #0000BB">3</span><span style="color: #007700">, </span><span style="color: #0000BB">4</span><span style="color: #007700">];<br />    yield from new </span><span style="color: #0000BB">ArrayIterator</span><span style="color: #007700">([</span><span style="color: #0000BB">5</span><span style="color: #007700">, </span><span style="color: #0000BB">6</span><span style="color: #007700">]);<br />    yield from </span><span style="color: #0000BB">seven_eight</span><span style="color: #007700">();<br />    return yield from </span><span style="color: #0000BB">nine_ten</span><span style="color: #007700">();<br />}<br /><br />function </span><span style="color: #0000BB">seven_eight</span><span style="color: #007700">() {<br />    yield </span><span style="color: #0000BB">7</span><span style="color: #007700">;<br />    yield from </span><span style="color: #0000BB">eight</span><span style="color: #007700">();<br />}<br /><br />function </span><span style="color: #0000BB">eight</span><span style="color: #007700">() {<br />    yield </span><span style="color: #0000BB">8</span><span style="color: #007700">;<br />}<br /><br />function </span><span style="color: #0000BB">nine_ten</span><span style="color: #007700">() {<br />    yield </span><span style="color: #0000BB">9</span><span style="color: #007700">;<br />    return </span><span style="color: #0000BB">10</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$gen </span><span style="color: #007700">= </span><span style="color: #0000BB">count_to_ten</span><span style="color: #007700">();<br />foreach (</span><span style="color: #0000BB">$gen </span><span style="color: #007700">as </span><span style="color: #0000BB">$num</span><span style="color: #007700">) {<br />    echo </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$num</span><span style="color: #DD0000"> "</span><span style="color: #007700">;<br />}<br />echo </span><span style="color: #0000BB">$gen</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getReturn</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     <div class="example-contents"><p>上の例の出力は以下となります。</p></div>
     <div class="example-contents screen">
<div class="cdata"><pre>
1 2 3 4 5 6 7 8 9 10
</pre></div>
     </div>
    </div>
   </div>
  </div>
 </div><?php manual_footer($setup); ?>