Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130041 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 89CB21A00BC for ; Fri, 6 Feb 2026 23:22:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1770420125; bh=AV7sETWm/QlO+j2rXxQ17LjnZWK09Scgrf7I846vMTM=; h=Date:To:From:Cc:Subject:In-Reply-To:References:From; b=clcsEigqnz28vBzt4aw2k9F4H66hGlkxcT8YZBwMTgL77/ede1fZ92gvBzKChrEo5 x+cdcYrAOgtOOkv/gjJlTUCGe9Xy3WlWcwu8Gqpe2+VR9Wjd60yI6WNZ4IPx8Q12ec ZPWrtmBGDh2IEzBkfr84L7TbovOrUz7EKNb0eQanY8G6Zorix94FyqujuXikRxIJQ2 2kQVjGyYgMKpG6WbjSixO1sYVIYJIYRTPjqJxvSE3NTe2YURKJ1JL0kS1eG9gj6tP9 pRTIsJ5mUMIAt/AH6IdRsvjoHugW0t1dDVvm337cdFCKeJ6shAWbWZAUWc4wiUQS0U Bby/Lmv9WxrHA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 1EDD118003B for ; Fri, 6 Feb 2026 23:22:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-0.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,RCVD_IN_DNSWL_LOW, SPF_HELO_PASS,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-10627.protonmail.ch (mail-10627.protonmail.ch [79.135.106.27]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Fri, 6 Feb 2026 23:22:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rochette.cc; s=protonmail; t=1770420115; x=1770679315; bh=KYpNH0UrJpGFx+fSztDAMlJDd/In6R/fy4iFCJjblKQ=; h=Date:To:From:Cc:Subject:Message-ID:In-Reply-To:References: Feedback-ID:From:To:Cc:Date:Subject:Reply-To:Feedback-ID: Message-ID:BIMI-Selector; b=RYvYEXcnpqKCMuPOeaqNtm+0LGsASOr2Px6e8EbbC4sK6bek5pnCJyjciI8pJCB0A Ev+yAfvjeFaauoNfF4crg3dpINvZwu2IqHCpEiMruLpNEsQvSQGgBwD3f7Bc3/AMl+ IRUyiXtLKpKNOv7gohZappFD77cYNd/4SORpMk0muEhbxGUoY9MqxuFSTw4Lcv5csL 0FHj+5MFaAluWEMHkh8m31f/kusVlAjlfEP4qs86tgGwtNmKjLpDCZWXIth8PFjH5e o6CKJnOT3Gia14V/Uq07Vj4RPIEAnw30v/n/ekneP3xP2t7qxqvoUkHY8IW8wBjXtj L1VXfhfQIl/qA== Date: Fri, 06 Feb 2026 23:21:50 +0000 To: Larry Garfield Cc: php internals Subject: Re: [PHP-DEV] [RFC] Partial Function Application for instance of non-static methods ("$this") Message-ID: In-Reply-To: References: <64953ec741a4c6609519e1878ad37b54@bastelstu.be> <253ee811-0c1d-7eab-4c36-38607401aaf6@php.net> <28461544eb11b41dce7c7563ad879e63@bastelstu.be> <62a90f31-697b-4607-a1ba-67956f5adfac@app.fastmail.com> <5c6ff4c3-8a1b-4b4a-8c1a-0acbb7b1cae2@bastelstu.be> Feedback-ID: 37040780:user:proton X-Pm-Message-ID: c351ff489e4db118a48b4946320fbee790678971 Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 Content-Type: multipart/signed; protocol="application/pgp-signature"; micalg=pgp-sha512; boundary="------1077a96769dba3e6aba0b167683f0e63d6e09bb481b70b1924300bc947bb3c90"; charset=utf-8 From: mathieu@rochette.cc (Mathieu Rochette) This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --------1077a96769dba3e6aba0b167683f0e63d6e09bb481b70b1924300bc947bb3c90 Content-Type: multipart/mixed;boundary=---------------------0f2e5f537e343abf20c225b082ccdb87 -----------------------0f2e5f537e343abf20c225b082ccdb87 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain;charset=utf-8 On Friday, February 6th, 2026 at 21:32, Larry Garfield wrote: > On Fri, Feb 6, 2026, at 10:43 AM, Tim D=C3=BCsterhus 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 =E2=80=9C= just > > write a Closure=E2=80=9D. 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 approac= h you'd still be able to reorder the method params, just keep the object a= s first arg. > = > >> That would then be a lot easier to write in cases where you're just d= ropping 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 > > =E2=80=9Cfunction handle=E2=80=9D, that's why the examples are ones wh= ere the resulting > > Closure is passed as a parameter to another function. > > > > Within a pipe chain you would just use the regular `->` operator on th= e > > result of the previous step: > > > > $result =3D (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 usefu= l 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 i= nvoke. So there's no need to think about reordering the params in the fir= st 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-s= tatic methods. > = > --Larry Garfield > = I find the `(Test ?)->method()` suggestion quite nice. For 2 reasons, it l= ooks similar to a function argument ("Type $arg"), and following that, giv= en that the type is optional for function arguments, it could also be opti= onal here to have `(?)->method()` or even `?->method()` as a shortcut. = I understand it means some optimization cannot be done, but in a lot of ca= se it doesn't matter, and if I have to write `DateTimeImmutable::format($t= his: ?, 'c')` vs `fn ($dt) =3D> $dt->format('c')`. The only benefit would = be the optimization. so if I don't care about that I'm still going to go f= or 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 t= he use cases --- That said, regarding your 2 suggestions, Tim, and after reading your expla= nations, 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 g= enerated function (with something like "__this" being the default if omitt= ed) 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 wor= se, 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 -----------------------0f2e5f537e343abf20c225b082ccdb87 Content-Type: application/pgp-keys; filename="publickey - mathieu@rochette.cc - 0x8D30BA0E.asc"; name="publickey - mathieu@rochette.cc - 0x8D30BA0E.asc" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="publickey - mathieu@rochette.cc - 0x8D30BA0E.asc"; name="publickey - mathieu@rochette.cc - 0x8D30BA0E.asc" LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCgp4ak1FWVFLZkNoWUpLd1lCQkFI YVJ3OEJBUWRBa1BDZHlabHI5bmZBMHdJcUJXSGl6dnRQNTQ5MTFQWDgKdkowcGp4T0JabHJOS1cx aGRHaHBaWFZBY205amFHVjBkR1V1WTJNZ1BHMWhkR2hwWlhWQWNtOWphR1YwCmRHVXVZMk0rd284 RUVCWUtBQ0FGQW1FQ253b0dDd2tIQ0FNQ0JCVUlDZ0lFRmdJQkFBSVpBUUliQXdJZQpBUUFoQ1JE SWdrVGc3MTk3UnhZaEJJMHd1ZzZMaWxERVUvYVBPY2lDUk9EdlgzdEh1Z29CQUtTcFdzNmcKWVdh bUU5Wkc5WGV5V2VxQVFLUnZwaUtJdnNoQzRlckNvNVVEQVA5VGNHMW5rWERiYTlIOTRpM2Y4Q3ZY CkZhK2kxM1ljTktUZU55ZllaUFFnQmM0NEJHRUNud29TQ2lzR0FRUUJsMVVCQlFFQkIwQ0hrOFBU dWJOMQpkR0Z6WjlscFVKYW5KbjA1RDJmaUhZOGY1N3QzeGxheUlnTUJDQWZDZUFRWUZnZ0FDUVVD WVFLZkNnSWIKREFBaENSRElna1RnNzE5N1J4WWhCSTB3dWc2TGlsREVVL2FQT2NpQ1JPRHZYM3RI dGNBQS8xWlNrVFVKCkU1TzU4bUR5VTNSeFFyVjNVQVA3U3BaamN1T0pKSTRTRzE5TUFQOXlIU3Rq dDJXa3IxS0o5c0VNeXY5aQprb0xNS2VZa3Q5RXlyUFM5bDdsUkRnPT0KPTNIZE8KLS0tLS1FTkQg UEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLQo= -----------------------0f2e5f537e343abf20c225b082ccdb87-- --------1077a96769dba3e6aba0b167683f0e63d6e09bb481b70b1924300bc947bb3c90 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: ProtonMail wrsEARYKAG0FgmmGd4YJEMiCRODvX3tHRRQAAAAAABwAIHNhbHRAbm90YXRp b25zLm9wZW5wZ3Bqcy5vcmfa9ZldLgANG9UEdlmhNnkN4A7a4hhEyiDv369U NC+PFRYhBI0wug6LilDEU/aPOciCRODvX3tHAAAWOAD/fXqvudBT0q4r8jcJ iq4+xfzU0r5ecPtWlk6xU5TaHxkBAPoLIbMKHVd0NV295PkL8NgvNLjKJf4n Xhy1nTzlvfgG =p7Tm -----END PGP SIGNATURE----- --------1077a96769dba3e6aba0b167683f0e63d6e09bb481b70b1924300bc947bb3c90--