On Friday, February 6th, 2026 at 21:32, Larry Garfield <[email protected]> 
wrote:

> 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
> 




I find the `(Test ?)->method()` suggestion quite nice. For 2 reasons, it looks 
similar to a function argument ("Type $arg"), and following that, given that 
the type is optional for function arguments, it could also be optional here to 
have `(?)->method()` or even `?->method()` as a shortcut. 


I understand it means some optimization cannot be done, but in a lot of case it 
doesn't matter, and if I have to write `DateTimeImmutable::format($this: ?, 
'c')` vs `fn ($dt) => $dt->format('c')`. The only benefit would be the 
optimization. so if I don't care about that I'm still going to go for the 
shorter one unless this a performance critical situation

Having `(DateTimeImmutable ?)->format('c')` and `?->format('c')` as a 
non-optimized shortcut seems more interesting to me.

I'm not too bothered by the reordering, I think this still covers 99% of the 
use cases

---

That said, regarding your 2 suggestions, Tim, and after reading your 
explanations, my preference goes for `$this: ?`

And yet more suggestions: `DateTimeImmutable::methodName($: ?, ...)` 


and whatever is between `$` and `:` could be used as the arg name of the 
generated function (with something like "__this" being the default if omitted)

the `$` prefix could also be replaced by any symbol not authorized at the start 
of an argument name, eg:

* `DateTimeImmutable::methodName(*it: ?, ...)`
* `DateTimeImmutable::methodName(~it: ?, ...)`
* `DateTimeImmutable::methodName(.it: ?, ...)` (it's getting worse and worse, 
ain't it?)

or, even more drastic changes:

* `DateTimeImmutable::methodName(*it, ...)`
* `DateTimeImmutable::methodName(?this, ...)`

(feel free to silently ignore them; I'm not putting that much thought into 
those suggestions)

regards,

Mathieu Rochette

Attachment: publickey - [email protected] - 0x8D30BA0E.asc
Description: application/pgp-keys

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to