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
Last revisionBoth sides next revision
rfc:callable-interfaces [2016/04/06 11:26] ocramiusrfc:callable-interfaces [2016/04/12 10:11] – Retiring RFC due to incompatible object -> function semantics mixup ocramius
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.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1