Rubyのイテレータもどき
こんなんじゃダメかなぁ・・・
function &yield(&$block) { if (!is_array($block)) { trigger_error("指定されたブロックは配列ではありません", E_USER_ERROR); } if (count($block) < 2) { trigger_error("指定されたブロックの要素数が不足です。", E_USER_ERROR); } if (!is_object($block[0]) && !is_string($block[0])) { trigger_error("指定されたブロックの最初の要素が不正です。", E_USER_ERROR); } if (!is_string($block[1])) { trigger_error("指定されたブロックの2番目の要素が不正です。", E_USER_ERROR); } $class =& $block[0]; $method =& $block[1]; $args = ""; for ($i = 2; $i < count($block); ++$i) { $args .= "\$block[$i],"; } $args = trim($args, ','); if (is_object($class)) { $evalstr = sprintf('$ret =& $class->%s(%s);', $method, $args); } else { $evalstr = sprintf('$ret =& %s::%s(%s);', $class, $method, $args); } $ret = null; eval($evalstr); return $ret; }
使う側
class Hoge { function &blockmethod(&$arg1, &arg2) { // ブロック処理を記述 return $obj; } function &calling() { $block = array(&$this, 'blockmethod', &$arg1, &$arg2); $ret =& $this->called($block); return $ret; } function &called(&$block) { $ret =& yield($block); return $ret; } }
PHPではRubyのようにブロック(処理のまとまり)を渡せないので、関数かオブジェクトにする必要があるはず。なので、Rubyとは違ってブロック部分をオブジェクトのメソッドを作る必要がありますが、とりあえず動いてそうなのでよしとしようと思ってます。