3v4l.org

run code in 300+ PHP versions simultaneously
)<?php class SinglePlaceholder { } class VariadicPlaceholder { } $PLACEHOLDER = new SinglePlaceholder(); $VARIADIC_PLACEHOLDER = new VariadicPlaceholder(); function partial(callable $in, ...$args) { $fmap = []; $partialIndex = 0; $variadic = false; foreach ($args as $k => $arg) { if ($arg instanceof SinglePlaceholder) { $fmap[$partialIndex++] = $k; } if ($arg instanceof VariadicPlaceholder) { $variadic = true; if ($k < count($args) - 1) { throw new ArgumentCountError('Only the last parameter may be a variadic placeholder'); } $fmap[$partialIndex++] = $k; } } return static function (...$partialArgs) use ($in, $args, $fmap, $variadic) { if (count($partialArgs) < count($fmap)) { throw new ArgumentCountError('Expected ' . count($fmap) . ' only received ' . count($partialArgs)); } foreach ($partialArgs as $pIndex => $pValue) { $targetSlot = $fmap[$pIndex] ?? null; if ($targetSlot === null) { if ($variadic) { $args[] = $pValue; } else { throw new ArgumentCountError('Too many arguments without a variadic placeholder'); } } else { $args[$targetSlot] = $pValue; } } return $in(...$args); }; } function foo($a, $b, $c, $d, $e) { var_dump($a, $b, $c, $d, $e); } print_r(partial('foo', 1, $PLACEHOLDER, 3, $PLACEHOLDER, 5)(2, 4)); print_r(partial('foo', $VARIADIC_PLACEHOLDER)('a', 'b', 'c', 'd', 'e')); print_r(partial('foo', 1, 2, 3, 4, 5)());
Output for 8.0.7
)int(1) int(2) int(3) int(4) int(5) string(1) "a" string(1) "b" string(1) "c" string(1) "d" string(1) "e" int(1) int(2) int(3) int(4) int(5)

preferences:
35.97 ms | 455 KiB | 5 Q