====== PHP RFC: Partial Function Application: Handling of Optional Parameters ======
* Version: 1.0
* Date: 2026-04-20
* Author: Tim Düsterhus (timwolla@php.net), Arnaud Le Blanc (arnaud.lb@gmail.com)
* Status: Draft
* Implementation: https://github.com/...
===== Introduction =====
The accepted Partial Function Application RFC proposed inheriting the “optionality” of ?-placeholdered parameters. This results in inconsistent user-facing behavior and prevents “Future Scope” extensions of Partial Function Application due to technical issues. We propose making all ? placeholders required for more predictable behavior and to enable these PFA extensions.
===== Proposal =====
Parameters generated from ? placeholders shall consistently be non-optional parameters. Parameters that are pulled in by a ... placeholder shall continue to inherit their “optionality”.
Specifically:
// For:
function example(mixed $a, string $b = 'default', string $c = 'also optional') { }
// Making $b a placeholder
$c = example(?, ?);
// will result in a Closure that is effectively equivalent to:
$c = static fn (mixed $a, string $b) => example($a, $b);
// instead of the originally proposed:
$c = static fn (mixed $a, string $b = 'default') => example($a, $b);
The example(?, ?) syntax already visually implies that two arguments are expected to be passed to the resulting function. Since partially applied functions are expected to be passed to code taking a “generic callable with a specific signature”, callers of the partially applied function are built with that specific signature (and arity) in mind and cannot rely on one of the parameters being optional. This can also help static analysis tools provide a more accurate signature in case a “dynamic function” is partially applied.
There already is a situation where optional parameters will not inherit the “optionality”, specifically when a variadic parameter of the original function is targeted by a ? placeholder:
// Example taken from the original RFC
function foo(int $a = 5, int $b = 1, string ...$c) { }
$pfa = foo(?, ?, ?, ?);
// Equivalent to this:
// Note that $a and $b become required, because there must be at least 4 arguments.
$pfa = static fn(int $a, int $b, string $c0, string $c1) => foo($a, $b, $c0, $c1);
This behavior will naturally be unchanged by this RFC and will no longer be a special case since now the resulting partially applied function will always have as many required parameters as are implied by the number of ? specified at the time of creation.
Variadic placeholders will continue to behave as originally proposed:
// For:
function example(mixed $a, string $b = 'default', string $c = 'also optional') { }
// Making using variadic placeholders starting at $b
$c = example('foo', ...);
// will result in a Closure that is effectively equivalent to:
$c = static fn (string $b = 'default', string $c = 'also optional') => example('foo', $b, $c, ...array_slice(func_get_args(), 2));
==== Enabling Future Extensions ====
A natural follow-up of “Partial Function Application” is enabling partial application of the $this-object of a method call. In these cases the actual function that is being called is not known at the time the partially applied function is created, since depending on the object that is being provided as $this the method in question could be overridden in a child class. Since “default values” are not part of the actual function signature, there is no restrictions for the child class in specifying a different default value, including making a required parameter optional:
class Foo {
public function foo($a) { }
}
class Bar extends Foo {
public function foo($a = 1) { }
}
$o = new Bar();
$o->foo();
This means that there is option of filling in default value that will not result in unexpected, or inconsistent behavior:
- Always using the default value of the parent class will result in unexpected behavior when intentionally relying on a parameter being optional, expected the correct default value being filled in.
- Making all ? placeholders required when partially applying $this will add another special case to partial function application that users will need to be aware of.
This RFC thus proposes to make (2) the behavior for *all* partial application, resolving the inconsistency in a way that is unlikely to impact real-world use-cases.
===== Backward Incompatible Changes =====
None. Partial Function Application is not yet released.
===== Proposed PHP Version(s) =====
PHP 8.6
===== RFC Impact =====
==== To the Ecosystem ====
? placeholders will behave more predictably. This likely makes it easier for static analysis tools to figure out the resulting signature. The removal of edge cases will also simplify the documentation.
==== To Existing Extensions ====
None.
==== To SAPIs ====
None.
===== Open Issues =====
Make sure there are no open issues when the vote starts!
===== Future Scope =====
Support partially applying the $this parameter of method calls.
===== Voting Choices =====
Primary Vote requiring a 2/3 majority to accept the RFC:
* Yes
* No
* Abstain
===== Patches and Tests =====
Links to proof of concept PR.
If there is no patch, make it clear who will create a patch, or whether a volunteer to help with implementation is needed.
===== Implementation =====
After the RFC is implemented, this section should contain:
- the version(s) it was merged into
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
===== References =====
* [[partial_function_application_v2|PHP RFC: Partial Function Application (v2)]]
===== Rejected Features =====
None.
===== Changelog =====
* 2026-04-20: Initial version