On Thu, Apr 20, 2023 at 11:25 AM Larry Garfield <[email protected]> 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