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