rfc:allow-closures-to-declare-interfaces-they-implement

This is an old revision of the document!


PHP RFC: Allow Closures to Declare Interfaces they Implement

Introduction

This RFC proposes the addition of a syntax that allows closures to declare one or more interfaces they implement. This would provide developers with a more explicit and type-safe way to define and interact with closures in PHP. The proposed syntax is as follows:

$f = function ($a) implements FooInterface { ... };

Proposal

The current version of PHP allows closures to be used as a convenient way to define anonymous functions. However, the language does not offer a way to explicitly define the interfaces that a closure implements, which can lead to less clear and less type-safe code. The proposed change would allow closures to declare one or more interfaces they implement, providing a more robust and explicit way to interact with closures.

Since closures implement only one __invoke() method, the interfaces listed when declaring the closure should all declare one single compatible __invoke() method.

Syntax

The proposed syntax adds an implements keyword followed by one or more interface names to the closure declaration. This addition can be combined with optional return types and the short closure syntax.

Example 1: Closure with a return type and a use statement

$add = function (int $a, int $b) use ($c) implements AddInterface: int {
    return $a + $b + $c;
};

Example 3: Closure implementing multiple interfaces

$process = function ($input) use ($config) implements ProcessorInterface, ValidatorInterface: Result {
    // ...
};

Example 4: Short closure syntax

$square = fn (int $x) implements SquarerInterface: int => $x * $x;

Benefits

Introducing the ability to declare interfaces for closures would provide several benefits:

  • Improved code readability: By explicitly declaring the interfaces that a closure implements, developers can more easily understand the intended behavior and usage of the closure. This can lead to clearer and more maintainable code.
  • Enhanced type safety: By allowing closures to declare interfaces, type hinting can be used more effectively in function and method signatures that accept closures. This can help prevent runtime errors and improve overall code quality.
  • Better IDE support: With the addition of interface declarations for closures, IDEs can provide better code completion, error checking, and refactoring support.
  • Promotes code reusability: By explicitly defining the interfaces that a closure implements, developers can create more modular and reusable code. This can lead to a reduction in code duplication and improved overall design.
  • Easier testing and mocking: Closures implementing interfaces can be more easily replaced with mock objects in unit tests, leading to more robust and maintainable test suites.

Thanks to this feature, it is expected that code authors would shift from type-hinting for Closure to type-hinting for interfaces they could leverage for the purpose of better type safety:

Before:

class Example
{
    /**
     * @param Closure(Input):Result $processor
     */
    function setProcessor(Closure $processor)
    {
        // ...
    }
}
 
(new Example)->setProcessor(fn ($input) => $result);

After:

interface ProcessorInterface
{
    public function __invoke(Input $input): Result;
}
 
class Example
{
    function setProcessor(ProcessorInterface $processor)
    {
        // ...
    }
}
 
(new Example)->setProcessor(fn ($input) implements ProcessorInterface => $result);

Backward Compatibility

The proposed change would be fully backward compatible, as it adds a new feature without affecting existing functionality.

Future Scope

The base Closure class could be extended to add a castTo() method that'd allow turning a Closure instance into an instance of another single-method interface.

Proposed PHP Version

This RFC targets PHP version 8.3.

Vote

The vote will require a 2/3 majority to be accepted. Voting will start on [Vote start date] and end on [Vote end date].

rfc/allow-closures-to-declare-interfaces-they-implement.1681455028.txt.gz · Last modified: 2023/04/14 06:50 by nicolasgrekas