On Thu, Apr 20, 2023 at 11:25 AM Larry Garfield <la...@garfieldtech.com> wrote:
>
> Hi folks.  This is a pre-discussion, in a sense, before a formal RFC.  
> Nicolas Grekas and I have been kicking around some ideas for how to address 
> the desire for typed callables, and have several overlapping concepts to 
> consider.  Before going down the rabbit hole on any of them we want to gauge 
> the general feeling about the approaches to see what is worth pursuing.
>
> We have three "brain dump" RFCs on this topic, although these are all still 
> in super-duper early stages so don't sweat the details in them at this point. 
>  We just want to discuss the basic concepts, which I have laid out below.
>
> https://wiki.php.net/rfc/allow_casting_closures_into_single-method_interface_implementations
> https://wiki.php.net/rfc/allow-closures-to-declare-interfaces-they-implement
> https://wiki.php.net/rfc/structural-typing-for-closures
>
> ## The problem
>
> function takeTwo(callable $c): int
> {
>     return $c(1, 2);
> }
>
> Right now, we have no way to statically enforce that $c is a callable that 
> takes 2 ints and returns an int.  We can document it, but that's it.
>
> There is one loophole, in that an interface may require an __invoke() method:
>
> interface TwoInts
> {
>     public function __invoke(int $a, int $b): int;
> }
>
> And then a class may implement TwoInts, and takeTwo() can type against 
> TwoInts.  However, that works only for classes, which are naturally 
> considerably more verbose than a simple closure and represent only a subset 
> of the possible callable types.
>
> The usual discussion has involved a way to specify a callable type's 
> signature, like so:
>
> function takeTwo(callable(int $a, int $b): int $c)
> {
>   return $c(1, 2);
> }
>
> But that runs quickly into the problem of verbosity, reusability, and type 
> aliases, and the discussion usually dies there.
>

I'm going to stop here. Two big things:

 1. I think reducing verbosity can be left for the future. We don't
have to solve that right now.
 2. I think there's another more important reason previous attempts
failed: they will inevitably burden the programmer without type
inference.For the moment, let's assume this signature:

    function takeTwo(callable(int $x, int $y): int $c);

What happens if I pass a short-closure?

    takeTwo(fn ($x, $y) => $x + $y);

I would be annoyed if I had to write the type info, but particularly
the return type.

Today, if I just used a static analysis tool, there's no problem:

    /** @param callable(int $x, int $y): int $c */
    function takeTwo(callable $c);
    takeTwo(fn ($x, $y) => $x + $y);

 3. And another reason they failed: callables are going to want
generic types pretty commonly. Think array_filter, array_map, etc.

So, I think these brain dump RFCs are all focusing on the wrong problems.

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to