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