Re: [RFC] Partial Function Application for instance of non-static methods ("$this")

From: Date: Fri, 06 Feb 2026 20:30:11 +0000
Subject: Re: [RFC] Partial Function Application for instance of non-static methods ("$this")
References: 1 2 3 4 5 6  Groups: php.internals 
Request: Send a blank email to internals+get-130039@lists.php.net to get a copy of this message
On Fri, Feb 6, 2026, at 10:43 AM, Tim Düsterhus wrote: > Hi > > On 1/22/26 17:41, Larry Garfield wrote: >> More spitballing on my previous reply: >> >> class Test { >> public function stuff(int $a) {} >> } >> >> (Test)?->stuff(?); > > As mentioned in the sibling mail, this is existing syntax and thus > doesn't work. Sure, but we can fiddle with the details to find something that works. I also suggested something like these to Arnaud off-list: (?: Test)->stuff(?); (Test ?)->stuff(?); ((Test)?)->stuff(?); > Keeping full type information is the main benefit of PFA over “just > write a Closure”. Being able to reorder parameters as part of partial > application is another explicit feature that would not be supported by > that syntax. Honestly, I don't much care about the reordering. And with this approach you'd still be able to reorder the method params, just keep the object as first arg. >> That would then be a lot easier to write in cases where you're just dropping a >> $this->stuff() call into a pipe chain but want to receive $this. > > The use case for partially applying $this is in cases where you > need a > “function handle”, that's why the examples are ones where the resulting > Closure is passed as a parameter to another function. > > Within a pipe chain you would just use the regular -> > operator on the > result of the previous step: > > $result = (trim($username) > |> $repository->findBy(name: ?) > )->getId(); > > It would also naturally support ?-> in case your repository > returns > null when the user cannot be found. Directly in a pipe chain, sure. However, I would see this as most useful as a callback to array_map et al (or future equivalents). Eg: import_stuff() |> array_filter(?, (?)->hasField('comment') |> array_map((?)->save(), $records) ; In this case, the only thing being partialed is the object on which to invoke. So there's no need to think about reordering the params in the first place: There's just one. Needing to specify the type in this case: import_stuff() |> array_filter(?, Record::hasField('comment', ...) |> array_map(Record::save(...), $records) ; Just adds more noise, and IMO creates confusion between static and non-static methods. --Larry Garfield

« previous php.internals (#130039) next »