Hello, thank you for an opinion as well! While I do fully agree that callable type needs to be improved with features such as typedefs, I found a couple of problems in your response.
First of all, I wouldn't say that the callable type provides little-to-no information like the resource type. A resource can only be made by specific functions such as `fopen()` and are bound to specific use cases/implementations e. g. MySQL resources are only for MySQL database access. Meanwhile, callables can be made "freely" (couldn't find a better word :-)) like integers or booleans and also in some cases don't have an exact function signature. One such example I mention in the next paragraph. Speaking of a snippet you showed, I'm not sure how that implementation would work with "dynamic" callables. For example let's assume we have a framework that allows registering routes with placeholders to controllers, like this: `$router->register('/post/{id}', [$controller, 'show']); // this would pass a single parameter to the callable` `$router->register('/user/{id}/post/{id}', [$controller, 'showFromUser']); // this would pass two parameters to the callable` ...in this case, we can't know how many placeholders/parameters a function can have as that depends on how many placeholders are in the string. A framework can only resolve these at runtime. Best regards, Benas Seliuginas ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Wednesday, April 22, 2020 6:01 PM, Michał Brzuchalski <michal.brzuchal...@gmail.com> wrote: > Hi all, > > śr., 22 kwi 2020 o 16:29 Dan Ackroyd <dan...@basereality.com> napisał(a): > >> On Tue, 21 Apr 2020 at 14:08, moliata <moli...@protonmail.com> wrote: >>> >> >>> I wanted to ignite a friendly discussion whether >>> PHP should allow typed callable properties. >> >> IMO no. > > I agree, a callable brings as much information as a resource type - you know > the type > but are unable to use it without additional information. > >> Trying to fix the problems with callables would be a huge amount of >> work, and not actually give that much benefit. Even just documenting >> the problems with callables* is a non-trivial amount of work, and I >> suspect there are many horrors lurking with the SPL code related to >> them. >> >>> I believe we should look into... >> >> I'm pretty sure that choosing a different problem to solve that: >> >> * would be easier to solve. >> * provide more benefit in the long term. >> * not require breaking a lot of userland + internal code immediately, >> but instead allow for migration over a longer period. > > I was pinged by Dan with typedef topic nearly 3 weeks ago and then started > thinking of the way to define callable types with some initial implementation. > I chose pattern known from other languages like C# where there are types > known as delegates. > > And so far got to the last line of snippet below where I have to figure out > some clever type checking with closure: > > delegate Reducer (?int $sum, int $item = 0): int; > > class Foo implements Reducer { > public function __invoke(?int $sum, int $item = 0): int { > return ($sum ?? 0) + $item; > } > } > function reduce(Reducer $reducer) { > var_dump($reducer(0, 5)); > } > reduce(new Foo()); > reduce(fn(?int $sum, int $item = 0): int => 8); > The delegate declaration resolves to an interface with __invoke method which > therefore can be easily checked > when the invokable object passed and that information can be easily cached. > Probably it can be cached also for closures > and functions but didn't get so far with the implementation yet. > > I was also asked why not a general use typedef which can be used to alias any > kind of type not only a callable. > But the reason why I chose delegates was that IMO typedef is more like an > aliasing mechanism, which means > all that is possible to be aliased should also be possible to be unaliased > and pasted in all type constraints used in > function/method parameters as well as class properties. > > Meaning if we allow: typedef reducer = callable(?int $sum, int $item = 0): > int; > We should also allow: function(callable(?int $sum, int $item = 0): int > $reducer) {} > Which IMO looks too verbose and that's why I think a delegate might be a good > idea as a way to provide > callable types checking. > > Any thoughts are highly appreciated! > > Cheers, > Michał Brzuchalski