在闭包不存在的情况下,实现部分参数绑定的一个替代品……
首先举例partial/curry
- def add(a,b):
- return a+b
- def add_a(b):
- def ad(a):
- return a+b
- return ad
- print add(1,2) # 3
- add_1 = add_a(1)
- add_2 = add_a(2)
- print add_1(2) # 3
- print add_2(2) # 4
下面在php中实现类似功能
- function bind($func, array $params)
- {
- $reflect = new ReflectionFunction($func);
- $funParams = $reflect->getParameters();
- $paramsDeclare = array();
- $paramsInvoke = array();
- $paramsRestore = array();
- foreach ($funParams as $i => $p)
- {
- /*@var $p ReflectionParameter*/
- if(array_key_exists($i, $params)){
- $paramsRestore[] = "/${$p->getName()} = unserialize('" . serialize($params[$i]) . "');";
- }else {
- $string = ReflectionParameter::export($func, $p->getName(), true);
- $paramsDeclare[] = preg_replace('(^[^/[]*/[ |or NULL | /]|<optional> )', '', $string);
- }
-
- $paramsInvoke[] = '$' . $p->getName();
- }
- $clauseRestore = implode("/n", $paramsRestore);
- $clauseInvoke = implode(",", $paramsInvoke);
- $clauseDeclare = implode(",", $paramsDeclare);
- // echo nl2br("create_function(/"$clauseDeclare/", /"$clauseRestore;/nreturn $func($clauseInvoke);/");");
- return create_function($clauseDeclare, "$clauseRestore;/nreturn $func($clauseInvoke);");
- }
用法如下:
- function testfun($arg1 = "sdf", ReflectionFunction $objArg = null, Array $arrayArg = null){
- echo $arg1;
- var_export($objArg);
- echo $arrayArg;
- }
- $a = bind('testfun', array(0=> 'cat', 1=> new ReflectionFunction('run'), 2=> array('sdf' => true)));
- $a();
bind function好丑啊~~愁死我了……php啊php……
----------------------------------------------------------------------------
在这里的评论里看到一个实现:
- function curry($funcName) {
- $inArgs = array_slice(func_get_args(), 1);
- $serInArgs = serialize($inArgs);
- $rfunc = new ReflectionFunction($funcName);
- $funcArgs = $rfunc->getParameters();
- $curriedArgs = array_slice($funcArgs, count($inArgs));
- foreach ($curriedArgs as $i=>$arg) {
- $curriedArgs[$i] = '$'.$arg->getName();
- }
- $curriedArgs = implode(', ', $curriedArgs);
- return create_function(
- $curriedArgs,
- '
- $rfunc = new ReflectionFunction("'.$funcName.'");
- $args = func_get_args();
- $applyArgs = unserialize("'.str_replace('"', '//"', $serInArgs).'");
- settype($applyArgs, "array");
- foreach ($applyArgs as $arg) {
- array_unshift($args, $arg);
- }
- return $rfunc->invokeArgs($args);
- '
- );
- }
在这里看到另一个美一些的实现:
- function partial()
- {
- if(!class_exists('partial'))
- {
- class partial{
- var $values = array();
- var $func;
- function partial($func, $args)
- {
- $this->values = $args;
- $this->func = $func;
- }
- function method()
- {
- $args = func_get_args();
- return call_user_func_array($this->func, array_merge($args, $this->values));
- }
- }
- }
- //assume $0 is funcname, $1-$x is partial values
- $args = func_get_args();
- $func = $args[0];
- $p = new partial($func, array_slice($args,1));
- return array($p, 'method');
- }