From b8824bf0c3b95aaca42afc7d5d53e53705dfcb42 Mon Sep 17 00:00:00 2001 From: Satoshi Nishimura Date: Fri, 22 Jan 2016 17:56:30 +0900 Subject: [PATCH] support referential transparency of curried function --- src/Laiz/Func/CurryTrait.php | 52 ++++++++++++++------------- test/src/Laiz/Test/Func/CurryTest.php | 18 ++++++++++ 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/src/Laiz/Func/CurryTrait.php b/src/Laiz/Func/CurryTrait.php index fae04da..373863e 100644 --- a/src/Laiz/Func/CurryTrait.php +++ b/src/Laiz/Func/CurryTrait.php @@ -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) diff --git a/test/src/Laiz/Test/Func/CurryTest.php b/test/src/Laiz/Test/Func/CurryTest.php index ff747c7..3c36b41 100644 --- a/test/src/Laiz/Test/Func/CurryTest.php +++ b/test/src/Laiz/Test/Func/CurryTest.php @@ -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)); + } }