On Mon, Jan 23, 2023, at 12:32 PM, Dan Ackroyd wrote: > 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.**
I don't think that actually helps. If you have the object already, then making an FCC from it already works: https://3v4l.org/GTAGR If you do not have the object already, then we run back into the issue I pointed out before where we need to differentiate a bindable from needs-binding callable, which is already an issue (though one I've not run into). I think that's a prerequisite for adding any dedicated syntax for "make a closure that doesn't work until it gets bound". --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php