PHP で クロージャ さっきまでの無し
http://d.hatena.ne.jp/am11op/20070702/1183376369
↑前エントリがただの劣化コピーだってことに電車の中で気が付いた。
てことで、勝手にリベンジ。
その前に、closure の定義自体はとりあえず置いておいて、
自分が作ろうとしてる(欲しい)のは何なのか。
- 外側の変数を参照できる
- 使うその場で定義できる
↓ていうか、これ。
http://itpro.nikkeibp.co.jp/article/COLUMN/20050930/221971/?ST=oss
これができないのは、ただの callback 関数なんじゃないかと思うわけです。
で作ったのがこれ。
/*
* closure を実現するための class
*/
class Closure {
var $_args;
var $_func;
/**
* @private
*/
function Closure($func, $args) {
$this->_args = $args;
$func = ereg_replace("^function\([^\)]*\) *\{", "", $func);
$func = ereg_replace("\}$", "", $func);
$this->_func = $func;
}
/**
* @param $func string closure
* @param $arg1 $mixed first object/var which is used in $func
* @param $arg2 $mixed second object/var which is used in $func
* ...
*/
function bind() {
$args = func_get_args();
return new Closure(array_shift($args), $args);
}/**
* use this method to call closure
*/
function call() {
$func = create_function('$args', $this->_func);
$func($this->_args);
}
}// 以下、使用例
class Test{
function sayTest($int=0){
return 'this is a test.';
}
}
$obj = new Test;function piyo($bool, $obj) {
if ($bool) {
$obj['onSuccess']->call();
} else {
$obj['onFailure']->call();
}
}$hoge = "you know, ";
$arr = array(
'onSuccess'=>Closure::bind("function(\$args){echo '$hoge'.\$args[0]->sayTest();}", &$obj),
'onFailure'=>Closure::bind("function(\$args){echo 'fail!';"),
);echo piyo(true, $arr); // you know, this is a test.
echo piyo(false, $arr); // fail!
- Closure::bind の第一引数に closure を渡す
- closure 内の instance は全て $args とする
- $args に対応する instance を第二引数以降に渡す
- closure はダブルクォーテーションでくくる場合は、$args の前に「\」を付ける必要がある
- closure の頭に「function(\$args){」、尻に「}」が付いているが、これは closure であることを明示するためである
- どっちみち ereg_replace で削除されるので、はっきり言って必要ない
「\」がウザい場合は、クロージャをシングルクォーテーションで囲って、
普通の変数も引数に渡してクロージャ内から $args[n] として参照すればよいです。
ちょっとは closure ぽくなったでしょか。
トラックバック(0)
このブログ記事を参照しているブログ一覧: PHP で クロージャ さっきまでの無し
このブログ記事に対するトラックバックURL: http://pm.11op.net/mt/mt-tb.cgi/56
コメントする