keep currying when compiling curried closures
This commit is contained in:
parent
a4a51e32a1
commit
71e1b2cbdc
@ -71,6 +71,9 @@ function memoize(callable $callable)
|
|||||||
* Flattens a callable into a plain closure. Compilable objects (decorators, pipelines, predicates) are compiled, so
|
* Flattens a callable into a plain closure. Compilable objects (decorators, pipelines, predicates) are compiled, so
|
||||||
* calling the result does not go through them, also when given as a closure of their `__invoke` (e.g. `$pipe(...)`);
|
* calling the result does not go through them, also when given as a closure of their `__invoke` (e.g. `$pipe(...)`);
|
||||||
* any other callable is converted with closure().
|
* any other callable is converted with closure().
|
||||||
|
*
|
||||||
|
* A closure of a curried function's `__invoke` (`$curried(...)`) is kept as it is, so it keeps currying; the compiled
|
||||||
|
* curried function itself calls its target and does not curry further.
|
||||||
*/
|
*/
|
||||||
function compile(callable $callable): \Closure
|
function compile(callable $callable): \Closure
|
||||||
{
|
{
|
||||||
@ -78,7 +81,9 @@ function compile(callable $callable): \Closure
|
|||||||
$reflection = new \ReflectionFunction($callable);
|
$reflection = new \ReflectionFunction($callable);
|
||||||
$bound = $reflection->getClosureThis();
|
$bound = $reflection->getClosureThis();
|
||||||
|
|
||||||
return $bound instanceof Compilable && $reflection->getName() === '__invoke' ? $bound->compile() : $callable;
|
return $bound instanceof Compilable && !$bound instanceof CurriedFunction && $reflection->getName() === '__invoke'
|
||||||
|
? $bound->compile()
|
||||||
|
: $callable;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $callable instanceof Compilable ? $callable->compile() : closure($callable);
|
return $callable instanceof Compilable ? $callable->compile() : closure($callable);
|
||||||
|
|||||||
@ -243,6 +243,23 @@ class CompileTest extends \PHPUnit\Framework\TestCase
|
|||||||
$this->assertSame($pipeline('a')('b'), f\compile($pipeline)('a')('b'));
|
$this->assertSame($pipeline('a')('b'), f\compile($pipeline)('a')('b'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testCompiledClosureOfCurriedKeepsCurrying()
|
||||||
|
{
|
||||||
|
$curried = f\curry(fn ($a, $b) => "$a$b");
|
||||||
|
|
||||||
|
$this->assertSame('ab', f\compile($curried(...))('a')('b'));
|
||||||
|
$this->assertSame('ab', f\compile($curried(...))('a', 'b'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCompiledPipelineOfCurriedClosureKeepsCurrying()
|
||||||
|
{
|
||||||
|
$curried = f\curry(fn ($a, $b) => "$a$b");
|
||||||
|
$pipeline = f\pipe(strtoupper(...), $curried(...));
|
||||||
|
|
||||||
|
$this->assertSame($pipeline('a')('b'), f\compile($pipeline)('a')('b'));
|
||||||
|
$this->assertSame('ab', f\compile(f\pipe($curried(...), fn ($rest) => $rest('b')))('a'));
|
||||||
|
}
|
||||||
|
|
||||||
public function testCompileUnwrapsClosureOfCompilable()
|
public function testCompileUnwrapsClosureOfCompilable()
|
||||||
{
|
{
|
||||||
$spy = new class(strtoupper(...)) extends FunctionPipeline {
|
$spy = new class(strtoupper(...)) extends FunctionPipeline {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user