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

Reply via email to