SlideShare a Scribd company logo
PHPカンファレンス2012


PHP5.5新機能                かもしれない




Generator
初心者入門
makoto kuwata <kwa@kuwata-lab.com>
http://www.kuwata-lab.com/
2012-09-15 (Sat)




                    copyright(c) 2012 kuwata-lab.com all rights reserved.
本発表について
【目的】 • PHP5.5の新機能かもしれない「ジェネレータ」を、
       「なんだか凄そうだ」と思ってもらう。


【内容】 • ジェネレータって何?
      • どううれしいの?
      • どんなことに使えるの?


【注意】 • 内容は2012-09-15時点での情報に基づく。
       今後、仕様変更があり得るので注意。


          copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータって何?
What is Generator?




                copyright(c) 2012 kuwata-lab.com all rights reserved.
まとめ

◆ ジェネレータ                                     セーブ機能


◆ ジェネレータ関数                                   ゲームシナリオ


◆ ジェネレータオブジェクト                                            冒険の書
                                                        (セーブデータ)

◆ yield文                                     宿屋(セーブポイント)


           copyright(c) 2012 kuwata-lab.com all rights reserved.
通常の関数

	 1:	 function	 func()	 {
	 2:	 	 	 	 $i	 =	 0;
                         1, 2, 3回目 (0が返される)
	 3:	 	 	 	 return	 $i;
	 4:	 	 	 	 $i++;
	 5:	 	 	 	 return	 $i;
	 6:	 	 	 	 $i++;
	 7:	 	 	 	 return	 $i;
	 8:	 }
                     毎回先頭から実行され、また
                   return文より後ろは実行されない


            copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータ (Generator) 関数

	 1:	 function	 gfunc()	 {
	 2:	 	 	 	 $i	 =	 0;
                        1回目 (0が返される)
	 3:	 	 	 	 yield	 $i;
	 4:	 	 	 	 $i++;
	 5:	 	 	 	 yield	 $i;  2回目 (1が返される)
	 6:	 	 	 	 $i++;
	 7:	 	 	 	 yield	 $i;  3回目 (2が返される)
	 8:	 }
           前回の終了位置から再開



           copyright(c) 2012 kuwata-lab.com all rights reserved.
使い方
         ジェネレータオブジェクトを生成
       (通常の関数と使い方が違うことに注意!)

	 1:	 $g	 =	 gfunc();
	 2:	 foreach	 ($g	 as	 $x)	 {
	 3:	 	 	 	 var_dump($x);
	 4:	 }
                         foreach文とともに使用
                       (イテレータとして振る舞う)
実行例
int(0)
int(1)
int(2)

             copyright(c) 2012 kuwata-lab.com all rights reserved.
実行順序:ループ1回目

メインプログラム                                    ジェネレータ関数

1
  $g	 =	 gfunc();                            function	 gfunc(){
2
  foreach($g	 as	 $x){                       	 	 $i	 =	 0;
                                               3
  	 	 var_dump($x);                          	 	 yield	 $i;
                                               4
    5
  }                                          	 	 $i++;
  echo	 "donen";                            	 	 yield	 $i;
                                             	 	 $i++;
                                             	 	 return	 $i;
                                             }

              copyright(c) 2012 kuwata-lab.com all rights reserved.
実行順序:ループ2回目

メインプログラム                                    ジェネレータ関数
  $g	 =	 gfunc();                            function	 gfunc(){
6
  foreach($g	 as	 $x){                       	 	 $i	 =	 0;
  	 	 var_dump($x);                          	 	 yield	 $i;
    9
  }                                          	 	 $i++;
                                               7

  echo	 "donen";                            	 	 yield	 $i;
                                               8
                                             	 	 $i++;
                                             	 	 return	 $i;
                                             }

              copyright(c) 2012 kuwata-lab.com all rights reserved.
実行順序:ループ3回目…は、ない

 メインプログラム                                   ジェネレータ関数
  $g	 =	 gfunc();                            function	 gfunc(){
10foreach($g	 as	 $x){                       	 	 $i	 =	 0;
  	 	 var_dump($x);                          	 	 yield	 $i;
  }                                          	 	 $i++;
                                             	 	 yield	 $i;
13echo	 "donen";
                                             	 	 $i++;
                                             11
                                             	 	 return	 $i;
                                             12
・ループのたびにyield文まで実行
・yield文の引数がループ変数に
                                             }

              copyright(c) 2012 kuwata-lab.com all rights reserved.
サンプル:2つの値を交互に出力

	 1:	 function	 toggle($odd,	 $even)	 {
	 2:	 	 	 	 while	 (TRUE)	 {
	 3:	 	 	 	 	 	 	 yield	 $odd;
	 4:	 	 	 	 	 	 	 yield	 $even;
	 5:	 	 	 	 }
	 6:	 }
	 7:	 
	 8:	 //	 "red"	 と	 "blue"	 を交互に出力
	 9:	 foreach	 (toggle("red",	 "blue")	 as	 $c){
10:	 	 	 	 echo	 $c,	 "n";	 	 //	 無限に出力
11:	 }


              copyright(c) 2012 kuwata-lab.com all rights reserved.
サンプル:フィボナッチ数列 (0, 1, 1, 2, 3, 5, 8, 13,...)

	 1:	 function	 fib()	 {
	 2:	 	 	 	 $x	 =	 0;	 $y	 =	 1; コツ:ループの終了条件を
	 3:	 	 	 	 while	 (TRUE)	 {         指定しない (無限ループ)
	 4:	 	 	 	 	 	 	 yield	 $x;
	 5:	 	 	 	 	 	 	 list($x,	 $y)	 =	 [$y,	 $x+$y];
	 6:	 	 	 	 }
	 7:	 }
	 8:
	 9:	 //	 100未満のフィボナッチ数列を出力
10:	 foreach	 (fib()	 as	 $x)	 {
11:	 	 	 	 if	 ($x	 >=	 100)	 break;
12:	 	 	 	 echo	 $x,	 "n";             コツ:終了条件は呼
13:	 }                                  び出す側で指定する

              copyright(c) 2012 kuwata-lab.com all rights reserved.
まとめ

◆ ジェネレータ                                     セーブ機能


◆ ジェネレータ関数                                   ゲームシナリオ


◆ ジェネレータオブジェクト                                            冒険の書
                                                        (セーブデータ)

◆ yield文                                     宿屋(セーブポイント)


           copyright(c) 2012 kuwata-lab.com all rights reserved.
どううれしいの?
Why Generator is so useful?




                copyright(c) 2012 kuwata-lab.com all rights reserved.
Before: ファイルを1行ずつ処理する

	 1:	 	 	 	 //	 行番号つきで表示
	 2:	 	 	 	 $f	 =	 fopen($filename,	 'r');
	 3:	 	 	 	 if	 ($f	 ===	 FALSE)	 throw	 ....;
	 4:	 	 	 	 $line	 =	 fgets($f);
	 5:	 	 	 	 while	 ($line	 !==	 FALSE)	 {
	 6:	 	 	 	 	 	 	 ++$i;
	 7:	 	 	 	 	 	 	 echo	 $i,	 ":	 ",	 $line;
	 8:	 	 	 	 	 	 	 $line	 =	 fgets($f);
	 9:	 	 	 	 }
10:	 	 	 	 fclose($f);
11:	 
               copyright(c) 2012 kuwata-lab.com all rights reserved.
Before: ファイルを1行ずつ処理する

	 1:	 	 	 	 //	 パターンで絞り込む
	 2:	 	 	 	 $f	 =	 fopen($filename,	 'r');
	 3:	 	 	 	 if	 ($f	 ===	 FALSE)	 throw	 ....;
	 4:	 	 	 	 $line	 =	 fgets($f);
	 5:	 	 	 	 while	 ($line	 !==	 FALSE)	 {
	 6:	 	 	 	 	 	 	 if	 (preg_match('/@/',	 $line))
	 7:	 	 	 	 	 	 	 	 	 	 echo	 $line;
	 8:	 	 	 	 	 	 	 $line	 =	 fgets($f);
	 9:	 	 	 	 }
10:	 	 	 	 fclose($f);
11:	 
              copyright(c) 2012 kuwata-lab.com all rights reserved.
Before: ファイルを1行ずつ処理する

	 1:	 	 	 	 //	 タブ文字でフィールドに分解
	 2:	 	 	 	 $f	 =	 fopen($filename,	 'r');
	 3:	 	 	 	 if	 ($f	 ===	 FALSE)	 throw	 ....;
	 4:	 	 	 	 $line	 =	 fgets($f);
	 5:	 	 	 	 while	 ($line	 !==	 FALSE)	 {
	 6:	 	 	 	 	 	 	 $arr	 =	 explode("t",	 $line);
	 7:	 	 	 	 	 	 	 echo	 $arr[1],	 "n";
	 8:	 	 	 	 	 	 	 $line	 =	 fgets($f);
	 9:	 	 	 	 }                    汎用性の高いコードの中に
10:	 	 	 	 fclose($f);           汎用性の低いコードが混在
11:	 
              copyright(c) 2012 kuwata-lab.com all rights reserved.
After: ジェネレータ関数
                                            汎用性の高い箇所を関数に抽出

	 1: function	 each_line($filename)	 {
	 2:	 	 	 	 $f	 =	 fopen($filename,	 'r');
	 3:	 	 	 	 if	 ($f	 ===	 FALSE)	 throw	 ....;
	 4:	 	 	 	 $line	 =	 fgets($f);
	 5:	 	 	 	 while	 ($line	 !==	 FALSE)	 {
	 6:	 	 	 	 	 	 	 $arr	 =	 explode("t",	 $line);
                  yield	 $line;
	 7:	 	 	 	 	 	 	 echo	 $arr[1];
                        汎用性の低い箇所を yield 文に
	 8:	 	 	 	 	 	 	 $line	 =	 fgets($f);
	 9:	 	 	 	 }
10:	 	 	 	 fclose($f);
11:	 }
               copyright(c) 2012 kuwata-lab.com all rights reserved.
After: メインプログラム

	 1:	 //	 ジェネレータオブジェクトを生成
	 2:	 $g	 =	 each_line($filename);
	 3:	 //	 メインループ
	 4:	 foreach	 ($g	 as	 $line)	 {
	 5:	 	 	 	 //	 汎用性の低い処理
	 6:	 	 	 	 $arr	 =	 explode("t",	 $line);
	 7:	 	 	 	 echo	 $arr[1],	 "n";
	 8:	 }




              copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータの利点

◆ ループ処理から、汎用性の高い箇所だけを切り
  出せる(再利用性の向上)
◆


◆


◆



      copyright(c) 2012 kuwata-lab.com all rights reserved.
もっとジェネレータ関数
          ジェネレータオブジェクトを受け取り、新し
          い別のジェネレータオブジェクトを生成する

	 1:	 	 	 	 //	 ジェネレータオブジェクトを作成            受け取る
        function	 each_fields($g)	 {
	 2:	 	 	 	 $g	 =	 each_line($filename);
	 3:	 	 	 	 //	 ループ                   配列やイテレータでも可
	 4:	 	 	 	 foreach	 ($g	 as	 $line)	 {
	 5:	 	 	 	 	 	 	 $arr	 =	 explode("t",	 $line);
	 6:	 	 	 	 	 	 	 echo	 $arr[1];
                  yield	 $arr;
	 7:	 	 	 	 }
	 8: }



             copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータを「重ねる」

	 1:	 //	 ジェネレータオブジェクトを生成
	 2:	 $g	 =	 each_line($filename);
	 3: $g	 =	 each_fields($g);         ジェネレータから
	 4:	 //	 メインループ                     別のジェネレータ
	 5:	 foreach	 ($g	 as	 $line)	 { を生成
                          $arr
	 6:	 	 	 	 $arr	 =	 explode("n",	 $line);  
                                            	 
	 7:	 	 	 	 echo	 $arr[1],	 "n";
	 8:	 }



             copyright(c) 2012 kuwata-lab.com all rights reserved.
1つの大きなループ vs. 複数の小さなループ

ジェネレータ使用前                                                  ジェネレータ使用後
$f	 =	 fopen($filename,	 'r');                              while	 ($line	 !==	 FALSE)	 {
$line	 =	 fgets($f);                                        	 	 yield	 $line;
while	 ($line	 !==	 FALSE)	 {                               }
	 	 $arr	 =	 explode("n",$line);	 
	 	 echo	 $arr[1];                                          foreach	 ($g	 as	 $line)	 {
	 	 $line	 =	 fgets($f);                                    	 	 yield	 $arr;
}                                                           }
fclose($f);
                                                            $g	 =	 each_line($filename);
                                                            $g	 =	 each_fields($g);
                                                            foreach	 ($g	 as	 $arr)	 {
                                                            	 	 echo	 $arr[1],	 "n";
                                                            }



                     copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータの利点

◆ ループ処理から、汎用性の高い箇所だけを切り
  出せる(再利用性の向上)
◆ ひとつの大きなループを、複数の小さなループ
  に分解できる(ループの簡素化とPipeline化)
◆


◆



        copyright(c) 2012 kuwata-lab.com all rights reserved.
従来方法との比較:配列にすべて格納する

	 1:	 function	 each_line($filename)	 {
	 2:	 	 	 	 $f	 =	 fopen($filename,	 'r');
	 3:	 	 	 	 $lines	 =	 array(); メモリを大量に消費
	 4:	 	 	 	 $line	 =	 fgets($f);(巨大データだと落ちる)
	 5:	 	 	 	 while	 ($line	 !==	 FALSE)	 {
	 6:	 	 	 	 	 	 	 $lines[]	 =	 $line;
	 7:	 	 	 	 	 	 	 $line	 =	 fgets($f);
	 8:	 	 	 	 }
	 9:	 	 	 	 fclose($f);          すべてを読み込まないと
10:	 	 	 	 return	 $lines;        結果が返ってこない
11:	 }

            copyright(c) 2012 kuwata-lab.com all rights reserved.
従来方法との比較:ジェネレータ

	 1:	 function	 each_line($filename)	 {
	 2:	 	 	 	 $f	 =	 fopen($filename,	 'r');
	 3:	 	 	 	 
                                 1度に1行しか読み込まない
	 4:	 	 	 	 $line	 =	 fgets($f); (巨大なデータでも落ちない)
	 5:	 	 	 	 while	 ($line	 !==	 FALSE)	 {
	 6:	 	 	 	 	 	 	 yield	 $line;
	 7:	 	 	 	 	 	 	 $line	 =	 fgets($f);
	 8:	 	 	 	 }                 読み込んだはしから値を返す
	 9:	 	 	 	 fclose($f); (ストリーム処理に最適)
10
11:	 }

             copyright(c) 2012 kuwata-lab.com all rights reserved.
リダイレクト v.s. パイプライン

すべてを配列に格納する                                  ≒「リダイレクト」
・巨大な中間ファイルが必要
・最後まで処理しないと何も出力されない


bash% command1 < input > tmp1
bash% command2 < tmp1 > tmp2
bash% command3 < tmp2



          copyright(c) 2012 kuwata-lab.com all rights reserved.
リダイレクト v.s. パイプライン

ジェネレータを連結する                                  ≒ 「パイプ」
・巨大な中間ファイルがいらない
・読み込んだはしから出力される


bash% cat input | command1 
                | command2 
                | command3



          copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータの利点

◆ ループ処理から、汎用性の高い箇所だけを切り
  出せる(再利用性の向上)
◆ ひとつの大きなループを、複数の小さなループ
  に分解できる(ループの簡素化とPipeline化)
◆ メモリ消費量が少ない
  (巨大なデータを扱ってもプロセスが落ちない)
◆ データを読んだはしから処理できる
  (ストリームデータも処理可能)

        copyright(c) 2012 kuwata-lab.com all rights reserved.
どんな使い道があるの?
Advanced Generator




               copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータとインタラクション

$g->send() … 次のyield文まで実行する

             メインプログラム                                               ジェネレータ関数
                                                                    からメインプログ
                                                                    ラムに値を返す
   foreach(){}                                               yield	 $value
 $g->send($arg)

メインプログラム
                 ジェネレータ関数
からジェネレータ
関数に値を渡せる



            copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータとインタラクション

双方向への値の受け渡しが可能に
メインプログラム

    $value	 =	 $g->send("arg");

                                                       send()の引数が
                                                       yield文の値に

                                                      yield文の引数が
                                                      send()の戻り値に
ジェネレータ関数
     $arg	 =	 (yield	 "value");

           copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータとインタラクション

メインプログラム                                     ジェネレータ関数

1$g	 =	 gfunc();                              function	 gfunc(){
$ret	 =	 $g->send(1);                         	 	 $arg	 =	 yield;
       2                                        3
$ret	 =	 $g->send(2);                         	 	 while	 (条件式)	 {
                                                 4
$ret	 =	 $g->send(3);                         	 	 	 	 $ret	 =	 ...;
                                                    5
                                              	 	 	 	 $arg	 =
                                              	 	 	 	 	 	 (yield	 $ret);
                                                        6
                                              	 	 	 	 var_dump($arg);
                                              	 	 }
                                              }

               copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータとインタラクション

メインプログラム                                   ジェネレータ関数
$g	 =	 gfunc();                             function	 gfunc(){
$ret	 =	 $g->send(1);                       	 	 $arg	 =	 yield;
$ret	 =	 $g->send(2);                       	 	 while	 (条件式)	 {
                                              9
        7
$ret	 =	 $g->send(3);                       	 	 	 	 $ret	 =	 ...;
                                                 10
                                            	 	 	 	 $arg	 =
                                            	 	 	 	 	 	 (yield	 $ret);
                                                     11
                                            	 	 	 	 var_dump($arg);
                                                  8
                                            	 	 }
                                            }

             copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータとインタラクション

メインプログラム                                   ジェネレータ関数
$g	 =	 gfunc();                             function	 gfunc(){
$ret	 =	 $g->send(1);                       	 	 $arg	 =	 yield;
$ret	 =	 $g->send(2);                       	 	 while	 (条件式)	 {
                                             14
$ret	 =	 $g->send(3);                       	 	 	 	 $ret	 =	 ...;
                                                 15
     12
                                            	 	 	 	 $arg	 =
                                            	 	 	 	 	 	 (yield	 $ret);
                                                     16
                                            	 	 	 	 var_dump($arg);
                                                 13
                                            	 	 }
                                            }

             copyright(c) 2012 kuwata-lab.com all rights reserved.
サンプル:数字あてゲーム
                            最初のsend()の引数値を変数に代入
1:	 function	 guess_quiz($num)	 {
2:	 	 	 	 $ans	 =	 yield;
3:	 	 	 	 while	 ($num	 !=	 $ans)	 {
4:	 	 	 	 	 	 	 if	 ($ans	 >	 $num)
5:	 	 	 	 	 	 	 	 	 	 $ans	 =	 (yield	 "too	 large");
6:	 	 	 	 	 	 	 else
7:	 	 	 	 	 	 	 	 	 	 $ans	 =	 (yield	 "too	 small");
8:	 	 	 	 }                     値を返し、かつsend()
9:	 }                           の引数値を変数に代入



                copyright(c) 2012 kuwata-lab.com all rights reserved.
サンプル:数字あてゲーム

1:	 $g	 =	 guess_quiz(mt_rand(1,	 100));
2:	 do	 {
3:	 	 	 	 echo	 "guess	 number	 (1-100):	 ";
4:	 	 	 	 $ans	 =	 fgets(STDIN,	 128);
5:	 	 	 	 if	 ($ans	 ===	 false)	 break;
6:	 	 	 	 $hint	 =	 $g->send($ans);
7:	 	 	 	 echo	 $hint	 ?	 $hint."n"
8:	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 :	 "Correct!n";
9:	 }	 while	 ($hint);                  値を送信し、かつ
                                                      次のyield文まで実行

               copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータとマルチスレッド

                                                                    Process
高機能



      機能は限られるが                                        Native Thread
      メモリ消費量が
      極めて少ない
      (=大量生成可能)
                                                 Green Thread

         Generator

                                                              リソース消費量
      : OSの機能として実現
      : 言語やライブラリで実現

            copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータと非同期処理

ネストしたコールバック関数
処理1(function($data)	 {
	 	 	 処理2(function($data)	 {
	 	 	 	 	 	 処理3(function($data)	 {
	 	 	 	 	 	 	 	 	 ....
	 	 	 	 	 	 });                                 読みにくい、
	 	 	 });                                       書きにくい、
});                                             わかりにくい




                    copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータと非同期処理

コールバック関数を数珠つなぎ
$d	 =	 new	 Deferred();
$d->next(function($data)	 {
	 	 	 	 	 	 ..処理1..;
})->next(function($data)	 {
	 	 	 	 	 	 ..処理2..;
})->next(function($data)	 {
	 	 	 	 	 	 ..処理3..;                                                記述量が多い、
                                                                    書き方が不自然
});


            copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータと非同期処理

ジェネレータ
function	 doSomething()	 {
	 	 	 $data	 =	 yield;
	 	 	 ...処理1...;
	 	 	 $data	 =	 yield;
	 	 	 ...処理2...;
	 	 	 $data	 =	 yield;
	 	 	 ...処理3...;          自然な書き方で
                          わかりやすい!
}


           copyright(c) 2012 kuwata-lab.com all rights reserved.
ジェネレータとページ遷移

1:	 $response	 =	 フォームを表示();
2:	 $request	 =	 (yield	 $response);
3:	 $response	 =	 プレビューを表示($request);
4:	 $request	 =	 (yield	 $response);
5:	 データベースに登録($request);

                               複数ページにまたがる遷移を
                               非同期処理と同じように記述 ※
                               (詳しくは「継続ベース フレームワーク」でggr)



※ Apache だとリクエストごとにすべてをリセットするので、実現できない。
  PHP のビルトイン Web サーバのようなパーシステントプロセスのサーバを使って、
 リクエストを超えてジェネレータオブジェクトを保持できるような仕組みが必要。
               copyright(c) 2012 kuwata-lab.com all rights reserved.
落とし穴:breakされた場合

	 1:	 function	 each_line($filename)	 {
	 2:	 	 	 	 $f	 =	 fopen($filename,	 'r');
	 3:	 	 	 	 $line	 =	 fgets($f);
	 4:	 	 	 	 while	 ($line	 !==	 FALSE)	 {
	 5:	 	 	 	 	 	 	 yield	 $line;
	 6:	 	 	 	 	 	 	 $line	 =	 fgets($f);
	 7:	 	 	 	 }
	 8:	 	 	 	 fclose($f);
	 9:	 }
                               呼び出し側でbreakされると
                                終了処理が行われない!※
                            (しかもPHPにはfinallyがないorz)

※ SPLFileObject も同じ問題を抱えているが、デストラクタで fclose() している。
                   copyright(c) 2012 kuwata-lab.com all rights reserved.
落とし穴:リファクタリング

奇数番目をyieldしてから、偶数番目をyieldする
	 1:	 function	 stepping($arr)	 {
	 2:	 	 	 	 $n	 =	 count($arr);
	 3:	 	 	 	 for	 ($i=0;	 $i<$n;	 $i+=2)
	 4:	 	 	 	 	 	 	 yield	 $arr[$i];
	 5:	 	 	 	 for	 ($i=1;	 $i<$n;	 $i+=2)
	 6:	 	 	 	 	 	 	 yield	 $arr[$i];
	 7:	 }
                                        DRYじゃない!関数化しよう!




              copyright(c) 2012 kuwata-lab.com all rights reserved.
落とし穴:リファクタリング

DRYになった、けど動かない!
	 1:	 function	 _sub($arr,	 $i,	 $n)	 {
	 2:	 	 	 	 for	 (;	 $i<$n;	 $i+=2)
	 3:	 	 	 	 	 	 	 yield	 $arr[$i];
	 4:	 }
	 5:	 function	 stepping($arr)	 {
	 6:	 	 	 	 $n	 =	 count($arr);
	 7:	 	 	 	 _sub($arr,	 0,	 $n);
	 8:	 	 	 	 _sub($arr,	 1,	 $n);
	 9:	 }
              ジェネレータ関数を呼び出して
              いるがforeach文を使ってない

              copyright(c) 2012 kuwata-lab.com all rights reserved.
落とし穴:リファクタリング

動くようになった…けどなんか腑に落ちない
	 1:	 function	 _sub($arr,	 $i,	 $n)	 {
	 2:	 	 	 	 for	 (;	 $i<$n;	 $i+=2)
	 3:	 	 	 	 	 	 	 yield	 $arr[$i];
	 4:	 }
	 5:	 function	 stepping($arr)	 {
	 6:	 	 	 	 $n	 =	 count($arr);
	 7:	 	 	 	 foreach	 (_sub($arr,	 0,	 $n)	 as	 $x)
	 8:	 	 	 	 	 	 	 yield	 $x;
	 9:	 	 	 	 foreach	 (_sub($arr,	 1,	 $n)	 as	 $x)
10:	 	 	 	 	 	 	 yield	 $x;
11:	 }
              copyright(c) 2012 kuwata-lab.com all rights reserved.
まとめ

◆ $->send()を使うと、双方向での値の受け渡し
  が可能
◆ マルチスレッドよりも低機能だが軽量
◆ 非同期処理が自然な形で記述できる
◆ 落とし穴もあるよ!




        copyright(c) 2012 kuwata-lab.com all rights reserved.
any questions?
おまけ
More Things




              copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:PHP5.5 コンパイル方法

$ git clone 
   https://github.com/nikic/php-src.git
$ cd php-src/
$ git checkout -b addGeneratorSupport 
   origin/addGeneratorSupport
$ ./buildconf
$ apxs2=/usr/local/apache2/bin/apxs
$ ./configure --with-apxs2=$apxs2
$ nice -20 time make
$ sapi/cli/php myexample.php


           copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:インデックスつきyield


	 1:	 function	 gfunc()	 {                                             //	 実行結果
	 2:	 	 	 	 yield	 'a';                                                0	 =>	 a
	 3:	 	 	 	 yield	 'b';                                                1	 =>	 b
	 4:	 	 	 	 yield	 99=>'c';                                            99	 =>	 c
	 5:	 }
	 6:	 
	 7:	 $g	 =	 gfunc();
	 8:	 foreach	 ($g	 as	 $k=>$v)	 {
	 9:	 	 	 echo	 "$k	 =>	 $v	 n";
10:	 }



               copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:参照渡しでのyield


	 1:	 function	 &gfunc(&$arr)	 {                                        //	 実行結果
	 2:	 	 	 foreach	 ($arr	 as	 &$x){                                     array(3)	 {
	 3:	 	 	 	 	 yield	 $x;                                                	 	 [0]=>
	 4:	 	 	 }                                                             	 	 int(11)
	 5:	 }                                                                 	 	 [1]=>
	 6:	                                                                   	 	 int(21)
	 7:	 $arr	 =	 [10,	 20,	 30];                                          	 	 [2]=>
	 8:	 $g	 =	 gfunc($arr);                                               	 	 &int(31)
	 9:	 foreach	 ($g	 as	 &$x)                                            }
10:	 	 	 $x	 +=	 1;
11:	 var_dump($arr);


                copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:クロージャとの比較

それ、クロージャでもできるよ!
function	 fib()	 {                              //	 使い方
	 	 list($x,	 $y)	 =                            $closure	 =	 fib();
	 	 	 	 [0,	 1];                                $x	 =	 $closure();
	 	 return	 function()                          while	 ($x	 <	 100)	 {
	 	 	 	 use	 ($x,	 $y)	 {                       	 	 echo	 $x,	 "n";
	 	 	 	 $tmp	 =	 $x;                            	 	 $x	 =	 $closure();
	 	 	 	 list($x,	 $y)	 =                        }
	 	 	 	 	 	 [$y,	 $x+$y];
	 	 	 	 return	 $tmp;
	 	 };
}


                 copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:クロージャとの比較

クロージャ版                                       ジェネレータ版
function	 fib()	 {                            function	 fib()	 {
	 	 list($x,	 $y)	 =                          	 	 list($x,	 $y)	 =
	 	 	 	 [0,	 1];                              	 	 	 	 [0,	 1];
	 	 return	 function()                        	 	 while	 (TRUE)	 {
	 	 	 	 use	 ($x,	 $y)	 {                     	 	 	 	 yield	 $x;
	 	 	 	 $tmp	 =	 $x;                          	 	 	 	 list($x,	 $y)	 =
	 	 	 	 list($x,	 $y)	 =                      	 	 	 	 	 	 [$y,	 $x+$y];
	 	 	 	 	 	 [$y,	 $x+$y];                     	 	 }
	 	 	 	 return	 $tmp;                         }
	 	 };
        ・毎回先頭から実行される                                    ・前回の終了場所から自動
}          制約                                            的に再開 (より自然な記述)
    ・すべてをreturnの前に書                                     ・yieldの後ろにも処理が書
      かなければならない制約                                        ける (より自然な記述)
               copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:内部イテレータとの比較

それ、内部イテレータでもできるよ!
function	 fib($fn)	 {                          //	 使い方
	 	 list($x,	 $y)	 =                           fib(function($x)	 {
	 	 	 	 [0,	 1];                               	 	 echo	 $x,	 "n";
	 	 while	 ($x	 <	 100)	 {                     });
	 	 	 	 $fn($x);
	 	 	 	 list($x,	 $y)	 =
	 	 	 	 	 	 [$y,	 $x+$y];
	 	 }
}




                copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:内部イテレータとの比較

ループの終了条件も指定したい場合は、非常にブサイク
function	 fib($c,$fn){                        //	 使い方          終了条件と…
	 	 list($x,	 $y)	 =                          fib(
	 	 	 	 [0,	 1];                              	 	 function($x)	 {
	 	 while	 ($c($x))	 {                        	 	 	 	 return	 $x	 <	 100;
	 	 	 	 $fn($x);                              	 	 },
	 	 	 	 list($x,	 $y)	 =                      	 	 function($x)	 {
	 	 	 	 	 	 [$y,	 $x+$y];                     	 	 	 	 echo	 $x,	 "n";
	 	 }                                         	 	 }
}                                             );       ボディ部の両方が必要




               copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:内部イテレータとの比較

可変箇所が複数ならジェネレータのほうがよっぽどきれい
function	 fib(){                                 //	 使い方
	 	 list($x,	 $y)	 =                             foreach(fib()	 as	 $x){
	 	 	 	 [0,	 1];                                 	 	 //	 終了条件
	 	 while	 (TRUE)	 {                             	 	 if	 ($x	 >=	 100)
	 	 	 	 yield	 $x;                               	 	 	 	 break;
	 	 	 	 list($x,	 $y)	 =                         	 	 //	 ボディ部
	 	 	 	 	 	 [$y,	 $x+$y];                        	 	 echo	 $x,	 "n";
	 	 }                                            };
}




                  copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:内部イテレータとの比較
Rubyでは、1つの無名関数 (ブロック) で「終了条件」と
「ボディ部」の両方を指定できる。

def	 fib()                                        //	 使い方
	 	 x,	 y	 =	 0,	 1                               fib	 {|x|
	 	 while	 true                                   	 	 //	 終了条件
	 	 	 	 yield	 x                                  	 	 break	 if	 x	 >=	 100
	 	 	 	 x,	 y	 =	 y,	 x+y                         	 	 //	 ボディ部
	 	 end                                           	 	 puts	 x
end                                               }




                   copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:「継続 (Continuation)」との比較

◆ 継続のほうができることが広い、
  ジェネレータはそのサブセット
                        ※
◆ 継続はcall stackを丸ごとコピーする ので重い、
  ジェネレータはstack flame1つだけなので軽い
◆ 継続は理解するのがすーーーっごく難しい、
  ジェネレータはわかりやすいし使いやすい




※処理系により実装方法は異なる場合がある

              copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:ベンチマーク
                                                        Code: https://gist.github.com/3710544

                                                                                 配列に詰め込む
          Loop                                                                   のは高コスト

          Array

    Generator

 Inner Iterator

       Closure
                  0                    0.2                       0.4                   0.6   0.8
                                                                                             (sec)



PHP: 5.5-addGeneratorSupport
OS: MacOSX
CPU: Core2DUO 2GHz
                               copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:ベンチマーク
                                                        Code: https://gist.github.com/3710569



          Loop                                      ジェネレータは
                                                    十分に低コスト
    Generator

G + explode()

G + explode()
   + array()
                  0                    0.5                         1                   1.5    2
                                                                                             (sec)

                                              ループ内処理 (explode()やarray())
                                              のほうがよっぽど高コスト
PHP: 5.5-addGeneratorSupport
OS: MacOSX
CPU: Core2DUO 2GHz
                               copyright(c) 2012 kuwata-lab.com all rights reserved.
おまけ:参考文献

◆ What PHP 5.5 might look like
   http://nikic.github.com/2012/07/10/What-PHP-5-5-might-look-like.html

◆ Request for Comments: Generators
   https://wiki.php.net/rfc/generators

◆ Scheme/継続の種類と利用例
   http://ja.wikibooks.org/wiki/Scheme/継続の種類と利用例

◆ Vallog - 継続の実装方針
   http://valvallow.blogspot.jp/2011/01/blog-post_11.html

◆ Twisted Intro: 「コールバック」ではない方法
  http://skitazaki.appspot.com/translation/twisted-intro-ja/p17.html

◆ 境界を越える: 継続とWeb開発、そしてJavaプログラミング
  http://www.ibm.com/developerworks/jp/java/library/j-cb03216/index.html


                          copyright(c) 2012 kuwata-lab.com all rights reserved.
おしまい

More Related Content

What's hot

DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
kwatch
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
Takuto Wada
 
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
parrotstudio
 
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
onozaty
 
ふつうの受託開発チームのつくりかた
ふつうの受託開発チームのつくりかたふつうの受託開発チームのつくりかた
ふつうの受託開発チームのつくりかた
Yoshitaka Kawashima
 
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
Mikiya Okuno
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
yoku0825
 
徳丸本に載っていないWebアプリケーションセキュリティ
徳丸本に載っていないWebアプリケーションセキュリティ徳丸本に載っていないWebアプリケーションセキュリティ
徳丸本に載っていないWebアプリケーションセキュリティ
Hiroshi Tokumaru
 
CloudFront経由でのCORS利用
CloudFront経由でのCORS利用CloudFront経由でのCORS利用
CloudFront経由でのCORS利用
Yuta Imai
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
Takuto Wada
 
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
慎一 古賀
 
PSR-1 と PSR-2 を 5分でざっくり理解する
PSR-1 と PSR-2 を5分でざっくり理解するPSR-1 と PSR-2 を5分でざっくり理解する
PSR-1 と PSR-2 を 5分でざっくり理解する
Wataru Terada
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南
Mikiya Okuno
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
Y Watanabe
 
ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計
Yoshinori Matsunobu
 
SPAのルーティングの話
SPAのルーティングの話SPAのルーティングの話
SPAのルーティングの話
ushiboy
 
Flutter移行の苦労と、乗り越えた先に得られたもの
Flutter移行の苦労と、乗り越えた先に得られたものFlutter移行の苦労と、乗り越えた先に得られたもの
Flutter移行の苦労と、乗り越えた先に得られたもの
Recruit Lifestyle Co., Ltd.
 
Laravelの検索機能の実装方法
Laravelの検索機能の実装方法Laravelの検索機能の実装方法
Laravelの検索機能の実装方法
yoshitaro yoyo
 
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
Daichi Koike
 
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
土岐 孝平
 

What's hot (20)

DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
「再代入なんて、あるわけない」 ~ふつうのプログラマが関数型言語を知るべき理由~ (Gunma.web #5 2011/05/14)
 
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
 
ふつうの受託開発チームのつくりかた
ふつうの受託開発チームのつくりかたふつうの受託開発チームのつくりかた
ふつうの受託開発チームのつくりかた
 
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
なぜ、いま リレーショナルモデルなのか(理論から学ぶデータベース実践入門読書会スペシャル)
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
 
徳丸本に載っていないWebアプリケーションセキュリティ
徳丸本に載っていないWebアプリケーションセキュリティ徳丸本に載っていないWebアプリケーションセキュリティ
徳丸本に載っていないWebアプリケーションセキュリティ
 
CloudFront経由でのCORS利用
CloudFront経由でのCORS利用CloudFront経由でのCORS利用
CloudFront経由でのCORS利用
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
ちゃんとした C# プログラムを書けるようになる実践的な方法~ Visual Studio を使った 高品質・低コスト・保守性の高い開発
 
PSR-1 と PSR-2 を 5分でざっくり理解する
PSR-1 と PSR-2 を5分でざっくり理解するPSR-1 と PSR-2 を5分でざっくり理解する
PSR-1 と PSR-2 を 5分でざっくり理解する
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
 
ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計ソーシャルゲームのためのデータベース設計
ソーシャルゲームのためのデータベース設計
 
SPAのルーティングの話
SPAのルーティングの話SPAのルーティングの話
SPAのルーティングの話
 
Flutter移行の苦労と、乗り越えた先に得られたもの
Flutter移行の苦労と、乗り越えた先に得られたものFlutter移行の苦労と、乗り越えた先に得られたもの
Flutter移行の苦労と、乗り越えた先に得られたもの
 
Laravelの検索機能の実装方法
Laravelの検索機能の実装方法Laravelの検索機能の実装方法
Laravelの検索機能の実装方法
 
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
 
怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション怖くないSpring Bootのオートコンフィグレーション
怖くないSpring Bootのオートコンフィグレーション
 

Similar to PHP5.5新機能「ジェネレータ」初心者入門

ちょっと詳しくJavaScript 第4回【スコープとクロージャ】
ちょっと詳しくJavaScript 第4回【スコープとクロージャ】ちょっと詳しくJavaScript 第4回【スコープとクロージャ】
ちょっと詳しくJavaScript 第4回【スコープとクロージャ】株式会社ランチェスター
 
Hack/HHVM 入門
Hack/HHVM 入門Hack/HHVM 入門
Hack/HHVM 入門
y-uti
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
Masao Kato
 
test
testtest
Perl 非同期プログラミング
Perl 非同期プログラミングPerl 非同期プログラミング
Perl 非同期プログラミングlestrrat
 
最近の PHP の話
最近の PHP の話最近の PHP の話
最近の PHP の話
y-uti
 
PHP7を魔改造した話
PHP7を魔改造した話PHP7を魔改造した話
PHP7を魔改造した話
Moriyoshi Koizumi
 
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
Akabane Hiroyuki
 
Grails-1.1を斬る!~Grails-1.1からのチーム開発~ in Tokyo
Grails-1.1を斬る!~Grails-1.1からのチーム開発~ in TokyoGrails-1.1を斬る!~Grails-1.1からのチーム開発~ in Tokyo
Grails-1.1を斬る!~Grails-1.1からのチーム開発~ in Tokyo
Tsuyoshi Yamamoto
 
PHPの今とこれから2014
PHPの今とこれから2014PHPの今とこれから2014
PHPの今とこれから2014
Rui Hirokawa
 
今日からはじめるGPars
今日からはじめるGPars今日からはじめるGPars
今日からはじめるGPars
fumokmm
 
PHPBLT#6 PHPの未来に入るかもしれない機能の紹介
PHPBLT#6 PHPの未来に入るかもしれない機能の紹介PHPBLT#6 PHPの未来に入るかもしれない機能の紹介
PHPBLT#6 PHPの未来に入るかもしれない機能の紹介
sters
 
Node.js - JavaScript Thread Programming
Node.js - JavaScript Thread ProgrammingNode.js - JavaScript Thread Programming
Node.js - JavaScript Thread Programmingtakesako
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-Kazunari Hara
 
Try Jetpack
Try JetpackTry Jetpack
Try Jetpack
Hideaki Miyake
 
PHPの今とこれから2019
PHPの今とこれから2019PHPの今とこれから2019
PHPの今とこれから2019
Rui Hirokawa
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」yoshiaki iwanaga
 

Similar to PHP5.5新機能「ジェネレータ」初心者入門 (20)

ちょっと詳しくJavaScript 第4回【スコープとクロージャ】
ちょっと詳しくJavaScript 第4回【スコープとクロージャ】ちょっと詳しくJavaScript 第4回【スコープとクロージャ】
ちょっと詳しくJavaScript 第4回【スコープとクロージャ】
 
Hack/HHVM 入門
Hack/HHVM 入門Hack/HHVM 入門
Hack/HHVM 入門
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
test
testtest
test
 
Perl 非同期プログラミング
Perl 非同期プログラミングPerl 非同期プログラミング
Perl 非同期プログラミング
 
最近の PHP の話
最近の PHP の話最近の PHP の話
最近の PHP の話
 
0x300
0x3000x300
0x300
 
PHP7を魔改造した話
PHP7を魔改造した話PHP7を魔改造した話
PHP7を魔改造した話
 
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~
 
Grails-1.1を斬る!~Grails-1.1からのチーム開発~ in Tokyo
Grails-1.1を斬る!~Grails-1.1からのチーム開発~ in TokyoGrails-1.1を斬る!~Grails-1.1からのチーム開発~ in Tokyo
Grails-1.1を斬る!~Grails-1.1からのチーム開発~ in Tokyo
 
PHP language update 201211
PHP language update 201211PHP language update 201211
PHP language update 201211
 
OSC京都2011
OSC京都2011OSC京都2011
OSC京都2011
 
PHPの今とこれから2014
PHPの今とこれから2014PHPの今とこれから2014
PHPの今とこれから2014
 
今日からはじめるGPars
今日からはじめるGPars今日からはじめるGPars
今日からはじめるGPars
 
PHPBLT#6 PHPの未来に入るかもしれない機能の紹介
PHPBLT#6 PHPの未来に入るかもしれない機能の紹介PHPBLT#6 PHPの未来に入るかもしれない機能の紹介
PHPBLT#6 PHPの未来に入るかもしれない機能の紹介
 
Node.js - JavaScript Thread Programming
Node.js - JavaScript Thread ProgrammingNode.js - JavaScript Thread Programming
Node.js - JavaScript Thread Programming
 
速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-速くなければスマフォじゃない - インターンバージョン-
速くなければスマフォじゃない - インターンバージョン-
 
Try Jetpack
Try JetpackTry Jetpack
Try Jetpack
 
PHPの今とこれから2019
PHPの今とこれから2019PHPの今とこれから2019
PHPの今とこれから2019
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」
 

More from kwatch

How to make the fastest Router in Python
How to make the fastest Router in PythonHow to make the fastest Router in Python
How to make the fastest Router in Python
kwatch
 
Migr8.rb チュートリアル
Migr8.rb チュートリアルMigr8.rb チュートリアル
Migr8.rb チュートリアル
kwatch
 
なんでもID
なんでもIDなんでもID
なんでもID
kwatch
 
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
kwatch
 
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
kwatch
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐ
kwatch
 
正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?
kwatch
 
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
kwatch
 
PHPとJavaScriptにおけるオブジェクト指向を比較する
PHPとJavaScriptにおけるオブジェクト指向を比較するPHPとJavaScriptにおけるオブジェクト指向を比較する
PHPとJavaScriptにおけるオブジェクト指向を比較する
kwatch
 
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
kwatch
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
kwatch
 
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
kwatch
 
Pretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/MercurialPretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/Mercurial
kwatch
 
Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -
kwatch
 
文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた
kwatch
 
I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"kwatch
 
Cより速いRubyプログラム
Cより速いRubyプログラムCより速いRubyプログラム
Cより速いRubyプログラム
kwatch
 
Javaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジンJavaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジン
kwatch
 
Underlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R MapperUnderlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R Mapper
kwatch
 
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -kwatch
 

More from kwatch (20)

How to make the fastest Router in Python
How to make the fastest Router in PythonHow to make the fastest Router in Python
How to make the fastest Router in Python
 
Migr8.rb チュートリアル
Migr8.rb チュートリアルMigr8.rb チュートリアル
Migr8.rb チュートリアル
 
なんでもID
なんでもIDなんでもID
なんでもID
 
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
Nippondanji氏に怒られても仕方ない、配列型とJSON型の使い方
 
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
【SQLインジェクション対策】徳丸先生に怒られない、動的SQLの安全な組み立て方
 
O/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐO/Rマッパーによるトラブルを未然に防ぐ
O/Rマッパーによるトラブルを未然に防ぐ
 
正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?正規表現リテラルは本当に必要なのか?
正規表現リテラルは本当に必要なのか?
 
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
【公開終了】Python4PHPer - PHPユーザのためのPython入門 (Python2.5)
 
PHPとJavaScriptにおけるオブジェクト指向を比較する
PHPとJavaScriptにおけるオブジェクト指向を比較するPHPとJavaScriptにおけるオブジェクト指向を比較する
PHPとJavaScriptにおけるオブジェクト指向を比較する
 
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
 
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
What is wrong on Test::More? / Test::Moreが抱える問題点とその解決策
 
Pretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/MercurialPretty Good Branch Strategy for Git/Mercurial
Pretty Good Branch Strategy for Git/Mercurial
 
Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -Oktest - a new style testing library for Python -
Oktest - a new style testing library for Python -
 
文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた文字列結合のベンチマークをいろんな処理系でやってみた
文字列結合のベンチマークをいろんな処理系でやってみた
 
I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"I have something to say about the buzz word "From Java to Ruby"
I have something to say about the buzz word "From Java to Ruby"
 
Cより速いRubyプログラム
Cより速いRubyプログラムCより速いRubyプログラム
Cより速いRubyプログラム
 
Javaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジンJavaより速いLL用テンプレートエンジン
Javaより速いLL用テンプレートエンジン
 
Underlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R MapperUnderlaying Technology of Modern O/R Mapper
Underlaying Technology of Modern O/R Mapper
 
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
How to Make Ruby CGI Script Faster - CGIを高速化する小手先テクニック -
 

Recently uploaded

論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
Toru Tamaki
 
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
harmonylab
 
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
atsushi061452
 
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
NTT DATA Technology & Innovation
 
FIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance Osaka Seminar: Welcome Slides.pdfFIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance
 
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
Matsushita Laboratory
 
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
iPride Co., Ltd.
 
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアルLoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
CRI Japan, Inc.
 
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
Fukuoka Institute of Technology
 
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdfFIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance
 
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
yassun7010
 
FIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance Osaka Seminar: CloudGate.pdfFIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance
 
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdfFIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance
 
CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料
Yuuitirou528 default
 
【AI論文解説】Consistency ModelとRectified Flow
【AI論文解説】Consistency ModelとRectified Flow【AI論文解説】Consistency ModelとRectified Flow
【AI論文解説】Consistency ModelとRectified Flow
Sony - Neural Network Libraries
 
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdfFIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance
 

Recently uploaded (16)

論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
論文紹介:When Visual Prompt Tuning Meets Source-Free Domain Adaptive Semantic Seg...
 
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
【DLゼミ】XFeat: Accelerated Features for Lightweight Image Matching
 
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
論文紹介: Offline Q-Learning on diverse Multi-Task data both scales and generalizes
 
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
YugabyteDB適用に向けた取り組みと隠れた魅力 (DSS Asia 2024 発表資料)
 
FIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance Osaka Seminar: Welcome Slides.pdfFIDO Alliance Osaka Seminar: Welcome Slides.pdf
FIDO Alliance Osaka Seminar: Welcome Slides.pdf
 
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
TaketoFujikawa_物語のコンセプトに基づく情報アクセス手法の基礎検討_JSAI2024
 
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
MPAなWebフレームワーク、Astroの紹介 (その2) 2024/05/24の勉強会で発表されたものです。
 
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアルLoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
LoRaWAN 4チャンネル電流センサー・コンバーター CS01-LB 日本語マニュアル
 
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
単腕マニピュレータによる 複数物体の同時組み立ての 基礎的考察 / Basic Approach to Robotic Assembly of Multi...
 
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdfFIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
FIDO Alliance Osaka Seminar: LY-DOCOMO-KDDI-Mercari Panel.pdf
 
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
2024年度_サイバーエージェント_新卒研修「データベースの歴史」.pptx
 
FIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance Osaka Seminar: CloudGate.pdfFIDO Alliance Osaka Seminar: CloudGate.pdf
FIDO Alliance Osaka Seminar: CloudGate.pdf
 
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdfFIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
FIDO Alliance Osaka Seminar: PlayStation Passkey Deployment Case Study.pdf
 
CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料CS集会#13_なるほどわからん通信技術 発表資料
CS集会#13_なるほどわからん通信技術 発表資料
 
【AI論文解説】Consistency ModelとRectified Flow
【AI論文解説】Consistency ModelとRectified Flow【AI論文解説】Consistency ModelとRectified Flow
【AI論文解説】Consistency ModelとRectified Flow
 
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdfFIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
FIDO Alliance Osaka Seminar: NEC & Yubico Panel.pdf
 

PHP5.5新機能「ジェネレータ」初心者入門

  • 1. PHPカンファレンス2012 PHP5.5新機能 かもしれない Generator 初心者入門 makoto kuwata <kwa@kuwata-lab.com> http://www.kuwata-lab.com/ 2012-09-15 (Sat) copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 2. 本発表について 【目的】 • PHP5.5の新機能かもしれない「ジェネレータ」を、 「なんだか凄そうだ」と思ってもらう。 【内容】 • ジェネレータって何? • どううれしいの? • どんなことに使えるの? 【注意】 • 内容は2012-09-15時点での情報に基づく。 今後、仕様変更があり得るので注意。 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 3. ジェネレータって何? What is Generator? copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 4. まとめ ◆ ジェネレータ セーブ機能 ◆ ジェネレータ関数 ゲームシナリオ ◆ ジェネレータオブジェクト 冒険の書 (セーブデータ) ◆ yield文 宿屋(セーブポイント) copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 5. 通常の関数 1: function func() { 2: $i = 0; 1, 2, 3回目 (0が返される) 3: return $i; 4: $i++; 5: return $i; 6: $i++; 7: return $i; 8: } 毎回先頭から実行され、また return文より後ろは実行されない copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 6. ジェネレータ (Generator) 関数 1: function gfunc() { 2: $i = 0; 1回目 (0が返される) 3: yield $i; 4: $i++; 5: yield $i; 2回目 (1が返される) 6: $i++; 7: yield $i; 3回目 (2が返される) 8: } 前回の終了位置から再開 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 7. 使い方 ジェネレータオブジェクトを生成 (通常の関数と使い方が違うことに注意!) 1: $g = gfunc(); 2: foreach ($g as $x) { 3: var_dump($x); 4: } foreach文とともに使用 (イテレータとして振る舞う) 実行例 int(0) int(1) int(2) copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 8. 実行順序:ループ1回目 メインプログラム ジェネレータ関数 1 $g = gfunc(); function gfunc(){ 2 foreach($g as $x){ $i = 0; 3 var_dump($x); yield $i; 4 5 } $i++; echo "donen"; yield $i; $i++; return $i; } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 9. 実行順序:ループ2回目 メインプログラム ジェネレータ関数 $g = gfunc(); function gfunc(){ 6 foreach($g as $x){ $i = 0; var_dump($x); yield $i; 9 } $i++; 7 echo "donen"; yield $i; 8 $i++; return $i; } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 10. 実行順序:ループ3回目…は、ない メインプログラム ジェネレータ関数 $g = gfunc(); function gfunc(){ 10foreach($g as $x){ $i = 0; var_dump($x); yield $i; } $i++; yield $i; 13echo "donen"; $i++; 11 return $i; 12 ・ループのたびにyield文まで実行 ・yield文の引数がループ変数に } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 11. サンプル:2つの値を交互に出力 1: function toggle($odd, $even) { 2: while (TRUE) { 3: yield $odd; 4: yield $even; 5: } 6: } 7: 8: // "red" と "blue" を交互に出力 9: foreach (toggle("red", "blue") as $c){ 10: echo $c, "n"; // 無限に出力 11: } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 12. サンプル:フィボナッチ数列 (0, 1, 1, 2, 3, 5, 8, 13,...) 1: function fib() { 2: $x = 0; $y = 1; コツ:ループの終了条件を 3: while (TRUE) { 指定しない (無限ループ) 4: yield $x; 5: list($x, $y) = [$y, $x+$y]; 6: } 7: } 8: 9: // 100未満のフィボナッチ数列を出力 10: foreach (fib() as $x) { 11: if ($x >= 100) break; 12: echo $x, "n"; コツ:終了条件は呼 13: } び出す側で指定する copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 13. まとめ ◆ ジェネレータ セーブ機能 ◆ ジェネレータ関数 ゲームシナリオ ◆ ジェネレータオブジェクト 冒険の書 (セーブデータ) ◆ yield文 宿屋(セーブポイント) copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 14. どううれしいの? Why Generator is so useful? copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 15. Before: ファイルを1行ずつ処理する 1: // 行番号つきで表示 2: $f = fopen($filename, 'r'); 3: if ($f === FALSE) throw ....; 4: $line = fgets($f); 5: while ($line !== FALSE) { 6: ++$i; 7: echo $i, ": ", $line; 8: $line = fgets($f); 9: } 10: fclose($f); 11: copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 16. Before: ファイルを1行ずつ処理する 1: // パターンで絞り込む 2: $f = fopen($filename, 'r'); 3: if ($f === FALSE) throw ....; 4: $line = fgets($f); 5: while ($line !== FALSE) { 6: if (preg_match('/@/', $line)) 7: echo $line; 8: $line = fgets($f); 9: } 10: fclose($f); 11: copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 17. Before: ファイルを1行ずつ処理する 1: // タブ文字でフィールドに分解 2: $f = fopen($filename, 'r'); 3: if ($f === FALSE) throw ....; 4: $line = fgets($f); 5: while ($line !== FALSE) { 6: $arr = explode("t", $line); 7: echo $arr[1], "n"; 8: $line = fgets($f); 9: } 汎用性の高いコードの中に 10: fclose($f); 汎用性の低いコードが混在 11: copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 18. After: ジェネレータ関数 汎用性の高い箇所を関数に抽出 1: function each_line($filename) { 2: $f = fopen($filename, 'r'); 3: if ($f === FALSE) throw ....; 4: $line = fgets($f); 5: while ($line !== FALSE) { 6: $arr = explode("t", $line); yield $line; 7: echo $arr[1]; 汎用性の低い箇所を yield 文に 8: $line = fgets($f); 9: } 10: fclose($f); 11: } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 19. After: メインプログラム 1: // ジェネレータオブジェクトを生成 2: $g = each_line($filename); 3: // メインループ 4: foreach ($g as $line) { 5: // 汎用性の低い処理 6: $arr = explode("t", $line); 7: echo $arr[1], "n"; 8: } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 20. ジェネレータの利点 ◆ ループ処理から、汎用性の高い箇所だけを切り 出せる(再利用性の向上) ◆ ◆ ◆ copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 21. もっとジェネレータ関数 ジェネレータオブジェクトを受け取り、新し い別のジェネレータオブジェクトを生成する 1: // ジェネレータオブジェクトを作成 受け取る function each_fields($g) { 2: $g = each_line($filename); 3: // ループ 配列やイテレータでも可 4: foreach ($g as $line) { 5: $arr = explode("t", $line); 6: echo $arr[1]; yield $arr; 7: } 8: } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 22. ジェネレータを「重ねる」 1: // ジェネレータオブジェクトを生成 2: $g = each_line($filename); 3: $g = each_fields($g); ジェネレータから 4: // メインループ 別のジェネレータ 5: foreach ($g as $line) { を生成 $arr 6: $arr = explode("n", $line);                     7: echo $arr[1], "n"; 8: } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 23. 1つの大きなループ vs. 複数の小さなループ ジェネレータ使用前 ジェネレータ使用後 $f = fopen($filename, 'r'); while ($line !== FALSE) { $line = fgets($f); yield $line; while ($line !== FALSE) { } $arr = explode("n",$line); echo $arr[1]; foreach ($g as $line) { $line = fgets($f); yield $arr; } } fclose($f); $g = each_line($filename); $g = each_fields($g); foreach ($g as $arr) { echo $arr[1], "n"; } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 24. ジェネレータの利点 ◆ ループ処理から、汎用性の高い箇所だけを切り 出せる(再利用性の向上) ◆ ひとつの大きなループを、複数の小さなループ に分解できる(ループの簡素化とPipeline化) ◆ ◆ copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 25. 従来方法との比較:配列にすべて格納する 1: function each_line($filename) { 2: $f = fopen($filename, 'r'); 3: $lines = array(); メモリを大量に消費 4: $line = fgets($f);(巨大データだと落ちる) 5: while ($line !== FALSE) { 6: $lines[] = $line; 7: $line = fgets($f); 8: } 9: fclose($f); すべてを読み込まないと 10: return $lines; 結果が返ってこない 11: } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 26. 従来方法との比較:ジェネレータ 1: function each_line($filename) { 2: $f = fopen($filename, 'r'); 3: 1度に1行しか読み込まない 4: $line = fgets($f); (巨大なデータでも落ちない) 5: while ($line !== FALSE) { 6: yield $line; 7: $line = fgets($f); 8: } 読み込んだはしから値を返す 9: fclose($f); (ストリーム処理に最適) 10 11: } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 27. リダイレクト v.s. パイプライン すべてを配列に格納する ≒「リダイレクト」 ・巨大な中間ファイルが必要 ・最後まで処理しないと何も出力されない bash% command1 < input > tmp1 bash% command2 < tmp1 > tmp2 bash% command3 < tmp2 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 28. リダイレクト v.s. パイプライン ジェネレータを連結する ≒ 「パイプ」 ・巨大な中間ファイルがいらない ・読み込んだはしから出力される bash% cat input | command1 | command2 | command3 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 29. ジェネレータの利点 ◆ ループ処理から、汎用性の高い箇所だけを切り 出せる(再利用性の向上) ◆ ひとつの大きなループを、複数の小さなループ に分解できる(ループの簡素化とPipeline化) ◆ メモリ消費量が少ない (巨大なデータを扱ってもプロセスが落ちない) ◆ データを読んだはしから処理できる (ストリームデータも処理可能) copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 30. どんな使い道があるの? Advanced Generator copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 31. ジェネレータとインタラクション $g->send() … 次のyield文まで実行する メインプログラム ジェネレータ関数 からメインプログ ラムに値を返す foreach(){} yield $value $g->send($arg) メインプログラム ジェネレータ関数 からジェネレータ 関数に値を渡せる copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 32. ジェネレータとインタラクション 双方向への値の受け渡しが可能に メインプログラム $value = $g->send("arg"); send()の引数が yield文の値に yield文の引数が send()の戻り値に ジェネレータ関数 $arg = (yield "value"); copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 33. ジェネレータとインタラクション メインプログラム ジェネレータ関数 1$g = gfunc(); function gfunc(){ $ret = $g->send(1); $arg = yield; 2 3 $ret = $g->send(2); while (条件式) { 4 $ret = $g->send(3); $ret = ...; 5 $arg = (yield $ret); 6 var_dump($arg); } } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 34. ジェネレータとインタラクション メインプログラム ジェネレータ関数 $g = gfunc(); function gfunc(){ $ret = $g->send(1); $arg = yield; $ret = $g->send(2); while (条件式) { 9 7 $ret = $g->send(3); $ret = ...; 10 $arg = (yield $ret); 11 var_dump($arg); 8 } } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 35. ジェネレータとインタラクション メインプログラム ジェネレータ関数 $g = gfunc(); function gfunc(){ $ret = $g->send(1); $arg = yield; $ret = $g->send(2); while (条件式) { 14 $ret = $g->send(3); $ret = ...; 15 12 $arg = (yield $ret); 16 var_dump($arg); 13 } } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 36. サンプル:数字あてゲーム 最初のsend()の引数値を変数に代入 1: function guess_quiz($num) { 2: $ans = yield; 3: while ($num != $ans) { 4: if ($ans > $num) 5: $ans = (yield "too large"); 6: else 7: $ans = (yield "too small"); 8: } 値を返し、かつsend() 9: } の引数値を変数に代入 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 37. サンプル:数字あてゲーム 1: $g = guess_quiz(mt_rand(1, 100)); 2: do { 3: echo "guess number (1-100): "; 4: $ans = fgets(STDIN, 128); 5: if ($ans === false) break; 6: $hint = $g->send($ans); 7: echo $hint ? $hint."n" 8: : "Correct!n"; 9: } while ($hint); 値を送信し、かつ 次のyield文まで実行 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 38. ジェネレータとマルチスレッド Process 高機能 機能は限られるが Native Thread メモリ消費量が 極めて少ない (=大量生成可能) Green Thread Generator リソース消費量 : OSの機能として実現 : 言語やライブラリで実現 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 39. ジェネレータと非同期処理 ネストしたコールバック関数 処理1(function($data) { 処理2(function($data) { 処理3(function($data) { .... }); 読みにくい、 }); 書きにくい、 }); わかりにくい copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 40. ジェネレータと非同期処理 コールバック関数を数珠つなぎ $d = new Deferred(); $d->next(function($data) { ..処理1..; })->next(function($data) { ..処理2..; })->next(function($data) { ..処理3..; 記述量が多い、 書き方が不自然 }); copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 41. ジェネレータと非同期処理 ジェネレータ function doSomething() { $data = yield; ...処理1...; $data = yield; ...処理2...; $data = yield; ...処理3...; 自然な書き方で わかりやすい! } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 42. ジェネレータとページ遷移 1: $response = フォームを表示(); 2: $request = (yield $response); 3: $response = プレビューを表示($request); 4: $request = (yield $response); 5: データベースに登録($request); 複数ページにまたがる遷移を 非同期処理と同じように記述 ※ (詳しくは「継続ベース フレームワーク」でggr) ※ Apache だとリクエストごとにすべてをリセットするので、実現できない。 PHP のビルトイン Web サーバのようなパーシステントプロセスのサーバを使って、 リクエストを超えてジェネレータオブジェクトを保持できるような仕組みが必要。 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 43. 落とし穴:breakされた場合 1: function each_line($filename) { 2: $f = fopen($filename, 'r'); 3: $line = fgets($f); 4: while ($line !== FALSE) { 5: yield $line; 6: $line = fgets($f); 7: } 8: fclose($f); 9: } 呼び出し側でbreakされると 終了処理が行われない!※ (しかもPHPにはfinallyがないorz) ※ SPLFileObject も同じ問題を抱えているが、デストラクタで fclose() している。 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 44. 落とし穴:リファクタリング 奇数番目をyieldしてから、偶数番目をyieldする 1: function stepping($arr) { 2: $n = count($arr); 3: for ($i=0; $i<$n; $i+=2) 4: yield $arr[$i]; 5: for ($i=1; $i<$n; $i+=2) 6: yield $arr[$i]; 7: } DRYじゃない!関数化しよう! copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 45. 落とし穴:リファクタリング DRYになった、けど動かない! 1: function _sub($arr, $i, $n) { 2: for (; $i<$n; $i+=2) 3: yield $arr[$i]; 4: } 5: function stepping($arr) { 6: $n = count($arr); 7: _sub($arr, 0, $n); 8: _sub($arr, 1, $n); 9: } ジェネレータ関数を呼び出して いるがforeach文を使ってない copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 46. 落とし穴:リファクタリング 動くようになった…けどなんか腑に落ちない 1: function _sub($arr, $i, $n) { 2: for (; $i<$n; $i+=2) 3: yield $arr[$i]; 4: } 5: function stepping($arr) { 6: $n = count($arr); 7: foreach (_sub($arr, 0, $n) as $x) 8: yield $x; 9: foreach (_sub($arr, 1, $n) as $x) 10: yield $x; 11: } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 47. まとめ ◆ $->send()を使うと、双方向での値の受け渡し が可能 ◆ マルチスレッドよりも低機能だが軽量 ◆ 非同期処理が自然な形で記述できる ◆ 落とし穴もあるよ! copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 49. おまけ More Things copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 50. おまけ:PHP5.5 コンパイル方法 $ git clone https://github.com/nikic/php-src.git $ cd php-src/ $ git checkout -b addGeneratorSupport origin/addGeneratorSupport $ ./buildconf $ apxs2=/usr/local/apache2/bin/apxs $ ./configure --with-apxs2=$apxs2 $ nice -20 time make $ sapi/cli/php myexample.php copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 51. おまけ:インデックスつきyield 1: function gfunc() { // 実行結果 2: yield 'a'; 0 => a 3: yield 'b'; 1 => b 4: yield 99=>'c'; 99 => c 5: } 6: 7: $g = gfunc(); 8: foreach ($g as $k=>$v) { 9: echo "$k => $v n"; 10: } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 52. おまけ:参照渡しでのyield 1: function &gfunc(&$arr) { // 実行結果 2: foreach ($arr as &$x){ array(3) { 3: yield $x; [0]=> 4: } int(11) 5: } [1]=> 6: int(21) 7: $arr = [10, 20, 30]; [2]=> 8: $g = gfunc($arr); &int(31) 9: foreach ($g as &$x) } 10: $x += 1; 11: var_dump($arr); copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 53. おまけ:クロージャとの比較 それ、クロージャでもできるよ! function fib() { // 使い方 list($x, $y) = $closure = fib(); [0, 1]; $x = $closure(); return function() while ($x < 100) { use ($x, $y) { echo $x, "n"; $tmp = $x; $x = $closure(); list($x, $y) = } [$y, $x+$y]; return $tmp; }; } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 54. おまけ:クロージャとの比較 クロージャ版 ジェネレータ版 function fib() { function fib() { list($x, $y) = list($x, $y) = [0, 1]; [0, 1]; return function() while (TRUE) { use ($x, $y) { yield $x; $tmp = $x; list($x, $y) = list($x, $y) = [$y, $x+$y]; [$y, $x+$y]; } return $tmp; } }; ・毎回先頭から実行される ・前回の終了場所から自動 } 制約 的に再開 (より自然な記述) ・すべてをreturnの前に書 ・yieldの後ろにも処理が書 かなければならない制約 ける (より自然な記述) copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 55. おまけ:内部イテレータとの比較 それ、内部イテレータでもできるよ! function fib($fn) { // 使い方 list($x, $y) = fib(function($x) { [0, 1]; echo $x, "n"; while ($x < 100) { }); $fn($x); list($x, $y) = [$y, $x+$y]; } } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 56. おまけ:内部イテレータとの比較 ループの終了条件も指定したい場合は、非常にブサイク function fib($c,$fn){ // 使い方 終了条件と… list($x, $y) = fib( [0, 1]; function($x) { while ($c($x)) { return $x < 100; $fn($x); }, list($x, $y) = function($x) { [$y, $x+$y]; echo $x, "n"; } } } ); ボディ部の両方が必要 copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 57. おまけ:内部イテレータとの比較 可変箇所が複数ならジェネレータのほうがよっぽどきれい function fib(){ // 使い方 list($x, $y) = foreach(fib() as $x){ [0, 1]; // 終了条件 while (TRUE) { if ($x >= 100) yield $x; break; list($x, $y) = // ボディ部 [$y, $x+$y]; echo $x, "n"; } }; } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 58. おまけ:内部イテレータとの比較 Rubyでは、1つの無名関数 (ブロック) で「終了条件」と 「ボディ部」の両方を指定できる。 def fib() // 使い方 x, y = 0, 1 fib {|x| while true // 終了条件 yield x break if x >= 100 x, y = y, x+y // ボディ部 end puts x end } copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 59. おまけ:「継続 (Continuation)」との比較 ◆ 継続のほうができることが広い、 ジェネレータはそのサブセット ※ ◆ 継続はcall stackを丸ごとコピーする ので重い、 ジェネレータはstack flame1つだけなので軽い ◆ 継続は理解するのがすーーーっごく難しい、 ジェネレータはわかりやすいし使いやすい ※処理系により実装方法は異なる場合がある copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 60. おまけ:ベンチマーク Code: https://gist.github.com/3710544 配列に詰め込む Loop のは高コスト Array Generator Inner Iterator Closure 0 0.2 0.4 0.6 0.8 (sec) PHP: 5.5-addGeneratorSupport OS: MacOSX CPU: Core2DUO 2GHz copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 61. おまけ:ベンチマーク Code: https://gist.github.com/3710569 Loop ジェネレータは 十分に低コスト Generator G + explode() G + explode() + array() 0 0.5 1 1.5 2 (sec) ループ内処理 (explode()やarray()) のほうがよっぽど高コスト PHP: 5.5-addGeneratorSupport OS: MacOSX CPU: Core2DUO 2GHz copyright(c) 2012 kuwata-lab.com all rights reserved.
  • 62. おまけ:参考文献 ◆ What PHP 5.5 might look like http://nikic.github.com/2012/07/10/What-PHP-5-5-might-look-like.html ◆ Request for Comments: Generators https://wiki.php.net/rfc/generators ◆ Scheme/継続の種類と利用例 http://ja.wikibooks.org/wiki/Scheme/継続の種類と利用例 ◆ Vallog - 継続の実装方針 http://valvallow.blogspot.jp/2011/01/blog-post_11.html ◆ Twisted Intro: 「コールバック」ではない方法 http://skitazaki.appspot.com/translation/twisted-intro-ja/p17.html ◆ 境界を越える: 継続とWeb開発、そしてJavaプログラミング http://www.ibm.com/developerworks/jp/java/library/j-cb03216/index.html copyright(c) 2012 kuwata-lab.com all rights reserved.