On Sun, 22 Jan 2023 at 17:45, Ollie Read <php@ollie.codes> wrote:
>
> Hello all,

Hi Ollie,

> I've created a feature request issue on GitHub (here: 
> https://github.com/php/php-src/issues/10414), but I have been advised that 
> it's best to post here.
> ...
> I think we could delay the error until the closure was called.

That sounds like a complete non-starter. Adding something to the
language that produces a closure that can't be called would be an
instant new entry for PHPSadness.

> Whereas it would be much nicer to have the following:
>
> ```
> $collection->filter(Str::empty(...));
> ```
>
> In this situation, the collection library would be responsible for binding the
> closure to the value it is iterating.

How would the collection library know it was safe to bind the closure
to each value it was iterating over? It sounds really type unsafe.


> What I would like to introduce/suggest, is the ability to create a closure
> from a method using the first-class-callable syntax...
>
> The more I think about it, the more I think this may require a new ...

I think people should say clearly what the problem they are trying to
solve first, before suggesting solutions.

I think there's at least a couple of problems that can be thought about:

i. Although the first-class-callable syntax allowed avoiding string
based programming for most callables, it doesn't support referring to
some things that you would want to call, including both instance
methods, and constructors*.

ii. Representing an instance method requires at least two pieces of
info; which class it belongs to (which can be used to find the
constructor) and the parameters of the method itself. That doesn't
naturally fit into a closure.

iii. The appropriate syntax for referencing a class instance method
without it being string based isn't obvious. Or at least it isn't
obvious to me.

iv. Writing code that for callback methods is longer than it could be,
e.g. as Larry Garfield wrote:

> So what you're really looking for is a shorter way to write this:
>
> foo(fn(Str $s) => $s->beep());


At the risk of suggesting an abomination, given a class of:

class Zoq
{
    public function __construct(private Fot $fot) {}

    public function Pik(string $zebranky): Frungy {...}
}

If it was possible to generate callable for the constructor with:

$fnConstructor = Closure::fromClassConstructor(Zoq::class);
// signature of $fnConstructor is the same as `function(Fot $fot): Zoq`

Or for individual methods:

$fnMethod = Closure::fromClassMethod(Zoq::class, 'Pik');
// signature of $fnMethod is the same as `function(Zoq $zoq, string
$zebranky): Frungy`

That sort of looks like a solution to most of the problems I think exist.

For your particular problem, I believe that would allow:

$fnMethod = Closure::fromClassMethod(Str::class, 'empty');
$collection->filter($fnMethod);

Which isn't shorter, but at least allows passing the callables around
with the type inspectable. Though it might be nicer if PHP had the
ability to definte function signatures types.

That sort of solution obviously doesn't address the problem of having
to refer to the class method as a string, but as I said, I don't have
a suggestion for that. Well, other than to use a different syntax.**

cheers
Dan
Ack

* constructors having their own terrible history.

** https://news-web.php.net/php.internals/114542

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

Reply via email to