rfc:callable-interfaces

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:callable-interfaces [2016/04/06 11:27] ocramiusrfc:callable-interfaces [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 4: Line 4:
   * Author: Ben Scholzen, mail@dasprids.de   * Author: Ben Scholzen, mail@dasprids.de
   * Author: Marco Pivetta, ocramius@gmail.com   * Author: Marco Pivetta, ocramius@gmail.com
-  * Status: Draft+  * Status: Retired
   * First Published at: http://wiki.php.net/rfc/callable-interfaces   * First Published at: http://wiki.php.net/rfc/callable-interfaces
  
Line 15: Line 15:
 ===== Proposal ===== ===== Proposal =====
  
-PHP already has a way to define objects that act as functions. That mechanism is the **_****_invoke** magic method, which is widely used in libraries and frameworks. In addition to that, **Closure** already implements **_**_****invoke**.+PHP already has a way to define objects that act as functions. That mechanism is the **_****_invoke** magic method, which is widely used in libraries and frameworks. In addition to that, **Closure** already implements **_****_****invoke**.
  
-**_**_****invoke** already works quite well: with this proposal, generic *callable* arrays, functions and objects will be usable as if they implemented a matching interface:+**_****_****invoke** already works quite well: with this proposal, generic *callable* arrays, functions and objects will be usable as if they implemented a matching interface:
  
 <code php> <code php>
-interface RegisterUser +interface RegisterUser {
-{+
     public function __invoke(Username $username) : UserRegistration;     public function __invoke(Username $username) : UserRegistration;
 } }
Line 52: Line 51:
  
 <code php> <code php>
-class Register +class Register {
-{+
     public static function register(Username $username) : UserRegistration {     public static function register(Username $username) : UserRegistration {
         // ... domain logic here ...         // ... domain logic here ...
Line 67: Line 65:
  
 <code php> <code php>
-class Register +class Register {
-{+
     public function register(Username $username) : UserRegistration {     public function register(Username $username) : UserRegistration {
         // ... domain logic here ...         // ... domain logic here ...
Line 90: Line 87:
  
 In order for this to work, any implicitly defined callable should be cast to a *Closure* at call-time. In order for this to work, any implicitly defined callable should be cast to a *Closure* at call-time.
 +
 +In pseudo-code, this would look like following, under the hood:
 +
 +<code php>
 +function passAParameterToAPhpFunction(callable $callable, $expectedParameterInterface) {
 +    if (! $expectedParameterInterface->isCallableInterface()) {
 +        passParameter($callable);
 +        
 +        return;
 +    }
 +    
 +    if (! $expectedParameterInterface->matches($callable)) {
 +         throw new TypeError('Expected X, got Y');
 +    }
 +    
 +    if (! is_object($callable)) {
 +        $callable = wrapInCompatibleAnonymousClass($callable);
 +    }
 +    
 +    passParameter($callable);
 +}
 +</code>
 +
 +===== Still Open for Discussion =====
 +
 +How will **instanceof** behave, when asked for a type-check against **callable**?
 +
 +<code php>
 +interface RegisterUser {
 +    public function __invoke(Username $username) : UserRegistration;
 +}
 +
 +interface DeleteUserRegistration {
 +    public function __invoke(Username $username) : UserRegistration;
 +}
 +
 +$register = function (Username $username) : UserRegistration {
 +    return new UserRegistration(...);
 +};
 +
 +var_dump($register instanceof DeleteUserRegistration); // true? false? possibly want to keep current semantics here.
 +</code>
 +
 +===== Retired =====
 +
 +This RFC has been retired. Reason for that is that PHP currently (Version 7.0~7.1) allows applying function semantics to objects via the **_****_invoke** magic methods. Allowing the opposite would mix the domain of functions and objects in ways that are very hard to disentangle, and it would needlessly complicate the language semantics.
 +
 +While it is unfortunate that migration to type-safe callables (https://wiki.php.net/rfc/typesafe-callable) would require some interface rewrites, that is indeed the correct solution, as it keeps the uni-directionality between object and function semantics.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
rfc/callable-interfaces.1459942024.txt.gz · Last modified: 2017/09/22 13:28 (external edit)