2014-10-10 23:50 追記
GitHub および Packagist に公開しました。
https://github.com/yuya-takeyama/curry
https://packagist.org/packages/yuyat/curry
眠いのでコードのメモだけ。
<?php
class CurryingFunction
{
private $fn;
private $count;
private $args;
public function __construct($fn, $count, $args)
{
$this->fn = $fn;
$this->count = $count;
$this->args = $args;
}
public function apply($x)
{
$count = $this->count;
$nextArgs = $this->args;
foreach (func_get_args() as $arg) {
$nextArgs[] = $arg;
$count -= 1;
if ($count < 1) {
break;
}
}
if ($count < 1) {
return call_user_func_array($this->fn, $nextArgs);
} else {
return new static($this->fn, $count, $nextArgs);
}
}
public function __invoke($x)
{
return call_user_func_array(array($this, 'apply'), func_get_args());
}
}
function curry($fn, $count = null) {
if (!$count) {
$ref = new ReflectionFunction($fn);
$count = $ref->getNumberOfParameters();
}
return new CurryingFunction($fn, $count, array());
}
$f = curry(function ($x, $y, $z) { return $x + $y + $z; });
var_dump($f(1)->apply(2)->apply(3));
// => 6
var_dump($f(1, 2)->apply(3));
// => 6
var_dump($f(1, 2, 3));
// => 6