diff --git a/src/Utils/PartiallyAppliedFunction.php b/src/Utils/PartiallyAppliedFunction.php index a521e92..408b7d2 100644 --- a/src/Utils/PartiallyAppliedFunction.php +++ b/src/Utils/PartiallyAppliedFunction.php @@ -82,6 +82,24 @@ class PartiallyAppliedFunction implements Decorator, Compilable return static fn (...$args) => $callable(...$arguments, ...array_slice(array_values($args), 0, $extra)); } + // The common shape, e.g. partial(str_pad(...), _, 8): one placeholder and no room for more arguments. An + // unfilled placeholder stays in place, as below. + if (count($placeholders) === 1 && $extra === 0) { + $position = $placeholders[0]; + + if ($position === 0) { + $rest = array_slice($arguments, 1); + + return static fn ($value = PLACEHOLDER) => $callable($value, ...$rest); + } + + return static function ($value = PLACEHOLDER) use ($callable, $arguments, $position) { + $arguments[$position] = $value; + + return $callable(...$arguments); + }; + } + return static function (...$args) use ($callable, $arguments, $placeholders, $extra) { $args = array_values($args); $count = min(count($placeholders), count($args)); diff --git a/tests/CompileTest.php b/tests/CompileTest.php index cbf8bd1..81345ad 100644 --- a/tests/CompileTest.php +++ b/tests/CompileTest.php @@ -107,6 +107,17 @@ class CompileTest extends \PHPUnit\Framework\TestCase $this->assertSame('aa', f\compile(f\curry(str_repeat(...), null, 'a'))(2, 'extra')); } + public function testCompileSinglePlaceholderOfInternalTarget() + { + $leading = f\partial(str_pad(...), _, 3, '0', STR_PAD_LEFT); + $middle = f\partial(substr(...), 'abcdef', _, 2); + + $this->assertSame('007', f\compile($leading)('7', 'extra')); + $this->assertSame('cd', f\compile($middle)(2, 'extra')); + $this->assertSame($this->outcome(fn () => $leading()), $this->outcome(fn () => f\compile($leading)())); + $this->assertSame($this->outcome(fn () => $middle()), $this->outcome(fn () => f\compile($middle)())); + } + public function testCompileWithFewerArgumentsThanPlaceholdersMatchesDecorator() { $partial = f\partial(str_repeat(...), _, _);