Skip to content

Commit

Permalink
support referential transparency of curried function
Browse files Browse the repository at this point in the history
  • Loading branch information
nishimura committed Jan 22, 2016
1 parent 35d2b2b commit b8824bf
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 24 deletions.
52 changes: 28 additions & 24 deletions src/Laiz/Func/CurryTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,37 @@ public static function curry(callable $f)
if ($count === 0)
throw new \InvalidArgumentException('Cannot curry none arguments function');

$args = array_fill(0, $count, null);
$prev = function($a) use ($f, &$args, $count){
$args[$count - 1] = $a;
$anys = [];
foreach ($args as $k => $v){
if ($v instanceof Any)
$anys[$k] = $v;
}
if ($anys){
$ref = new \ReflectionFunction($f);
$params = $ref->getParameters();
foreach ($anys as $k => $v){
$type = $params[$k]->getClass();
if ($type){
$args[$k] = $v->castByName($type->getName());
$makeCurry = function($count, $args) use ($f, &$makeCurry){
$count--;
if ($count > 0){
return new static(function($a) use (&$makeCurry, $count, $args){
$args[] = $a;
return $makeCurry($count, $args);
});
}else{
return function($a) use ($args, $f){
$args[] = $a;
$anys = [];

foreach ($args as $k => $v){
if ($v instanceof Any)
$anys[$k] = $v;
}
}
if ($anys){
$ref = new \ReflectionFunction($f);
$params = $ref->getParameters();
foreach ($anys as $k => $v){
$type = $params[$k]->getClass();
if ($type){
$args[$k] = $v->castByName($type->getName());
}
}
}
return $f(...$args);
};
}
return call_user_func_array($f, $args);
};
for ($i = $count - 2; $i >= 0; $i--){
$prev = new static(function($a) use ($prev, &$args, $i){
$args[$i] = $a;
return $prev;
});
}
return $prev;
return $makeCurry($count, []);
}

public function __invoke($a)
Expand Down
18 changes: 18 additions & 0 deletions test/src/Laiz/Test/Func/CurryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,22 @@ public function testStaticArray()
$f = c(['Laiz\Test\Func\CurryTest','staticFunc']);
$this->assertInstanceOf('Laiz\Func\Curry', $f);
}

public function testReferentialTransparency()
{
$f = c(function($a, $b, $c){
return $a + $b + $c;
});
$f1 = $f(5);
$f2 = $f1(8);
$this->assertEquals(213, $f2(200));

$f3 = $f1(9);
$this->assertEquals(213, $f2(200));
$this->assertEquals(214, $f3(200));

$tmp = $f(-100);
$this->assertEquals(213, $f2(200));
$this->assertEquals(214, $f3(200));
}
}

0 comments on commit b8824bf

Please sign in to comment.