# RFC: Functional Interfaces

- Thread: https://externals.io/message/92404
- Original archive: https://news-web.php.net/php.internals/92404
- Started by Joe Watkins on 2016-04-18T10:22:48+00:00
- Messages: 20
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #92404 — Joe Watkins — 2016-04-18T10:22:48+00:00

URL: https://externals.io/message/92404#92404

Morning Internals,

    Please review the following RFC:

    https://wiki.php.net/rfc/functional-interfaces

    An implementation is provided, and is testable on 3v4l.

    Review of the implementation from those of you that do that would be
good :)

Cheers
Joe

---

## #92407 — Rowan Collins — 2016-04-18T11:34:31+00:00

URL: https://externals.io/message/92404#92407 · In reply to: #92404

Joe Watkins wrote on 18/04/2016 11:22:
>      Please review the following RFC:
>
>      https://wiki.php.net/rfc/functional-interfaces
>
>      An implementation is provided, and is testable on 3v4l.

This sounds like a really nice feature. As well as using functions to 
implement existing interfaces, it gives a nice way of typehinting the 
requirements of a callback without forcing users to create an object.

I must admit to being a bit confused by the term "functional interface" 
at first, though, because "functional" has so many different meanings - 
is this a term used elsewhere, or is it up for debate?

In particular, the error message "Fatal error: cannot implement non 
functional interface IFoo" makes me wonder what's "non-functional" about 
the interface. It would be clearer to me if it was more specific and 
avoided the jargon, e.g. "Anonymous function cannot implement interface 
with more than one method".

The error "functional interface cannot implement self" also seems 
inconsistent with the others - here "functional interface" refers to the 
*implementation*, not the interface. It might be clearer to just say 
"cannot implement non interface self" anyway - there's nothing actually 
special about "self" here, it's just another example of trying to use a 
class as an interface, which is illegal whatever the implementation.

These are of course minor details, and the rest of the feature as 
described sounds great. :)

Regards,
-- 
Rowan Collins
[IMSoP]

---

## #92409 — Joe Watkins — 2016-04-18T11:53:21+00:00

URL: https://externals.io/message/92404#92409 · In reply to: #92407

Morning,

    > I must admit to being a bit confused by the term "functional
interface" at first, though,
    > because "functional" has so many different meanings - is this a term
used elsewhere,
    > or is it up for debate?

The terminology is borrowed, Java 8 uses lamdas to implement specially
annotated interfaces, it refers to them as functional interfaces.

The other term is SAM ... but it feels a bit strange to give code a people
name, right ? :)

Single Abstract Method Interface Implementations is just ... too much ...

I find it to be a pretty concise description, although the wording of the
errors is definitely flexible.

The "non thing" wording was only chosen because it's used elsewhere in the
core, "non static" and so on.

It just feels a bit strange to say or think "functional interface", but
once you get over that ...

As far as anyone who is not familiar with the workings of PHP is concerned,
what they have is a function that implements an interface, functional
interface is a pretty good description of that.

Cheers
Joe





On Mon, Apr 18, 2016 at 12:34 PM, Rowan Collins <rowan.collins@gmail.com>
wrote:

> Joe Watkins wrote on 18/04/2016 11:22:
>
> > […]
>
> This sounds like a really nice feature. As well as using functions to
> implement existing interfaces, it gives a nice way of typehinting the
> requirements of a callback without forcing users to create an object.
>
> I must admit to being a bit confused by the term "functional interface" at
> first, though, because "functional" has so many different meanings - is
> this a term used elsewhere, or is it up for debate?
>
> In particular, the error message "Fatal error: cannot implement non
> functional interface IFoo" makes me wonder what's "non-functional" about
> the interface. It would be clearer to me if it was more specific and
> avoided the jargon, e.g. "Anonymous function cannot implement interface
> with more than one method".
>
> The error "functional interface cannot implement self" also seems
> inconsistent with the others - here "functional interface" refers to the
> *implementation*, not the interface. It might be clearer to just say
> "cannot implement non interface self" anyway - there's nothing actually
> special about "self" here, it's just another example of trying to use a
> class as an interface, which is illegal whatever the implementation.
>
> These are of course minor details, and the rest of the feature as
> described sounds great. :)
>
> Regards,
> --
> Rowan Collins
> [IMSoP]

---

## #92410 — Rowan Collins — 2016-04-18T12:00:57+00:00

URL: https://externals.io/message/92404#92410 · In reply to: #92409

Joe Watkins wrote on 18/04/2016 12:53:
> Morning,
>
> > […]
> interface" at first, though,
> > […]
> term used elsewhere,
> > […]
>
> The terminology is borrowed, Java 8 uses lamdas to implement specially 
> annotated interfaces, it refers to them as functional interfaces.
>

Thanks, I figured that was probably the case.


> As far as anyone who is not familiar with the workings of PHP is 
> concerned, what they have is a function that implements an interface, 
> functional interface is a pretty good description of that.

I guess what's confusing is that the new feature happens entirely at the 
implementation end, but the term describes the interface itself. What we 
actually have is a functional *implementation* of a normal, 
non-annotated interface; but the interface is *implicitly* functional 
because of having only a single method. So when the error says you have 
a "non functional interface", it's not clear what you need to do about it.

I like the implicit definition, though, because it reduces the need for 
a forwards compatibility break (libraries can support old versions of 
PHP, but their users still take advantage of the new feature if they 
want). So I'm not really sure how to make the definition of "functional 
interface" clearer, other than making sure we write some decent 
documentation. :)

Regards,
-- 
Rowan Collins
[IMSoP]

---

## #92420 — Fleshgrinder — 2016-04-18T18:28:58+00:00

URL: https://externals.io/message/92404#92420 · In reply to: #92410

+1 for the feature, very nice syntactic sugar to solve some edge cases.

I agree with Rowan, i also do not like the name and propose to call them
*closure interfaces*. There are already various synonyms for closures:

- anonymous function
- lambda function
- callback*

However, the strongest argument to call them *closure* is the fact that
the the class in PHP itself is actually called *\Closure*. I would even
go as far as saying that the documentation should be updated to always
use that word everywhere.* The fact that only closures can implement
such interfaces strengthens the reason to call them as proposed in my
opinion. Just because Java calls them /functional/ does not mean that we
should.

Regarding error messages:

    Fatal error: cannot implement non functional interface IFoo in
    /in/65W6i on line 7

    Fatal error: cannot implement nonclosure interface IFoo in
    /in/65W6i on line 7

Note on grammar:
http://www.chicagomanualofstyle.org/qanda/data/faq/topics/HyphensEnDashesEmDashes/faq0079.html

*) There is of course the situation of the various other ways to declare
the so called *user functions* (/call_user_func()/ and
/call_user_func_array()/) and those should always be referred to as
*callback*; imho.

-- 
Richard "Fleshgrinder" Fussenegger

---

## #92427 — Stanislav Malyshev — 2016-04-18T19:17:06+00:00

URL: https://externals.io/message/92404#92427 · In reply to: #92404

Hi!

>     Please review the following RFC:
> 
>     https://wiki.php.net/rfc/functional-interfaces
> 
>     An implementation is provided, and is testable on 3v4l.

This looks like a rather narrow case already covered by anonymous
classes. Am I missing something? What is the added value of it that
can't be done now?

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #92429 — Marcio Almada — 2016-04-18T21:01:53+00:00

URL: https://externals.io/message/92404#92429 · In reply to: #92427

Hi!

2016-04-18 15:17 GMT-04:00 Stanislav Malyshev <smalyshev@gmail.com>:

> Hi!
>
> > […]
>
> This looks like a rather narrow case already covered by anonymous
> classes. Am I missing something? What is the added value of it that
> can't be done now?
>
> --
> Stas Malyshev
> smalyshev@gmail.com
>
> --
> 
> 
>

I haven't decided if I'm in favor of this feature yet but I asked the same
questions as you when the pull request landed. This gist served as a good
illustration of possible benefits
https://gist.github.com/marcioAlmada/12ef23038bcf5acaa2e2f6b808c968d3.
Boilerplate measuring apart, it seems logical that a closure should be able
to fulfill an interface with a single method.

About the applicability, I'm under the same impression as you, the use case
is probably narrow, perhaps because anonymous classes is a newly added
feature and wasn't explored enough.

Cheers.
Márcio Almada.

---

## #92432 — Sara Golemon — 2016-04-19T00:37:27+00:00

URL: https://externals.io/message/92404#92432 · In reply to: #92427

On Mon, Apr 18, 2016 at 12:17 PM, Stanislav Malyshev
<smalyshev@gmail.com> wrote:
> Hi!
>
> > […]
>
> This looks like a rather narrow case already covered by anonymous
> classes. Am I missing something? What is the added value of it that
> can't be done now?
>
I thought Joe covered that question pretty thoroughly by his countable
examples.  The version using anonymous classes certainly *works*, but
it's significantly more boilerplate code and has a higher cognitive
overhead compared to the functional interface example which is concise
and to the point.

That said, I'm not sure what I'd use it for, but as syntactic sugar
goes it's quite sleek.

-Sara

---

## #92449 — Dmitry Stogov — 2016-04-19T12:01:33+00:00

URL: https://externals.io/message/92404#92449 · In reply to: #92404

<?php
interface IFoo {
    public function method() : int;
}
 
$cb1 = function () implements IFoo : int {
    return 42;
};

$cb2 = new class implements IFoo {
  function method() : int {
    return 42;
 }
};
?>

Are $cb1 and $cb2 going to be the same (do the same)?
Is this just a new syntax sugar, or a really new feature?

According to implementation, I think, you shouldn't extend "zend_closure" with "interface".
If this is a sugar, lets implement it as a sugar (without VM changes).

But may be I didn't understand the idea at all :)

Thanks. Dmitry.

---

## #92451 — Joe Watkins — 2016-04-19T12:50:38+00:00

URL: https://externals.io/message/92404#92451 · In reply to: #92449

Morning Dmitry,

  In your example, they will do the same thing.

  Anon classes don't have lexical scope, I have a patch for that, and an
RFC, I'm just tidying it.

  Even when anon classes do have lexical scope, there is value in being
able to implement these kinds of interfaces using only a function.

  The changes to the vm are restricted to a few lines, that's not seriously
a problem, is it !?

  I don't see where I extend closure with an interface ...

  >     zend_do_inheritance_ex(type, zend_ce_closure, 1);
  >     zend_class_implements(type, 1, interface);

Cheers
Joe



> <?php
> interface IFoo {
>     public function method() : int;
> }
>
> $cb1 = function () implements IFoo : int {
>     return 42;
> };
>
> $cb2 = new class implements IFoo {
>   function method() : int {
>     return 42;
>  }
> };
> ?>
>
> Are $cb1 and $cb2 going to be the same (do the same)?
> Is this just a new syntax sugar, or a really new feature?
>
> According to implementation, I think, you shouldn't extend "zend_closure"
> with "interface".
> If this is a sugar, lets implement it as a sugar (without VM changes).
>
> But may be I didn't understand the idea at all :)
>
> Thanks. Dmitry.
>
>
> ________________________________________
> From: Joe Watkins <pthreads@pthreads.org>
> Sent: Monday, April 18, 2016 13:22
> To: PHP internals
> Subject: [PHP-DEV] RFC: Functional Interfaces
>
> Morning Internals,
>
>     Please review the following RFC:
>
>     https://wiki.php.net/rfc/functional-interfaces
>
>     An implementation is provided, and is testable on 3v4l.
>
>     Review of the implementation from those of you that do that would be
> good :)
>
> Cheers
> Joe

---

## #92452 — Joe Watkins — 2016-04-19T12:52:40+00:00

URL: https://externals.io/message/92404#92452 · In reply to: #92451

Oh, it's confusing text in the RFC, using the word "Interface" ... that's
meant as a placeholder for InterfaceName.

Cheers
Joe



> Morning Dmitry,
>
>   In your example, they will do the same thing.
>
>   Anon classes don't have lexical scope, I have a patch for that, and an
> RFC, I'm just tidying it.
>
>   Even when anon classes do have lexical scope, there is value in being
> able to implement these kinds of interfaces using only a function.
>
>   The changes to the vm are restricted to a few lines, that's not
> seriously a problem, is it !?
>
>   I don't see where I extend closure with an interface ...
>
> > […]
>
> Cheers
> Joe
>
> 
>
> > […]

---

## #92455 — Dmitry Stogov — 2016-04-19T13:22:19+00:00

URL: https://externals.io/message/92404#92455 · In reply to: #92452

> Oh, it's confusing text in the RFC, using the word "Interface" ... 
> that's meant as a placeholder for InterfaceName.
>
> Cheers
> Joe
>
> On Tue, Apr 19, 2016 at 1:50 PM, Joe Watkins <pthreads@pthreads.org 
> <mailto:pthreads@pthreads.org>> wrote:
>
>     Morning Dmitry,
>
>       In your example, they will do the same thing.
>
>       Anon classes don't have lexical scope, I have a patch for that,
>     and an RFC, I'm just tidying it.
>

OK. so this is not just a syntax sugar, but if you implement lexical 
scope for anonymous classes it's going to be sugar. Right?
May be it's better to start from classes first?

>
>       Even when anon classes do have lexical scope, there is value in
>     being able to implement these kinds of interfaces using only a
>     function.
>

What value? just shorter syntax? or anything else?

>
>       The changes to the vm are restricted to a few lines, that's not
>     seriously a problem, is it !?
>

I hope no. I didn't understand all details of proposal and I didn't take 
a deep look into the code.

>
>       I don't see where I extend closure with an interface ...
>

I meant new field zend_execute_data *interface in zend_closure structure.
I thought the same might be implemented through anonymous classes.

Thanks. Dmitry.

>
> > […]
>
>     Cheers
>     Joe
>
>     On Tue, Apr 19, 2016 at 1:01 PM, Dmitry Stogov <dmitry@zend.com
>     <mailto:dmitry@zend.com>> wrote:
>
>         <?php
>         interface IFoo {
>             public function method() : int;
>         }
>
>         $cb1 = function () implements IFoo : int {
>             return 42;
>         };
>
>         $cb2 = new class implements IFoo {
>           function method() : int {
>             return 42;
>          }
>         };
>         ?>
>
>         Are $cb1 and $cb2 going to be the same (do the same)?
>         Is this just a new syntax sugar, or a really new feature?
>
>         According to implementation, I think, you shouldn't extend
>         "zend_closure" with "interface".
>         If this is a sugar, lets implement it as a sugar (without VM
>         changes).
>
>         But may be I didn't understand the idea at all :)
>
>         Thanks. Dmitry.
>
>
>         ________________________________________
>         From: Joe Watkins <pthreads@pthreads.org
>         <mailto:pthreads@pthreads.org>>
>         Sent: Monday, April 18, 2016 13:22
>         To: PHP internals
>         Subject: [PHP-DEV] RFC: Functional Interfaces
>
>         Morning Internals,
>
>             Please review the following RFC:
>
>         https://wiki.php.net/rfc/functional-interfaces
>
>             An implementation is provided, and is testable on 3v4l.
>
>             Review of the implementation from those of you that do
>         that would be
>         good :)
>
>         Cheers
>         Joe

---

## #92458 — Joe Watkins — 2016-04-19T13:29:33+00:00

URL: https://externals.io/message/92404#92458 · In reply to: #92455

> What value?

Yes, shorter, more concise (from the programmers perspective) syntax.

Right now, if you do a lot of work with Closures, you have to verify their
interface, the value in having the engine do it for you seems really
obvious.

But also ...

> I thought the same might be implemented through anonymous classes.

An anonymous class cannot be rebound, they are obviously not the same thing.

> I didn't take a deep look into the code.

I'll wait until you have, I think :)

Cheers
Joe



>
>
> 
>
> Oh, it's confusing text in the RFC, using the word "Interface" ... that's
> meant as a placeholder for InterfaceName.
>
> Cheers
> Joe
>
> On Tue, Apr 19, 2016 at 1:50 PM, Joe Watkins <pthreads@pthreads.org>
> wrote:
>
> > […]
>
> OK. so this is not just a syntax sugar, but if you implement lexical scope
> for anonymous classes it's going to be sugar. Right?
> May be it's better to start from classes first?
>
>
> > […]
>
> What value? just shorter syntax? or anything else?
>
>
> > […]
>
> I hope no. I didn't understand all details of proposal and I didn't take a
> deep look into the code.
>
>
> > […]
>
> I meant new field zend_execute_data *interface in zend_closure structure.
> I thought the same might be implemented through anonymous classes.
>
> Thanks. Dmitry.
>
>
>
> > […]

---

## #92461 — Dmitry Stogov — 2016-04-19T14:12:00+00:00

URL: https://externals.io/message/92404#92461 · In reply to: #92458

For me, the proposal is too complex.
I prefer intuitive concepts, that I may use without rereading manual 
again and again.
For this one, I even can't imagine a natural (not over-designed) use case.
But this is my personal opinion, and I may be wrong :)

I'll review the code later.

Thanks. Dmitry.



> > […]
>
> Yes, shorter, more concise (from the programmers perspective) syntax.
>
> Right now, if you do a lot of work with Closures, you have to verify 
> their interface, the value in having the engine do it for you seems 
> really obvious.
>
> But also ...
>
> > […]
>
> An anonymous class cannot be rebound, they are obviously not the same 
> thing.
>
> > […]
>
> I'll wait until you have, I think :)
>
> Cheers
> Joe
>
> On Tue, Apr 19, 2016 at 2:22 PM, Dmitry Stogov <dmitry@zend.com 
> <mailto:dmitry@zend.com>> wrote:
>
>
>
>     
> > […]
>
>     OK. so this is not just a syntax sugar, but if you implement
>     lexical scope for anonymous classes it's going to be sugar. Right?
>     May be it's better to start from classes first?
>
> > […]
>
>     What value? just shorter syntax? or anything else?
>
> > […]
>
>     I hope no. I didn't understand all details of proposal and I
>     didn't take a deep look into the code.
>
> > […]
>
>     I meant new field zend_execute_data *interface in zend_closure
>     structure.
>     I thought the same might be implemented through anonymous classes.
>
>     Thanks. Dmitry.
>
>
> > […]

---

## #92464 — Rowan Collins — 2016-04-19T14:30:36+00:00

URL: https://externals.io/message/92404#92464 · In reply to: #92461

Dmitry Stogov wrote on 19/04/2016 15:12:
> I prefer intuitive concepts, that I may use without rereading manual 
> again and again.
> For this one, I even can't imagine a natural (not over-designed) use 
> case. 

The use case that came to my mind is kind of the other way around from 
"syntax sugar for anonymous classes" - providing a contract for what a 
callback should look like. In essence, it's an alternative to specifying 
closure type with a generic-like syntax, as proposed at 
https://wiki.php.net/rfc/callable-types

Say you currently have this:

public function registerCallback(callable $callback) { ... }

You could instead specify what the callback needs to accept and return:

interface EventCallbackInterface {
     public function __invoke(Event $event): boolean;
}
public function registerCallback(EventCallbackInterface $callback) { ... }

Using __invoke as the method name may or may not be a good idea, but it 
interestingly means I don't need to change the code that runs the 
callback, I can just use $callback($some_event); Then if someone wants 
to use a complex object, they can; and if they just want to use a 
closure, it has to meet the contract.

Regards,
-- 
Rowan Collins
[IMSoP]

---

## #92467 — Dmitry Stogov — 2016-04-19T14:48:48+00:00

URL: https://externals.io/message/92404#92467 · In reply to: #92464

> Dmitry Stogov wrote on 19/04/2016 15:12:
> > […]
>
> The use case that came to my mind is kind of the other way around from 
> "syntax sugar for anonymous classes" - providing a contract for what a 
> callback should look like. In essence, it's an alternative to 
> specifying closure type with a generic-like syntax, as proposed at 
> https://wiki.php.net/rfc/callable-types
>
> Say you currently have this:
>
> public function registerCallback(callable $callback) { ... }
>
> You could instead specify what the callback needs to accept and return:
>
> interface EventCallbackInterface {
>     public function __invoke(Event $event): boolean;
> }
> public function registerCallback(EventCallbackInterface $callback) { 
> ... }
>
> Using __invoke as the method name may or may not be a good idea, but 
> it interestingly means I don't need to change the code that runs the 
> callback, I can just use $callback($some_event); Then if someone wants 
> to use a complex object, they can; and if they just want to use a 
> closure, it has to meet the contract.

callable-type is much simpler solution for this use-case.
Usage of Interfaces to check function prototypes is a bit tricky, but 
yes, this is a possible use-case.
Do you like to work with framework, that use this trick for every callback?

Thanks. Dmitry.
>
>
> Regards,

---

## #92468 — Rowan Collins — 2016-04-19T15:02:33+00:00

URL: https://externals.io/message/92404#92468 · In reply to: #92467

Dmitry Stogov wrote on 19/04/2016 15:48:
> callable-type is much simpler solution for this use-case.
> Usage of Interfaces to check function prototypes is a bit tricky, but 
> yes, this is a possible use-case.
> Do you like to work with framework, that use this trick for every 
> callback? 

If you don't use __invoke as the function name, you can have a single 
class implement multiple contracts, e.g. to register for more than one 
event type with different signatures.

I guess if you had callable-types *and* union types, you could get the 
best of both worlds:

interface UserEventCallbackInterface {
     public function handleUserEvent(UserEvent $event): boolean;
}
public function registerCallback(EventCallbackInterface|callable(Event): 
boolean $handler) { ... }

The implementation has to be a bit fiddlier here, because you need to 
sometimes call $handler->handleUserEvent($event) and sometimes 
$handler($event); with a functional interface, the engine makes 
$handler->handleUserEvent($event) work for you. The cost is that the 
call site has to be a bit more verbose to specify the interface, rather 
than implicitly meeting the contract.

Regards,
-- 
Rowan Collins
[IMSoP]

---

## #92469 — Larry Garfield — 2016-04-19T15:21:12+00:00

URL: https://externals.io/message/92404#92469 · In reply to: #92468

> Dmitry Stogov wrote on 19/04/2016 15:48:
> > […]
>
> If you don't use __invoke as the function name, you can have a single 
> class implement multiple contracts, e.g. to register for more than one 
> event type with different signatures.
>
> I guess if you had callable-types *and* union types, you could get the 
> best of both worlds:
>
> interface UserEventCallbackInterface {
>     public function handleUserEvent(UserEvent $event): boolean;
> }
> public function 
> registerCallback(EventCallbackInterface|callable(Event): boolean 
> $handler) { ... }
>
> The implementation has to be a bit fiddlier here, because you need to 
> sometimes call $handler->handleUserEvent($event) and sometimes 
> $handler($event); with a functional interface, the engine makes 
> $handler->handleUserEvent($event) work for you. The cost is that the 
> call site has to be a bit more verbose to specify the interface, 
> rather than implicitly meeting the contract.
>
> Regards,

Which is why I'm not sure I like that approach, because the place I then 
call $handler needs to have a conditional in it.  There's another RFC 
that was posted to Twitter but hasn't made it to the list yet that seems 
to solve this better:

https://wiki.php.net/rfc/callable-types

(My apologies to the authors if they aren't done with it; it's on the 
wiki so I'm assuming it's safe to mention in public.)

That allows just the callable-type syntax (which I presume is what 
you're referencing), but you can then pass an object in using 
[]-callable syntax: [$handler. 'handleUserEvent'], and then 
registerCallback() doesn't care if it was a function, method, closure, 
or whatever else. It can just () it.

-- 
--Larry Garfield

---

## #92470 — Marcio Almada — 2016-04-19T15:30:38+00:00

URL: https://externals.io/message/92404#92470 · In reply to: #92469

Hi!

2016-04-19 11:21 GMT-04:00 Larry Garfield <larry@garfieldtech.com>:

> 
>
> > […]
I believe Joe has both $handler->handleUserEvent($event) and
$handler($event) cases covered already. This means that
$handler->handleUserEvent($event), $handler() and $handler->__invoke($event)
should be 100% equivalent.


> Regards,
> > […]
>
> Which is why I'm not sure I like that approach, because the place I then
> call $handler needs to have a conditional in it.  There's another RFC that
> was posted to Twitter but hasn't made it to the list yet that seems to
> solve this better:
>
> https://wiki.php.net/rfc/callable-types
>
> (My apologies to the authors if they aren't done with it; it's on the wiki
> so I'm assuming it's safe to mention in public.)
>
>
Yes, it it's ok to mention the RFC. We are going to move it to discussion
phase ASAP some minor issues get a fix :)


> That allows just the callable-type syntax (which I presume is what you're
> referencing), but you can then pass an object in using []-callable syntax:
> [$handler. 'handleUserEvent'], and then registerCallback() doesn't care if
> it was a function, method, closure, or whatever else. It can just () it.
>
> --
> --Larry Garfield

---

## #92471 — Rowan Collins — 2016-04-19T15:33:18+00:00

URL: https://externals.io/message/92404#92471 · In reply to: #92469

Larry Garfield wrote on 19/04/2016 16:21:
> Which is why I'm not sure I like that approach, because the place I 
> then call $handler needs to have a conditional in it.  There's another 
> RFC that was posted to Twitter but hasn't made it to the list yet that 
> seems to solve this better:
>
> https://wiki.php.net/rfc/callable-types

I'm not sure which approach you mean, but in Joe's proposal, you always 
call $handler as though it was an object implementing the interface; 
have a look at the ILog example in the RFC.

With a typed callable, you can always invoke as $handler(...) will work, 
but the implementer can't create an object that meets more than one 
contract, because they can only provide one __invoke method.


interface UserEventCallbackInterface {
     public function handleUserEvent(UserEvent $event): boolean;
}
interface CommentEventCallbackInterface {
     public function handleCommentEvent(CommentEvent $event): boolean;
}

class Logger implements UserEventCallbackInterface, 
CommentEventCallbackInterface { ... }
$logger = new Logger;

$simple_user_handler = function(UserEvent $event) implements 
UserEventCallbackInterface: boolean { ... }


In Joe's proposal, $logger and $simple_user_handler can be used 
interchangeably by calling $handler->handleUserEvent(...); the receiving 
code doesn't need to do anything special to accept the closure form, 
because the engine transforms it into the required object.

Regards,
-- 
Rowan Collins
[IMSoP]
