Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:124640 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 qa.php.net (Postfix) with ESMTPS id 2C06F1A00B7 for ; Sat, 27 Jul 2024 09:41:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1722073411; bh=WvVF+YUSAU7COUNW+gVr39TpbiDCJyuBn41tPuncQTo=; h=In-Reply-To:References:Date:From:To:Subject:From; b=hCNbTQe9kL3Jf5drpvOPfA9EAziPjSaarIPEWo45DrzScruDYuDaIwGSRygHeDJax JP5lFlDbAxN9T0PeGxFvZRcENcFUekkxowI2pW/Wlf2rWUZDi/rWL3CQ0XdWMUKDRO ZjaR+roW64mwTtrNx+1dSzbtjmlnP0GmbhRyuPegAbnOdjVWhTIoJEr7a+ETrn7mDW 1rGeI1LNAXm3PYP9o/WIj0MgHiFIDw6jTXPGnCfCiOgVj43j8HI4HlssSYuw9lcy3w 4ac4qwMF1ui2WxLbIXY1I6GsIMOeVjB3PvdwgN30peQAo++dX+aMHAFYNUFGWSf5J4 NlySlnV8Mnm3w== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 6E51018007C for ; Sat, 27 Jul 2024 09:43:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) 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_MISSING,HTML_MESSAGE, RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS, SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from fhigh6-smtp.messagingengine.com (fhigh6-smtp.messagingengine.com [103.168.172.157]) (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 ; Sat, 27 Jul 2024 09:43:29 +0000 (UTC) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailfhigh.nyi.internal (Postfix) with ESMTP id 55A5B1140255 for ; Sat, 27 Jul 2024 05:41:52 -0400 (EDT) Received: from imap49 ([10.202.2.99]) by compute3.internal (MEProxy); Sat, 27 Jul 2024 05:41:52 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm1; t=1722073312; x=1722159712; bh=DCl/48ZO2u l4z/+1YX3OaKbXESi1lAkn6XgBM96KRvw=; b=sciYJ4MPwLB/g5TU489Q+niq1i 4TDE+8uRP/X+POhHuY32nMe9hu4C0n4A570btZg0pNSxpGWRu8KVngflULEfaGib NP/wzlCgmFRaHVjBUpwAhS0tKznQ5fVzzn30+OXG2X4CM/3tXF9+Um1kV8kqz2du y5fFgaOnDeSQ6kB/rS4tTKvbFVJ9DkVO6BiKZHo+ODww1Oh8OIviwwJc6Ju6YDmd cwOXquRW96WvGJNk3HU7y0aOnixm2JN0BnnIctkd5kreXuZvkWD8rfyPwKPowT1Z PNwUCoBqunqNTyssuKgdFiEggK62UgWr59I67d420K8Gm70CljTWX3vzXidA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; t=1722073312; x=1722159712; bh=DCl/48ZO2ul4z/+1YX3OaKbXESi1 lAkn6XgBM96KRvw=; b=QkDhG2FLLy0mNUgnTziRqKLKRxYA8FE7lLP9pcU95vod abAjrBpVaSt0G88ldW7JNGyUDkqSgrN8vX0w80w5IJ62Rj96QlGgmMWOSGsY6DcR 72HArII6DLMfF41sxGQiR1SmhH8r2vNVGZ4zpls61bYIkk/tX3cBaCbUjwoXU3fh cLcvquapBJEzO8RNsVbnHvzzpj5mdED50nPXaq3SOgl6PSCPYXNMsiGrbFOOJ8H1 lrSLVRCUbSicezOPnd4tkqE7L0GwI/ZwXo4aSlya3RaFTreV7HGXfPipKD694ve9 wwSxvLNRPEuBmOGUSB0GvdP9+XOvFWyiuBtUCyMCeg== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrieejgddulecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecunecujfgurhepofgfggfkjghffffhvffutgesrgdtre erreerjeenucfhrhhomhepfdftohgsucfnrghnuggvrhhsfdcuoehrohgssegsohhtthhl vggurdgtohguvghsqeenucggtffrrghtthgvrhhnpeekfeefteffgefffedtteeuuedvie euvdejffdvgeeuveelhfefueejieejkefhgeenucffohhmrghinhepphgrtghkrghgihhs thdrohhrghenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhroh hmpehrohgssegsohhtthhlvggurdgtohguvghspdhnsggprhgtphhtthhopedt X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id DAA8515A0092; Sat, 27 Jul 2024 05:41:51 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.11.0-alpha0-582-g5a02f8850-fm-20240719.002-g5a02f885 Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Message-ID: In-Reply-To: References: Date: Sat, 27 Jul 2024 11:41:30 +0200 To: internals@lists.php.net Subject: Re: [PHP-DEV] Explicit callee defaults Content-Type: multipart/alternative; boundary=afd720e7e05c497d883128f81714e9e5 From: rob@bottled.codes ("Rob Landers") --afd720e7e05c497d883128f81714e9e5 Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable On Fri, Jul 26, 2024, at 23:54, Bilge wrote: > Hi Internals, >=20 > New RFC idea just dropped. When writing a function, we can specify def= aults for its parameters, and when calling a function we can leverage th= ose defaults *implicitly* by not specifying those arguments or by "jumpi= ng over" some of them using named parameters. However, we cannot *explic= itly* use the defaults. But why would we want to? >=20 > Sometimes we want to effectively *inherit* the defaults of a function = we're essentially just proxying. One way to do that is copy and paste th= e entire method signature, but if the defaults of the proxied method cha= nge, we're now overriding them with our own, which is not what we wanted= to do. It is possible, in a roundabout way, to avoid specifying the opt= ional parameters by filtering them out (as shown in the next example). T= he final possibility is to use reflection and literally query the defaul= t value for each optional parameter, which is the most awkward and verbo= se way to inherit defaults. >=20 > Let's use a concrete example for clarity. >=20 > function query(string $sql, int $limit =3D PHP_INT_MAX, int $offset =3D= 0); >=20 >=20 >=20 > function myQuery(string $sql, ?int $limit =3D null, ?int $offset =3D n= ull) { > query(...array_filter(func_get_args(), fn ($arg) =3D> $arg !=3D=3D= null)); > } >=20 >=20 > In this way we are able to filter out the null arguments to inherit th= e callee defaults, but this code is quite ugly. Moreover, it makes the (= sometimes invalid) assumption that we're able to use `null` for all the = optional arguments. >=20 > In my new proposal for *explicit *callee defaults, it would be possibl= e to use the `default` keyword to expressly use the default value of the= callee in that argument position. For example, the above implementation= for myQuery() could be simplified to the following. >=20 >=20 >=20 > function myQuery(string $sql, ?int $limit =3D null, ?int $offset =3D n= ull) { > query($sql, $limit ?? default, $offset ?? default); > } >=20 >=20 > Furthermore, it would also be possible to "jump over" optional paramet= ers *without* using named parameters. >=20 > json_decode($json, true, default, JSON_THROW_ON_ERROR); >=20 > This proposal is built on the assumption that it is possible to specif= y that PHP should only accept the `default` expression in method and fun= ction call contexts. For example, it would not be valid to return `defau= lt` from a function and substitute it that way; my proposal is to only p= ermit `default` in literal function calling contexts. My knowledge of in= ternals is insufficient (read: non-existent) to know whether or not this= restriction is possible to implement, but if it is, I think this is a g= ood idea. What do you think? >=20 >=20 >=20 > Cheers, > Bilge >=20 >=20 This seems like a case for code generation =E2=80=94 and an RFC that pro= vides hooks for code generation would probably be better IMHO. There are a couple of neat tools out there doing this and hooking into c= omposer, like https://packagist.org/packages/olvlvl/composer-attribute-c= ollector There are many things that could benefit from this, such as DI container= s, scanning for attributes, generating efficient serializers/deserialize= rs, etc.=20 =E2=80=94 Rob --afd720e7e05c497d883128f81714e9e5 Content-Type: text/html;charset=utf-8 Content-Transfer-Encoding: quoted-printable

=

On Fri, Jul 26, 2024, at 23:54, Bilge wrote:

Hi Internals,

New RFC idea just dropped. When writing a function, we can specify defaults for its parameters, and when calling a function we can leverage those defaults implicitly by not specifying those arguments or by "jumping over" some of them using named parameters. However, we cannot explicitly use the defaults. But why would we want to?

Sometimes we want to= effectively inherit the defaults of a function we're essentially just proxying. One way to do that is copy and paste the entire method signature, but if the defaults of the proxied method change, we're now overriding them with our own, which is not what we wanted to do. It is possible, in a roundabout way, to avoid specifying the optional parameters by filtering them out (as shown in the next example). The final possibility is to use reflection and literally query the default value for each optional parameter, which is the most awkward and verbose way to inherit defaults.

Let's use a concrete example for clari= ty.

function query(string $sql, int $limit =3D PHP_INT_MAX, in= t $offset =3D 0);


function myQuery(string $sql, ?int = $limit =3D null, ?int $offset =3D null) {
    query(...array_filter(fun= c_get_args(), fn ($arg) =3D> $arg !=3D=3D null));
}


In this way= we are able to filter out the null arguments to inherit the callee defaults, but this code is quite ugly. Moreover, it makes the (sometimes invalid) assumption that we're able to use `null` for all the optional arguments.

In my= new proposal for explicit callee defaults, it would be possible to use the `default` keyword to expressly use the default value of the callee in that argument position. For example, the above implementation for myQuery() could be simplified to the following.


function myQue= ry(string $sql, ?int $limit =3D null, ?int $offset =3D null) {
    query($sql, $limit ?? def= ault, $offset ?? default);
}


Furthe= rmore, it would also be possible to "jump over" optional parameters without using named parameters.

json_d= ecode($json, true, default, JSON_THROW_ON_ERROR);

This proposa= l is built on the assumption that it is possible to specify that PHP should only accept the `default` expression in method and function call contexts. For example, it would not be valid to return `default` from a function and substitute it that way; my proposal is to only permit `default` in literal function calling contexts. My knowledge of internals is insufficient (read: non-existent) to know whether or not this restriction is possible to implement, but if it is, I think this is a good idea. What do you think?


Cheers,
Bilge
<= /div>



This seems like a case = for code generation =E2=80=94 and an RFC that provides hooks for code ge= neration would probably be better IMHO.

The= re are a couple of neat tools out there doing this and hooking into comp= oser, like https://packagist.org/packages/olvlvl/composer-at= tribute-collector

There are many things= that could benefit from this, such as DI containers, scanning for attri= butes, generating efficient serializers/deserializers, etc. 
<= div>
=E2=80=94 Rob
--afd720e7e05c497d883128f81714e9e5--