100
Good Parts of PHP and The UNIX Philosophy @ PHP カンファレンス 2014 フィードバックはこちら https://joind.in/talk/view/12040

Good Parts of PHP and the UNIX Philosophy

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: Good Parts of PHP and the UNIX Philosophy

Good Parts of PHP and

The UNIX Philosophy@ PHP カンファレンス 2014 フィードバックはこちら

https://joind.in/talk/view/12040

Page 2: Good Parts of PHP and the UNIX Philosophy

自己紹介

• Twitter: @yuya_takeyama

• GitHub: yuya-takeyama

• PHP / Ruby / Golang

Page 3: Good Parts of PHP and the UNIX Philosophy

Good Parts•Stream •Iterator •Generator

Page 4: Good Parts of PHP and the UNIX Philosophy

The UNIX Philosophy

Page 5: Good Parts of PHP and the UNIX Philosophy

これがUNIXの哲学である。 一つのことを行い、またそれをうまくやるプログラムを書け。 協調して動くプログラムを書け。 標準入出力(テキスト・ストリーム)を扱うプログラムを書け。標準入出力は普遍的インターフェースなのだ。

— M. D. マキルロイ、UNIXの四半世紀

http://ja.wikipedia.org/wiki/UNIX哲学

Page 6: Good Parts of PHP and the UNIX Philosophy
Page 7: Good Parts of PHP and the UNIX Philosophy

ひとつのことをうまくやれ

Page 8: Good Parts of PHP and the UNIX Philosophy

全てのプログラムをフィルタに

Page 9: Good Parts of PHP and the UNIX Philosophy

部分の総和は全体よりも大きい

Page 10: Good Parts of PHP and the UNIX Philosophy

対象者•ライブラリを書く人

Page 11: Good Parts of PHP and the UNIX Philosophy

効用•再利用性の高いコード

•組み合わせられるコード

•が書けるようになる

Page 12: Good Parts of PHP and the UNIX Philosophy

話さないこと

•並列・並行プログラミング

Page 13: Good Parts of PHP and the UNIX Philosophy

Stream

Page 14: Good Parts of PHP and the UNIX Philosophy

$fp = fopen($file, 'r');

Page 15: Good Parts of PHP and the UNIX Philosophy

Stream•データの流れ

•データを読み込めるかも

•データを書き込めるかも

Page 16: Good Parts of PHP and the UNIX Philosophy

<?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); }

ファイルの読み書き

Page 17: Good Parts of PHP and the UNIX Philosophy

<?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); }

ファイルの読み書き

わりと むずい

Page 18: Good Parts of PHP and the UNIX Philosophy

何が便利?

Page 19: Good Parts of PHP and the UNIX Philosophy

Stream wrapper

Page 20: Good Parts of PHP and the UNIX Philosophy

Stream wrapper• あらゆるものをfopen()可能に!

• 標準インターフェイスとしてのストリーム (または URL)!

• ユーザによる実装も可能

Page 21: Good Parts of PHP and the UNIX Philosophy

$fp = fopen($url);

Page 22: Good Parts of PHP and the UNIX Philosophy

file_get_contents($url);

Page 23: Good Parts of PHP and the UNIX Philosophy

Protocols•file://!

•http(s)://!

•ssh2.sftp://!

•etc…

Page 24: Good Parts of PHP and the UNIX Philosophy

Formats•phar://!

•zip://!

•rar://!

•etc…

Page 25: Good Parts of PHP and the UNIX Philosophy

Specials•php://stdin!

•php://memory!

•php://temp!

•etc…

Page 26: Good Parts of PHP and the UNIX Philosophy

Stream wrapper を

実装する 

Page 27: Good Parts of PHP and the UNIX Philosophy

http://php.net/manual/ja/class.streamwrapper.php

Page 28: Good Parts of PHP and the UNIX Philosophy

http://php.net/manual/ja/class.streamwrapper.php

かなり だるい

Page 29: Good Parts of PHP and the UNIX Philosophy

実例

Page 30: Good Parts of PHP and the UNIX Philosophy

http://docs.aws.amazon.com/aws-sdk-php/guide/latest/feature-s3-stream-wrapper.html

Page 31: Good Parts of PHP and the UNIX Philosophy

標準インターフェイス

Page 32: Good Parts of PHP and the UNIX Philosophy

Stream wrapper x

Symfony 

Page 33: Good Parts of PHP and the UNIX Philosophy

http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome

Page 34: Good Parts of PHP and the UNIX Philosophy

http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome

Page 35: Good Parts of PHP and the UNIX Philosophy
Page 36: Good Parts of PHP and the UNIX Philosophy

ひとつのことをうまくやれ

Page 37: Good Parts of PHP and the UNIX Philosophy

全てのプログラムをフィルタに

Page 38: Good Parts of PHP and the UNIX Philosophy

部分の総和は全体よりも大きい

Page 39: Good Parts of PHP and the UNIX Philosophy

http://fabien.potencier.org/article/44/php-iterators-and-streams-are-awesome

Page 40: Good Parts of PHP and the UNIX Philosophy

Stream Wrapper を利用することで、あらゆるプロトコル・フォーマットを抽象化して操作できる

Page 41: Good Parts of PHP and the UNIX Philosophy

Stream をフィルタする!プログラムを作って!組み合わせよう

Conclusion of Stream

Page 42: Good Parts of PHP and the UNIX Philosophy

Iterator

Page 43: Good Parts of PHP and the UNIX Philosophy
Page 44: Good Parts of PHP and the UNIX Philosophy

Iterator (in General)•要素の集合

•各要素に順番にアクセス

•リストのような何か

Page 45: Good Parts of PHP and the UNIX Philosophy

Iterator (in PHP)•Traversable インターフェイス!

•foreach できる何か

Page 46: Good Parts of PHP and the UNIX Philosophy

Iterator を

実装する 

Page 47: Good Parts of PHP and the UNIX Philosophy

http://jp1.php.net/manual/ja/class.iterator.php

Page 48: Good Parts of PHP and the UNIX Philosophy

RangeIterator をつくる 

Page 49: Good Parts of PHP and the UNIX Philosophy

RangeIterator•最初と最後の値を指定する!

•その値の幅を表すイテレータ!

•各ステップごとの増加数も指定できる

Page 50: Good Parts of PHP and the UNIX Philosophy

http://qiita.com/yuya_takeyama/items/51fb058ed20d3df8209e

Page 51: Good Parts of PHP and the UNIX Philosophy

$range = new RangeIterator(1, 10); foreach ($range as $n) { echo $n, PHP_EOL; }

RangeIterator を使う

Page 52: Good Parts of PHP and the UNIX Philosophy

1 !

!

!

RangeIterator を使う

Page 53: Good Parts of PHP and the UNIX Philosophy

1 2 !

!

RangeIterator を使う

Page 54: Good Parts of PHP and the UNIX Philosophy

1 2 3 !

RangeIterator を使う

Page 55: Good Parts of PHP and the UNIX Philosophy

1 2 3 4

RangeIterator を使う

Page 56: Good Parts of PHP and the UNIX Philosophy

1 2 3 4 …

RangeIterator を使う

Page 57: Good Parts of PHP and the UNIX Philosophy

Range といえば…. 

Page 58: Good Parts of PHP and the UNIX Philosophy

http://php.net/range

Page 59: Good Parts of PHP and the UNIX Philosophy

range() vs

Rangeiterator

Page 60: Good Parts of PHP and the UNIX Philosophy

range()

•要素数文の array を予め生成!

•その文メモリを消費

Page 61: Good Parts of PHP and the UNIX Philosophy

RangeIterator•各ループ時に次の値を計算して生成!

•要素数が増えてもメモリ量は一定!

•無限リストの生成も可能

Page 62: Good Parts of PHP and the UNIX Philosophy

$range = new RangeIterator(1, INF); foreach ($range as $n) { echo $n, PHP_EOL; }

無限リストを使う

Page 63: Good Parts of PHP and the UNIX Philosophy

$range = new RangeIterator(1, INF); $range = new LimitIterator($range, 2, 100); foreach ($range as $n) { echo $n, PHP_EOL; }

無限リストを切り取って使う

Page 64: Good Parts of PHP and the UNIX Philosophy

3 !

!

!

無限リストを切り取って使う

Page 65: Good Parts of PHP and the UNIX Philosophy

3 4 !

!

無限リストを切り取って使う

Page 66: Good Parts of PHP and the UNIX Philosophy

3 4 5 !

無限リストを切り取って使う

Page 67: Good Parts of PHP and the UNIX Philosophy

3 4 5 …

無限リストを切り取って使う

Page 68: Good Parts of PHP and the UNIX Philosophy

イテレータは

組み合わせられる

Page 69: Good Parts of PHP and the UNIX Philosophy

イテレータが

別のイテレータを

生成する

Page 70: Good Parts of PHP and the UNIX Philosophy
Page 71: Good Parts of PHP and the UNIX Philosophy

ひとつのことをうまくやれ

Page 72: Good Parts of PHP and the UNIX Philosophy

全てのプログラムをフィルタに

Page 73: Good Parts of PHP and the UNIX Philosophy

部分の総和は全体よりも大きい

Page 74: Good Parts of PHP and the UNIX Philosophy

$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; }

イテレータでファイル検索

Page 75: Good Parts of PHP and the UNIX Philosophy

01 Come To Daddy (Pappy Mix).mp3 !

!

!

イテレータでファイル検索

Page 76: Good Parts of PHP and the UNIX Philosophy

01 Come To Daddy (Pappy Mix).mp3 01 4.m4a !

!

イテレータでファイル検索

Page 77: Good Parts of PHP and the UNIX Philosophy

01 Come To Daddy (Pappy Mix).mp3 01 4.m4a 01 minipops 67 [120.2] [source field mix].m4a !

イテレータでファイル検索

Page 78: Good Parts of PHP and the UNIX Philosophy

01 Come To Daddy (Pappy Mix).mp3 01 4.m4a 01 minipops 67 [120.2] [source field mix].m4a 01 Windowlicker (Original Demo).mp3

イテレータでファイル検索

Page 79: Good Parts of PHP and the UNIX Philosophy

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

イテレータでファイル検索

Page 80: Good Parts of PHP and the UNIX Philosophy

イテレータは

組み合わせられる

Page 81: Good Parts of PHP and the UNIX Philosophy

イテレータが

別のイテレータを

生成する

Page 82: Good Parts of PHP and the UNIX Philosophy

標準インターフェイス

としての

イテレータ

Page 83: Good Parts of PHP and the UNIX Philosophy

Generator

Page 84: Good Parts of PHP and the UNIX Philosophy

Generator• PHP5.5~

• Iterator の一種

•ひとつの関数だけで作れる

Page 85: Good Parts of PHP and the UNIX Philosophy

$gen = function () { yield 1; yield 2; yield 3; }; !

foreach ($gen() as $n) { echo $n, PHP_EOL; }

ジェネレータを使ってみる

Page 86: Good Parts of PHP and the UNIX Philosophy

1 !

ジェネレータを使ってみる

Page 87: Good Parts of PHP and the UNIX Philosophy

1 2

ジェネレータを使ってみる

Page 88: Good Parts of PHP and the UNIX Philosophy

1 2 3

ジェネレータを使ってみる

Page 89: Good Parts of PHP and the UNIX Philosophy

$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

Page 90: Good Parts of PHP and the UNIX Philosophy

http://qiita.com/yuya_takeyama/items/51fb058ed20d3df8209e

Page 91: Good Parts of PHP and the UNIX Philosophy

$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

Page 92: Good Parts of PHP and the UNIX Philosophy

$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

圧倒的に 簡潔

Page 93: Good Parts of PHP and the UNIX Philosophy

Functional Programming

with Generator

Page 94: Good Parts of PHP and the UNIX Philosophy

nikic/iter

•コレクション操作関数群

• range/map/filter/reduce •イテレータを受けてジェネレータを返す

Page 95: Good Parts of PHP and the UNIX Philosophy
Page 96: Good Parts of PHP and the UNIX Philosophy

ひとつのことをうまくやれ

Page 97: Good Parts of PHP and the UNIX Philosophy

全てのプログラムをフィルタに

Page 98: Good Parts of PHP and the UNIX Philosophy

部分の総和は全体よりも大きい

Page 99: Good Parts of PHP and the UNIX Philosophy

まとめ•Stream と Iterator は PHP の標準インターフェイスである

•これらをフィルタする関数を組み合わせることで、あらゆるロジックを表現することができる

•ジェネレータにより柔軟にイテレータを生成できる

Page 100: Good Parts of PHP and the UNIX Philosophy

Thank you for

Listening