* * Full license available in separate LICENSE file */ use Kadet\Functional as f; use const Kadet\Functional\_; class CurriedFunctionTest extends \PHPUnit\Framework\TestCase { /** * @var \Kadet\Functional\Utils\CurriedFunction */ private $function; private $variadic; private $optional; protected function setUp() { $this->function = function ($a, $b, $c, $d) { return $a . $b . $c . $d; }; $this->variadic = function (...$args) { return implode('', $args); }; $this->optional = function($a, $b = 'b', $c = 'c') { return $a . $b . $c; }; } public function testCallAfterAllArguments() { $f = f\curry($this->function); $this->assertSame('abcd', $f('a')('b')('c')('d')); $this->assertSame('abcd', $f('a')('b', 'c')('d')); $this->assertSame('abcd', $f('a')('b', 'c', 'd')); $this->assertSame('abcd', $f('a', 'b')('c', 'd')); $this->assertSame('abcd', $f('a', 'b', 'c')('d')); $this->assertSame('abcd', $f('a', 'b', 'c', 'd')); } public function testPartialApplication() { $f = f\curry($this->function); $g = $f('a', 'b'); $this->assertSame(['a', 'b'], $g->getArguments()); } public function testPartialApplicationWithPlaceholder() { $f = f\curry($this->function); $g = $f('a', _, 'c'); $this->assertInstanceOf(f\Utils\PartiallyAppliedFunction::class, $g); $this->assertSame([0 => 'a', 2 => 'c'], $g->getArguments()); $this->assertSame('abcd', $g('b', 'd')); } public function testOptionalArgumentsCall() { $f = f\curry($this->optional); $this->assertSame('abc', $f('a')); $this->assertSame('aBc', $f('a', 'B')); $this->assertSame('aBC', $f('a', 'B', 'C')); } public function testVariadicThreshold() { $f = f\curry($this->variadic, 3); $g = $f('a', _, 'c'); $this->assertSame('abc', $f('a', 'b', 'c')); $this->assertInstanceOf(f\Utils\PartiallyAppliedFunction::class, $g); $this->assertSame([0 => 'a', 2 => 'c'], $g->getArguments()); $this->assertSame('abc', $g('b')); } public function testForceApply() { $f = f\curry($this->variadic); $g = $f->apply('a', 'b'); $this->assertSame('', $f()); $this->assertSame('abc', $f('a', 'b', 'c')); $this->assertInstanceOf(f\Utils\PartiallyAppliedFunction::class, $g); $this->assertSame(['a', 'b'], $g->getArguments()); $this->assertSame('abc', $g('c')); } public function testForceCall() { $f = f\curry($this->variadic, 10); $g = $f->apply('a', 'b'); $this->assertSame('', $f->call()); $this->assertSame('abc', $f->call('a', 'b', 'c')); $this->assertInstanceOf(f\Utils\PartiallyAppliedFunction::class, $g); $this->assertSame(['a', 'b'], $g->getArguments()); $this->assertSame('abc', $g->call('c')); } public function testForceCallIfNoArgs() { $f = f\curry($this->variadic, f\Utils\CurriedFunction::INF); $this->assertSame('abcdef', $f('a', 'b', 'c')('d', 'e')('f')()); } public function testUncurry() { $f = f\curry($this->variadic, 10); $f = $f('a', 'b'); $f = $f->uncurry(); $this->assertInstanceOf(f\Utils\PartiallyAppliedFunction::class, $f); $this->assertSame(['a', 'b'], $f->getArguments()); $this->assertSame('abc', $f('c')); } public function testUncurryAlias() { $f = f\curry($this->variadic, 10); $f = $f('a', 'b'); $f = f\uncurry($f); $this->assertInstanceOf(f\Utils\PartiallyAppliedFunction::class, $f); $this->assertSame(['a', 'b'], $f->getArguments()); $this->assertSame('abc', $f('c')); } public function testThresholdChange() { $f = f\curry($this->variadic, 10); $g = $f->apply('a', 'b')->withThreshold(4); $this->assertSame(4, $g->getThreshold()); $this->assertInstanceOf(f\Utils\PartiallyAppliedFunction::class, $g); $this->assertInstanceOf(f\Utils\PartiallyAppliedFunction::class, $g('c')); $this->assertSame('abcd', $g('c', 'd')); } public function testThreshold() { $f = f\curry($this->function); $this->assertSame(4, $f->getThreshold()); $g = f\curry($this->optional); $this->assertSame(1, $g->getThreshold()); $h = f\curry($this->variadic); $this->assertSame(0, $h->getThreshold()); } }