Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Good Parts of PHP and the UNIX Philosophy

3,079 views

Published on

PHP の良いパーツとして stream, Iterator, Generator を紹介します。 これらはファイルやコレクションに対して統一的な操作を提供し、小さな関数を組み合わせた関数型プログラミング的なアプローチの助けになります。 また、そういったテクニックの根底にある、UNIX 哲学についても紹介します。

Published in: Engineering
  • Be the first to comment

Good Parts of PHP and the UNIX Philosophy

  1. 1. Good Parts of PHP and The UNIX Philosophy @ PHP カンファレンス 2014 フィードバックはこちら https://joind.in/talk/view/12040
  2. 2. 自己紹介 • Twitter: @yuya_takeyama • GitHub: yuya-takeyama • PHP / Ruby / Golang
  3. 3. Good Parts •Stream •Iterator •Generator
  4. 4. The UNIX Philosophy
  5. 5. これがUNIXの哲学である。 一つのことを行い、またそれをうまくやるプログラムを書け。 協調して動くプログラムを書け。 標準入出力(テキスト・ストリーム)を扱うプログラムを書け。 標準入出力は普遍的インターフェースなのだ。 — M. D. マキルロイ、UNIXの四半世紀 http://ja.wikipedia.org/wiki/UNIX哲学
  6. 6. ひとつのこと をうまくやれ
  7. 7. 全てのプログラ ムをフィルタに
  8. 8. 部分の総和は全 体よりも大きい
  9. 9. 対象者 • ライブラリを書く人
  10. 10. 効用 • 再利用性の高いコード • 組み合わせられるコード • が書けるようになる
  11. 11. 話さないこと • 並列・並行プログラミング
  12. 12. Stream
  13. 13. $fp = fopen($file, 'r');
  14. 14. Stream • データの流れ • データを読み込めるかも • データを書き込めるかも
  15. 15. <?php $source = fopen('./input.txt', 'r'); $dest = fopen('./output.txt', 'w'); if ($source && $dest) { while (($buf = fgets($source, 8192)) !== false) { if (fputs($dest, $buf) === false) { throw new RuntimeException('write error'); } } if (feof($source) === false) { throw new RuntimeException('read error'); } fclose($source); fclose($dest); } ファイルの読み書き
  16. 16. <?php $source = fopen('./input.txt', 'r'); $dest = fopen('./output.txt', 'w'); if ($source && $dest) { while (($buf = fgets($source, 8192)) !== false) { if (fputs($dest, $buf) === false) { throw new RuntimeException('write error'); } } if (feof($source) === false) { throw new RuntimeException('read error'); } fclose($source); fclose($dest); } ファイルの読み書きわりと むずい
  17. 17. 何が便利?
  18. 18. Stream wrapper
  19. 19. Stream wrapper • あらゆるものをfopen()可能に! • 標準インターフェイスとしてのスト リーム (または URL)! • ユーザによる実装も可能
  20. 20. $fp = fopen($url);
  21. 21. file_get_contents($url);
  22. 22. Protocols •file://! •http(s)://! •ssh2.sftp://! •etc…
  23. 23. Formats •phar://! •zip://! •rar://! •etc…
  24. 24. Specials •php://stdin! •php://memory! •php://temp! •etc…
  25. 25. Stream wrapper を 実装する 
  26. 26. http://php.net/manual/ja/class.streamwrapper.php
  27. 27. かなり だるい http://php.net/manual/ja/class.streamwrapper.php
  28. 28. 実例
  29. 29. http://docs.aws.amazon.com/aws-sdk-php/guide/latest/feature-s3-stream-wrapper.html
  30. 30. 標準インターフェイス
  31. 31. Stream wrapper x Symfony 
  32. 32. http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome
  33. 33. http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome
  34. 34. ひとつのこと をうまくやれ
  35. 35. 全てのプログラ ムをフィルタに
  36. 36. 部分の総和は全 体よりも大きい
  37. 37. http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome
  38. 38. Stream Wrapper を 利用することで、あら ゆるプロトコル・フォー マットを抽象化して操 作できる
  39. 39. Conclusion of Stream Stream をフィルタする! プログラムを作って! 組み合わせよう
  40. 40. Iterator
  41. 41. Iterator (in General) • 要素の集合 • 各要素に順番にアクセス • リストのような何か
  42. 42. Iterator (in PHP) •Traversable イン ターフェイス! •foreach できる何か
  43. 43. Iterator を 実装する 
  44. 44. http://jp1.php.net/manual/ja/class.iterator.php
  45. 45. RangeIterator をつくる 
  46. 46. RangeIterator • 最初と最後の値を指定する! • その値の幅を表すイテレータ! • 各ステップごとの増加数も指定でき る
  47. 47. http://qiita.com/yuya_takeyama/items/51fb058ed20d3df8209e
  48. 48. $range = new RangeIterator(1, 10); foreach ($range as $n) { echo $n, PHP_EOL; } RangeIterator を使う
  49. 49. 1 ! ! ! RangeIterator を使う
  50. 50. 1 2 ! ! RangeIterator を使う
  51. 51. 1 2 3 ! RangeIterator を使う
  52. 52. 1 2 3 4 RangeIterator を使う
  53. 53. 1 2 3 4 … RangeIterator を使う
  54. 54. Range といえば…. 
  55. 55. http://php.net/range
  56. 56. range() vs Rangeiterator
  57. 57. range() • 要素数文の array を予め生成! • その文メモリを消費
  58. 58. RangeIterator • 各ループ時に次の値を計算して生成! • 要素数が増えてもメモリ量は一定! • 無限リストの生成も可能
  59. 59. $range = new RangeIterator(1, INF); foreach ($range as $n) { echo $n, PHP_EOL; } 無限リストを使う
  60. 60. 無限リストを切り取って使う $range = new RangeIterator(1, INF); $range = new LimitIterator($range, 2, 100); foreach ($range as $n) { echo $n, PHP_EOL; }
  61. 61. 無限リストを切り取って使う 3 ! ! !
  62. 62. 無限リストを切り取って使う 3 4 ! !
  63. 63. 無限リストを切り取って使う 3 4 5 !
  64. 64. 無限リストを切り取って使う 3 4 5 …
  65. 65. イテレータは 組み合わせられる
  66. 66. イテレータが 別のイテレータを 生成する
  67. 67. ひとつのこと をうまくやれ
  68. 68. 全てのプログラ ムをフィルタに
  69. 69. 部分の総和は全 体よりも大きい
  70. 70. $dir = new RecursiveDirectoryIterator( '/Users/yuya/Music/iTunes/iTunes Media/Music/Aphex Twin' ); $dir = new RecursiveIteratorIterator($dir); $dir = new CallbackFilterIterator($dir, function ($node) { return $node->isFile(); }); $dir = new CallbackFilterIterator($dir, function ($file) { return preg_match('/^01/', $file->getFilename()); }); ! foreach ($dir as $file) { echo $file, PHP_EOL; } イテレータでファイル検索
  71. 71. 01 Come To Daddy (Pappy Mix).mp3 ! ! ! イテレータでファイル検索
  72. 72. 01 Come To Daddy (Pappy Mix).mp3 01 4.m4a ! ! イテレータでファイル検索
  73. 73. イテレータでファイル検索 01 Come To Daddy (Pappy Mix).mp3 01 4.m4a 01 minipops 67 [120.2] [source field mix].m4a !
  74. 74. イテレータでファイル検索 01 Come To Daddy (Pappy Mix).mp3 01 4.m4a 01 minipops 67 [120.2] [source field mix].m4a 01 Windowlicker (Original Demo).mp3
  75. 75. イテレータでファイル検索 01 Come To Daddy (Pappy Mix).mp3 01 4.m4a 01 minipops 67 [120.2] [source field mix].m4a 01 Windowlicker (Original Demo).mp3 01 Windowlicker.mp3
  76. 76. イテレータは 組み合わせられる
  77. 77. イテレータが 別のイテレータを 生成する
  78. 78. 標準インターフェイス としての イテレータ
  79. 79. Generator
  80. 80. Generator • PHP5.5~ • Iterator の一種 • ひとつの関数だけで作れる
  81. 81. $gen = function () { yield 1; yield 2; yield 3; }; ! foreach ($gen() as $n) { echo $n, PHP_EOL; } ジェネレータを使ってみる
  82. 82. 1 ! ジェネレータを使ってみる
  83. 83. ジェネレータを使ってみる 1 2
  84. 84. ジェネレータを使ってみる 1 2 3
  85. 85. $range = function ($start, $end, $step = 1) { for ($i = 1; $i <= $end; $i += $step) { yield $i; } }; ! foreach ($range(1, 100) as $n) { echo $n, PHP_EOL; } ジェネレータでrange
  86. 86. http://qiita.com/yuya_takeyama/items/51fb058ed20d3df8209e
  87. 87. $range = function ($start, $end, $step = 1) { for ($i = 1; $i <= $end; $i += $step) { yield $i; } }; ! foreach ($range(1, 100) as $n) { echo $n, PHP_EOL; } ジェネレータでrange
  88. 88. $range = function ($start, $end, $step = 1) { for ($i = 1; $i <= $end; $i += $step) { yield $i; } }; ! foreach ($range(1, 100) as $n) { echo $n, PHP_EOL; } ジェネレータでrange 圧倒的に 簡潔
  89. 89. Functional Programming with Generator
  90. 90. nikic/iter • コレクション操作関数群 • range/map/filter/reduce • イテレータを受けてジェネレー タを返す
  91. 91. ひとつのこと をうまくやれ
  92. 92. 全てのプログラ ムをフィルタに
  93. 93. 部分の総和は全 体よりも大きい
  94. 94. まとめ •Stream と Iterator は PHP の標準インター フェイスである •これらをフィルタする関数を組み合わせる ことで、あらゆるロジックを表現すること ができる •ジェネレータにより柔軟にイテレータを 生成できる
  95. 95. Thank you for Listening

×