functional-php/tests/CurriedFunctionTest.php

166 lines
4.6 KiB
PHP

<?php
/**
* Copyright 2018 Kacper Donat
*
* @author Kacper "Kadet" Donat <kacper@kadet.net>
*
* 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());
}
}