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

Hi

Arnaud and I would like to start discussion on our RFC “Partial Function Application for instance of non-static methods ("$this")” which is intended to round-off the Partial Function Application RFC that was accepted recently:

Best regards
Tim Düsterhus

On Thu, 22 Jan 2026, Tim Düsterhus wrote:

Arnaud and I would like to start discussion on our RFC “Partial Function
Application for instance of non-static methods ("$this")” which is intended to
round-off the Partial Function Application RFC that was accepted recently:

PHP: rfc:partial_function_application_this

  We propose allowing a named parameter $this: ? to be combined with the
  “scope resolution operator” syntax of referring to a method.

I can't say I am entirely sold on the syntax here — starting with a $
makes it look like a variable.

  Since the $this: ? parameter does not refer to a parameter in
  the underlying argument list and thus there is no ambiguity with
  regard to positional parameters it may be placed at any position
  of the parameter list

I think I would be keen on *requiring* this to be the **first** in the
argument list.

Although there is no ambiguity, I also can't see why you would want to
have it anywhere else.

And the RFC does acknowledge "instance methods which effectively carry
an implicit $this parameter that is provided on the left side of the ->
operator."

With both these two above comments, I think I would like to see a better
syntax — but I am unsure if that's possible.

  It may also not be used when partially applying an instance
  method with a known object.

  $c = $dateTime->format($this: ?, "c"); // Fatal error: Invalid use of $this placeholder

Can you explain (in the RFC) what you mean by "known object" — I don't
think the language on what this means is clear enough.

cheers,
Derick

Hi

Am 2026-01-22 16:33, schrieb Derick Rethans:

PHP: rfc:partial_function_application_this

  We propose allowing a named parameter $this: ? to be combined with the
  “scope resolution operator” syntax of referring to a method.

I can't say I am entirely sold on the syntax here — starting with a $
makes it look like a variable.

Yes, it certainly requires some getting used to it. It's the best we could come up with, but if there are any better suggestions, we're open to hearing those. I'd like to note the “Rejected Features” section, since it lists some non-workable alternatives we considered.

  Since the $this: ? parameter does not refer to a parameter in
  the underlying argument list and thus there is no ambiguity with
  regard to positional parameters it may be placed at any position
  of the parameter list

I think I would be keen on *requiring* this to be the **first** in the
argument list.

Although there is no ambiguity, I also can't see why you would want to
have it anywhere else.

Being able to “reorder” parameters to (better) fit a specific callback signature is an explicit feature of PFA that we also wanted to support for `$this`.

As an example, suppose objects could be used as an array key. `array_find()` first passes the value and then the key to the callback. In this case users might want to do the following:

     class SomeObject {
         public function __construct(private string $value) { }
         public function hasMatchingValue(string $value) { return $value === $this->value; }
     }

     $array = [
         new SomeObject('foo') => 'bar',
         new SomeObject('baz') => 'baz',
     ];

     array_find(SomeObject::hasMatchingValue(value: ?, $this: ?), $array);

In this case `array_find()` is supposed to return `'baz'`, since this is where the values match.

  It may also not be used when partially applying an instance
  method with a known object.

  $c = $dateTime->format($this: ?, "c"); // Fatal error: Invalid use of $this placeholder

Can you explain (in the RFC) what you mean by "known object" — I don't
think the language on what this means is clear enough.

I have rephrased that to “It may also not be used when partially applying an instance method using the -> operator, since the object is already specified:”

Best regards
Tim Düsterhus

On 22/01/2026 16:08, Tim Düsterhus wrote:

Yes, it certainly requires some getting used to it. It's the best we could come up with, but if there are any better suggestions, we're open to hearing those. I'd like to note the “Rejected Features” section, since it lists some non-workable alternatives we considered.

Looking at this:

> PHP itself already has "ALGOL-style" declarations, for "const", "global", and "static".

I'm reminded of placeholders in PostgreSQL; the type is needed to choose overloaded functions and operators, so this doesn't compile (without extra metadata):

Select do_something(?) as result

Instead, you can insert a dummy cast to indicate the type:

Select do_something(?::int) as result

The PHP equivalent would be something like this:

$f = (DateTimeImmutable)?->format('c');

Or, slightly more readable but less consistent with casts:

$f = (? as DateTimeImmutable)->format('c');

That doesn't solve the second part of the problem though:

> It would also not allow to reorder the parameters in the resulting Closure, which is an explicit feature of Partial Function Application.

I thought I'd throw it out there anyway in case it stimulates any other ideas.

--
Rowan Tommins
[IMSoP]

On Thu, Jan 22, 2026, at 10:08 AM, Tim Düsterhus wrote:

Hi

Am 2026-01-22 16:33, schrieb Derick Rethans:

PHP: rfc:partial_function_application_this

  We propose allowing a named parameter $this: ? to be combined with the
  “scope resolution operator” syntax of referring to a method.

I can't say I am entirely sold on the syntax here — starting with a $
makes it look like a variable.

Yes, it certainly requires some getting used to it. It's the best we
could come up with, but if there are any better suggestions, we're open
to hearing those. I'd like to note the “Rejected Features” section,
since it lists some non-workable alternatives we considered.

I too am very much in favor of this functionality, though not a fan of the syntax either.

My previous, un-finished thinking was for `$$->foo('blah')`, which would translate to a mixed fn that just forwards the call. I... hadn't actually thought about also partially applying the method, since the use cases I can think of would all be "call this method on the value piped from the previous pipe step." (Or, read this property.) That would allow it to be embedded within an array_map() call or similar, since it's technically independent of both PFA and pipes.

If it's being partially applied, then I don't see a way around the redundant typing, which is annoying. At least not without vastly better type inference than we have today.

So, I think I am mainly interested in the degenerate case where $this is the only thing being partially applied, which seems like a common enough case that it could have a nicer version? I'm just spitballing at this point, I think. But I do like the direction.

--Larry Garfield

On Thu, Jan 22, 2026, at 10:26 AM, Rowan Tommins [IMSoP] wrote:

On 22/01/2026 16:08, Tim Düsterhus wrote:

Yes, it certainly requires some getting used to it. It's the best we
could come up with, but if there are any better suggestions, we're
open to hearing those. I'd like to note the “Rejected Features”
section, since it lists some non-workable alternatives we considered.

Looking at this:

> PHP itself already has "ALGOL-style" declarations, for "const",
"global", and "static".

I'm reminded of placeholders in PostgreSQL; the type is needed to choose
overloaded functions and operators, so this doesn't compile (without
extra metadata):

Select do_something(?) as result

Instead, you can insert a dummy cast to indicate the type:

Select do_something(?::int) as result

The PHP equivalent would be something like this:

$f = (DateTimeImmutable)?->format('c');

Or, slightly more readable but less consistent with casts:

$f = (? as DateTimeImmutable)->format('c');

That doesn't solve the second part of the problem though:

> It would also not allow to reorder the parameters in the resulting
Closure, which is an explicit feature of Partial Function Application.

I thought I'd throw it out there anyway in case it stimulates any other
ideas.

More spitballing on my previous reply:

class Test {
  public function stuff(int $a) {}
}

(Test)?->stuff(?);

Translates to:

fn(Test $__this, int $a) => $__this->stuff($a);

But if there's no partialing on the method side, it could get abbreviated to:

(?)->stuff(4);

Translates to:

fn(object $__this) => $__this->stuff(4);

Because we don't need to know the type at compile time, and a method-not-found error would still happen at runtime anyway if necessary. 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.

I'm not sure if that would also allow for reading properties with the same syntax?

--Larry Garfield

On Thursday, January 22nd, 2026 at 10:52, Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Arnaud and I would like to start discussion on our RFC “Partial Function
Application for instance of non-static methods ("$this")” which is
intended to round-off the Partial Function Application RFC that was
accepted recently:

PHP: rfc:partial_function_application_this

Hi!

I often whished something like this existed :slight_smile: Didn't get trough to suggest it because I wasn't sure of the syntax either (and lazyness)

still, my syntax suggestions:

    array_map(DateTimeImmutable->format("c"), $dates);

I understand this doesn't allow reordeing though, but it feels so much better and I expect would be what's needed for most cases that I hope something like this could work.

and an opt-in mechanic to reorder could be introduced for that use case. the previous suggestion could be a shortcut for:

    array_map(?::DateTimeImmutable->format("c"), $dates);

and a separate improvement to PFA could add support for picking arguments by name or position:

    array_find(?key::SomeObject->hasMatchingValue(?), $array);
    array_find(?2::SomeObject->hasMatchingValue(?), $array);

I noticed `?->method(?)` was considered; evne if it was possible, I would prefer if the type was explict, as you may want to use an interface name (or a union type, etc.) too

regards,

Mathieu Rochette

Best regards
Tim Düsterhus

On Thu, January 22, 2026 at 03:50 Tim Düsterhus wrote:

Arnaud and I would like to start discussion on our RFC “Partial Function
Application for instance of non-static methods ("$this")” which is
intended to round-off the Partial Function Application RFC that was
accepted recently:

PHP: rfc:partial_function_application_this

Hi Tim and Arnaud,

Thank you for your work on this. However, I'm struggling to see the benefit
of this syntax over short closures given the examples in the RFC:

    $dates = [
        new DateTimeImmutable('now'),
    ];

    $formattedDates = array_map(DateTimeImmutable::format($this: ?, "c"), $dates);

This saves only three characters compared to a short closure:

    $formattedDates = array_map(fn(DateTimeImmutable $d) => $d->format("c"), $dates);

Furthermore, duplicating the array's type isn't necessary when IDEs and static
analysis can infer it, so short closures can usually be even more concise:

    $formattedDates = array_map(fn($d) => $d->format("c"), $dates);

I also find the use of `$this` as a named argument confusing. It makes it
appear as though the current class instance is somehow being passed to the
method, when this isn't the case.

The other example with Symfony Form's `ChoiceType` doesn't sell the syntax
for me, either:

    'choice_label' => Category::getName($this: ?),

A short closure is barely any longer, and makes it easier to add additional
logic when needed:

    'choice_label' => fn(Category $c) => $c->getName(),

    'choice_label' => fn(Category $c) => strtoupper($c->getName()),

Ultimately I'm not convinced it's worth it to make the partial function syntax
and semantics more complicated to support this scenario, given that short
closures already provide similar conciseness and greater flexibility.

Kind regards,
Theodore

Hi

Am 2026-01-22 18:30, schrieb Mathieu Rochette:

I often whished something like this existed :slight_smile: Didn't get trough to suggest it because I wasn't sure of the syntax either (and lazyness)

Thank you for participating in the discussion of *this* RFC then. Having more voices available helps building things that suit the community best :slight_smile:

still, my syntax suggestions:

    array_map(DateTimeImmutable->format("c"), $dates);

Unfortunately this doesn't work, because it is a already-legal method call on a method stored in the constant called `DateTimeImmutable`. See: Online PHP editor | output for 3khkT

I noticed `?->method(?)` was considered; evne if it was possible, I would prefer if the type was explict, as you may want to use an interface name (or a union type, etc.) too

Union types would likely be unsupported either way, since multiple members of the union could have incompatible signatures for the same method. Interfaces are fully supported with the currently proposed syntax (it's explicitly mentioned in the RFC).

Best regards
Tim Düsterhus

Hi

Am 2026-01-23 00:25, schrieb Theodore Brown:

Thank you for your work on this. However, I'm struggling to see the benefit
of this syntax over short closures given the examples in the RFC:

    $dates = [
        new DateTimeImmutable('now'),
    ];

    $formattedDates = array_map(DateTimeImmutable::format($this: ?, "c"), $dates);

To provide some background on how this RFC came about: Arnaud and I were discussing my recent `array_map()` optimization (zend_compile: Optimize `array_map()` with callable convert callback into foreach by TimWolla · Pull Request #20934 · php/php-src · GitHub) that compiles `array_map()` calls that either use FCC or PFA as the callback into the equivalent `foreach()` loop. The optimization skipped when an actual Closure is passed, since full-blown Closures come with all kinds of scope-related (edge) cases to consider, making it much more complicated. I noted that I believed that with PFA many `array_map()` cases could be handled without a full Closure and that it was unfortunate that it didn't work for “filling in the object itself”.

I then came up with the basic idea for the proposed syntax half-a-minute later and we figured it would at least be worth proposing it, since it mapped onto the existing PFA semantics in a fairly straight-forward fashion.

This saves only three characters compared to a short closure:

    $formattedDates = array_map(fn(DateTimeImmutable $d) => $d->format("c"), $dates);

The return type would be missing in that snippet. And depending on your codebase's policy you might also need `static` in front of the short Closure. This might become less relevant with php.internals: Closure optimizations, but personally I would still consider it a best-practice to be explicit.

Personally I also feel that short Closures have some “visual overhead” in that they don't feel like a simple “method reference”. It's quite similar to how PFA itself is technically redundant with short Closures, but allows to be more explicit with the intention (which enabled the optimization mentioned above).

Furthermore, duplicating the array's type isn't necessary when IDEs and static
analysis can infer it, so short closures can usually be even more concise:

    $formattedDates = array_map(fn($d) => $d->format("c"), $dates);

This is true when the Closure is immediately consumed, but not when it's intended to be reused at a later point, e.g. with the Symfony Form example where the IDE / Static Analyzer needs some deeper knowledge about how the 2nd and 3rd parameter of `->add()` interact.

I also find the use of `$this` as a named argument confusing. It makes it
appear as though the current class instance is somehow being passed to the
method, when this isn't the case.

That's fair. I would've hoped to just use `this:` without the `$`, but that comes with the breaking change for variadics mentioned at the bottom of the RFC.

A short closure is barely any longer, and makes it easier to add additional
logic when needed:

    'choice_label' => fn(Category $c) => $c->getName(),

    'choice_label' => fn(Category $c) => strtoupper($c->getName()),

Note: Return type + Static also missing here. And of course if more parameters would be passed, it would scale differently (since more types are required for proper autocompletion).

Best regards
Tim Düsterhus

Mathieu Rochette

On Friday, January 23rd, 2026 at 09:37, Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Am 2026-01-22 18:30, schrieb

Mathieu Rochette

:

> I often whished something like this existed :slight_smile: Didn't get trough to
> suggest it because I wasn't sure of the syntax either (and lazyness)

Thank you for participating in the discussion of this RFC then. Having
more voices available helps building things that suit the community best
:slight_smile:

> still, my syntax suggestions:
>

> array_map(DateTimeImmutable->format("c"), $dates);

Unfortunately this doesn't work, because it is a already-legal method
call on a method stored in the constant called `DateTimeImmutable`. See:
Online PHP editor | output for 3khkT

ohhh

then, continuing on bikeshedding, I think I still prefer `?::DateTimeImmutable->format("c")` or `(? as DateTimeImmutable)->format("c")` as Larry mentioned.

`(DateTimeImmutable)?->format("c")` feels a bit weird. Reminds me too much of the null-safe operator.

> I noticed `?->method(?)` was considered; evne if it was possible, I
> would prefer if the type was explict, as you may want to use an
> interface name (or a union type, etc.) too

Union types would likely be unsupported either way, since multiple
members of the union could have incompatible signatures for the same

They could have incompatible signatures, yes, but they also could have compatible ones too. It's not a deal breaker. I don't imagine needing this in practice. But I don't see why the language would prevent that; I can already make that mistake with short closures or any methods. For me, it's the role of the static analyzer to tell me if I made such a mistake (or runtime errors ^^).

Interfaces are fully supported with the currently proposed
syntax (it's explicitly mentioned in the RFC).

Best regards
Tim Düsterhus

Hi

Am 2026-01-23 14:06, schrieb Mathieu Rochette:

`(DateTimeImmutable)?->format("c")` feels a bit weird. Reminds me too much of the null-safe operator.

That's because it is. It's literally the same case of a `DateTimeImmutable` constant with useless parentheses and the null-safe object member access: Online PHP editor | output for NebOR

They could have incompatible signatures, yes, but they also could have compatible ones too. It's not a deal breaker. I don't imagine needing this in practice. But I don't see why the language would prevent that; I can already make that mistake with short closures or any methods. For me, it's the role of the static analyzer to tell me if I made such a mistake (or runtime errors ^^).

The signature would need to be “unique” to properly generate the signature of the resulting Closure.

Best regards
Tim Düsterhus

Hi

Am 2026-01-22 17:26, schrieb Rowan Tommins [IMSoP]:

The PHP equivalent would be something like this:

$f = (DateTimeImmutable)?->format('c');

See my reply to Mathieu on why this specific one wouldn't work.

Or, slightly more readable but less consistent with casts:

$f = (? as DateTimeImmutable)->format('c');

That would work, but indeed would not solve the reordering case. I also feel it is inventing more new syntax than the current “scope-resolution-operator” syntax the RFC uses (which is not just used for static method calls).

Best regards
Tim Düsterhus

Hi Tim,

On Thu, Jan 22, 2026 at 4:53 PM Tim Düsterhus <tim@bastelstu.be> wrote:

Hi

Arnaud and I would like to start discussion on our RFC “Partial Function
Application for instance of non-static methods ("$this")” which is
intended to round-off the Partial Function Application RFC that was
accepted recently:

PHP: rfc:partial_function_application_this

I really like that feature.

The syntax however, including some proposed in this thread, makes
little sense to me.

It is also challenging as it targets 8.6. I am not sure it is a good
idea to rush and make bad compromises with the syntax because of BC or
other issues due to the engine current state/behaviors.

I would rather wait for the next major and have a proper, self
explained syntax. Even if I doubt that "_" as function name will ever
be deprecated as well, that would be my favorite. The next would be
"it", as new keyword, $formattedDates =
array_map(DateTimeImmutable::format(it, "c"), $dates);

That could give some time to send some deprecation warning for "it",
as an example. Or whatever other symbols may be chosen. Or whatever
else would be needed to have a better approach that could last for the
next decade :).

best,
--
Pierre

Hey Tim,

On 22.1.2026 10:50:26, Tim Düsterhus wrote:

Hi

Arnaud and I would like to start discussion on our RFC “Partial Function Application for instance of non-static methods ("$this")” which is intended to round-off the Partial Function Application RFC that was accepted recently:

PHP: rfc:partial_function_application_this

Best regards
Tim Düsterhus

I've been thinking about this RFC and I think it's a good addition.

I just have one question: Why "$this: $obj" and not "this: $obj"? The variable in the function is "$this". Just like "$arg", which gets passed as "arg: $value", without the extra leading dollar-sign.

(There's also no conflict, as you may not redeclare $this yourself in a non-static method.)

When I see $<varname> before the colon, I sort of expect a dynamic parameter name, but it's not.

Thanks,

Bob

Oh, I should scroll past the implementation section.

On 31.1.2026 05:21:12, Bob Weinand wrote:

Hey Tim,

On 22.1.2026 10:50:26, Tim Düsterhus wrote:

Hi

Arnaud and I would like to start discussion on our RFC “Partial Function Application for instance of non-static methods ("$this")” which is intended to round-off the Partial Function Application RFC that was accepted recently:

PHP: rfc:partial_function_application_this

Best regards
Tim Düsterhus

I've been thinking about this RFC and I think it's a good addition.

I just have one question: Why "$this: $obj" and not "this: $obj"? The variable in the function is "$this". Just like "$arg", which gets passed as "arg: $value", without the extra leading dollar-sign.

(There's also no conflict, as you may not redeclare $this yourself in a non-static method.)

When I see $<varname> before the colon, I sort of expect a dynamic parameter name, but it's not.

Thanks,

Bob

I see the rejected features section, but this is a non-argument to me, like x(...['$this' => $obj]) is just allowed the same currently.

I don't think that argument weighs strong enough.

Bob

Hi

Am 2026-01-31 05:25, schrieb Bob Weinand:

I see the rejected features section, but this is a non-argument to me, like x(...['$this' => $obj]) is just allowed the same currently.

I don't think that argument weighs strong enough.

Thank you. We didn't consider unpacking and after checking with Arnaud, it would indeed be an option to use `x(this: ?)` within the call and still allow `x(...["this" => $x])` as an escape hatch to preserve compatibility.

With regard to your comment on the PR and the “Open Issue” listed in the RFC about the name for the `$this` parameter in the resulting Closure we have two options to offer:

1. `ClassName::methodName(this: ?)` with the parameter being called `$__this`.

2. `ClassName::methodName($this: ?)` with the parameter being called `$this`.

Notably `ClassName::methodName(this: ?)` with the parameter being called `$this` is not an option, because it would result in inconsistent behavior:

`ClassName::methodName(this: ?)` semantically relies on `$this` never being a valid parameter name, such that `this: ?` can unambiguously refer to the “implicit `$this` value” for a method call. However when the parameter in the generated Closure would be called `$this`, there is some ambiguity for cases like:

      $c = DateTime::format(this: ?, format: ?);
      $c2 = $c(this: ?, format: 'c');

Is `this: ?` in the definition of `$c2` referring to the `$this` parameter of the generated Closure or is it an attempt to partially apply the `Closure` object for the `Closure::__invoke()` method that is referenced by `$c`?

Similarly allowing `this: $object` with a concrete value is explicitly disallowed, because of possible ambiguity with regard to inheritance:

      class P { public function m() { echo "P"; } }
      class C extends P { public function m() { echo "C"; } }

      // is this calling P::m() or is this calling C::m()?
      P::m(this: new C());

This would however prevent calling a partially applied instance method with named arguments:

      $c = DateTime::format(this: ?, format: ?);
      // Disallowed, because this: must be partially applied.
      $c(this: new DateTime(), format: 'c');

If the syntax to define the PFA was using `C::m($this: ?)`, `$this` in the resulting Closure would just work like any other parameter.

So this leaves `this: ?` + `$__this` and `$this: ?` + `$this`, for which Arnaud an I didn't come to a clear agreement and thus want to hold an informal poll. For you to make an educated decision, we prepared a comparison table:
                                                          ($this: ?) (this: ?)
      (1) `this: $value` remains legal (with variadics): Yes No
      (2) Unpack ambiguity: Yes Yes
      (3) Uses existing syntax / no weird name: No Yes
      (4) PFA param name is $this, not $__this: Yes No

To explain each of the points:

(1) Is referring to:

      function dump(...$args) { var_dump($args); }
      dump(this: "foo");

remaining legal without using dump(...['this' => 'test']); as a workaround.

(2) Is referring to:

      dump(...['this' => 'foo']);
      dump(...['$this' => 'foo']);

behaving differently from:

      dump(this: "foo");
      dump($this: "foo");

(3) Is referring to:

      dump($this: ?)

introducing new syntax (the leading `$`) instead of just new semantics (a special parameter referring to an object instance).

(4) Is referring to:

      $c = DateTime::format(this: ?, "c");
      $c("foo");

emitting:

      Uncaught TypeError: DateTime::{closure:pfa:test.php:3}(): Argument #1 ($__this) must be of type DateTime, string given

with the error message referring to `$__this` rather than `$this` and similarly:

      $c(__this: new DateTime());

being required when using named parameters to call the Closure is desired.

----------------

Long story short: Which of the two alternatives of

1. `ClassName::methodName(this: ?)` with the parameter being called `$__this`.

2. `ClassName::methodName($this: ?)` with the parameter being called `$this`.

Do you prefer?

Best regards
Tim Düsterhus

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.

But if there's no partialing on the method side, it could get abbreviated to:

(?)->stuff(4);

Translates to:

fn(object $__this) => $__this->stuff(4);

Because we don't need to know the type at compile time, and a method-not-found error would still happen at runtime anyway if necessary.

By that argument you wouldn't need to type the argument as `object` either (calling methods on a non-object will throw) and the comparison would become:

     $c = (?)->stuff(4);
     $c = fn($o) => $o->stuff(4);

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.

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.

Best regards
Tim Düsterhus

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’d like to search for appropriate words…

···

On 6.2.2026 21:30:11, Larry Garfield wrote:

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(?);

--Larry Garfield

Could you please not push this garbage.

It’s ugly, and just because we have a question mark, we don’t have to universally use it.

I know, PHP is the double clawed hammer and everything the nail.

That doesn’t have to apply to every aspect the language though.

No thank you,
Bob