Tuesday, February 19, 2008

[PHP] PartialFunction and PartialMethod

I found really interesting this John Resig post, about partial functions in JavaScript.

For a weird problem, I choosed to use the same behaviour, but with a different language: PHP

Sometime PHP is more flexible than we think (at least me), and this is the result of my little experiment:

class ReflectionPartialFunction extends ReflectionFunction {

protected $args;

public function __construct($name){
parent::__construct($name);
$this->args = func_get_args();
array_splice($this->args, 0, 1);
}

public function invoke($args){
$args = func_get_args();
return $this->invokeArgs($args);
}

public function invokeArgs(array $args){
return parent::invokeArgs(array_merge($args, $this->args));
}

public function rinvoke($args){
$args = func_get_args();
return $this->rinvokeArgs($args);
}

public function rinvokeArgs(array $args){
return parent::invokeArgs(array_merge($this->args, $args));
}
}

class ReflectionPartialMethod extends ReflectionMethod {

protected $args;

public function __construct($class, $name){
parent::__construct($class, $name);
$this->args = func_get_args();
array_splice($this->args, 0, 2);
}

public function invoke($object, $args){
$args = func_get_args();
return $this->invokeArgs(array_shift($args), $args);
}

public function invokeArgs($object, array $args){
return parent::invokeArgs($object, array_merge($args, $this->args));
}

public function rinvoke($object, $args){
$args = func_get_args();
return $this->rinvokeArgs(array_shift($args), $args);
}

public function rinvokeArgs($object, array $args){
return parent::invokeArgs($object, array_merge($this->args, $args));
}
}


While these are two simple tests:

function mul($num, $fixedParam = 0){
return $fixedParam * $num;
}

class Test{
protected $num;
public function __construct($num){
$this->num = $num;
}
public function me($num, $fixedParam = 1){
return $this->num * $fixedParam * $num;
}
}

$partial = new ReflectionPartialFunction('mul', 12);
echo $partial->invoke(2); // 24

$partial = new ReflectionPartialMethod('Test', 'me', 12);
echo $partial->invoke(new Test(2), 2); // 48


Now it's your round to find real applications ;)

update
Honestly, I need right arguments and my first implementation put partial arguments before the others and not at the end.

With this update you can use, by default, argments at the end of the function, but if you want to use them before, just call rinvoke or rinvokeArgs (r means put recieved arguments, during invoke or invokeArgs, on the right, at the end)

function mul($paramFixed, $num){
return $paramFixed / $num;
}
$ref = new ReflectionPartialFunction('mul', 4);
echo $ref->rinvoke(2); // will be 2, as 4 / 2

No comments:

Post a Comment