PHPでFollowというイテレータを書いた
こんなん。
<?php class Follow implements Iterator { protected $first, $fn, $key = 0, $current_value, $is_valid = true; function __construct($first, $fn) { list($this->first, $this->fn) = func_get_args(); $this->current_value = $first; } function valid() { return $this->is_valid; } function next() { $result = call_user_func($this->fn, $this->current_value, ++$this->key); if ($result === false) { $this->is_valid = false; } else { $this->current_value = $result; } } function current() { return $this->current_value; } function key() { return $this->key; } function rewind() { $this->key = 0; $this->current_value = $this->first; $this->is_valid = true; } } function follow($first, $fn) { return new Follow($first, $fn); }
これの元ネタは、Factorという言語のfollowなんだけど、便利っぽいのでPHPでも書いてみた。
使い方
こんな感じ。
初項と漸化式をイテレータに変換してくれる。
<?php function hoge($elt) { return $elt + 2; } foreach (follow(-10, 'hoge') as $i => $elt) if ($elt > 10) break; else { echo "{$i}:{$elt}\n"; }
実行結果。
0:-10 1:-8 2:-6 3:-4 4:-2 5:0 6:2 7:4 8:6 9:8 10:10
公差2の等差数列が-10から10まで表示される。
以下のように書いても結果は同じ。
followに渡したコールバックがfalseを返すとイテレータは止まる。
<?php function fuga($elt) { return $elt < 10 ? $elt + 2 : false; } foreach (follow(-10, 'fuga') as $i => $elt) { echo "{$i}:{$elt}\n"; }
と、ここまで記事を書いていて、「for使った方が早くね?」という心の声が聞こえたけど、イテレータにしておくとイテレータを取るイテレータと連携できたり、勝手に添え字を生成してくれたりするのでこれはこれでまあいいかな、と思った。終わり。