Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125302 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 D6C9F1A00BD for ; Tue, 27 Aug 2024 04:20:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1724732549; bh=phfLNHvZ8JPua53YxpzC0/wau4O8ypOBT9sk73wBbgY=; h=Date:From:To:Cc:In-Reply-To:References:Subject:From; b=bJvp/tIjzOdijWFEX0RbfVaCFplWbf0UC7w+GBeqrjssmwFTpzZSl7IQvgkl/Zu99 KD8xAjBUBc9qoRgUbapcff1tXl56N7OeTRabY96UTNLMCfVBpJzbkVVzC71d1pRyF0 1tRkoql3KogVO1BN0NQV3iQsLqi1KVdR+AG6rigTDCFgTvlWDv42OdQScmGzCYpiBo EVpoAv2rCFXtvUDmfGhB7apKYPLfAQmc68T7ZGe33Z0ktMVIw5sEDxQSC/t1l38PUt UstG1IxdKawfU+L1nj1/w0beQ2njqdez1tYc0Z/SRPxPPq2Z006Usjt5Hj1ha6IY0b 5HLkHq0NsN+ag== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 9AC3F18007E for ; Tue, 27 Aug 2024 04:22:28 +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=4.1 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DMARC_MISSING,HEADER_FROM_DIFFERENT_DOMAINS,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,RCVD_IN_SBL_CSS,SPF_HELO_NONE, SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-yw1-f182.google.com (mail-yw1-f182.google.com [209.85.128.182]) (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 ; Tue, 27 Aug 2024 04:22:28 +0000 (UTC) Received: by mail-yw1-f182.google.com with SMTP id 00721157ae682-6ca1d6f549eso23190187b3.0 for ; Mon, 26 Aug 2024 21:20:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=coggenterprises-com.20230601.gappssmtp.com; s=20230601; t=1724732434; x=1725337234; darn=lists.php.net; h=mime-version:subject:references:in-reply-to:message-id:cc:to:from :date:from:to:cc:subject:date:message-id:reply-to; bh=phfLNHvZ8JPua53YxpzC0/wau4O8ypOBT9sk73wBbgY=; b=H422PScJjm1wJaU7FgP40RSeAbuaOwfKaNOst6CZqMhSSu0LmuZ5gg8/RiBkF5rxTE dck/HaPT/LFbXlIBQNqkR2dWQ9S7l1hnGQt2pxkB3tO+aGi5l7K1QCAID7MML1zZ/dkT cdmZx8TVmmBprDoPVYdUwXrBHDnCCQNPGLFH1DK5jOL0rYrhnSefsfdZHaFezr7zbQmi GGKPUJXERxD0O7wrfcowhNm93X3B7oKnMTdgZbff1JG54GWiH0XJzFdBLraNNLcdRv88 tE0cm1q1AJ9fgYa9WSQmL5SwwxXTfqrm3JAxvIVfN4TsLCqPBTo31f2VzPIaJtjyCucK UyTA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724732434; x=1725337234; h=mime-version:subject:references:in-reply-to:message-id:cc:to:from :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=phfLNHvZ8JPua53YxpzC0/wau4O8ypOBT9sk73wBbgY=; b=iFtE8goGZCRlRxq2YzOZ02DIJZfbCrI8Gn/iSMz4xxA0f3vp6S1gndLs/fpsN8LaSJ EQ9VcmKxLXrOHxI3Ir+wzT+z+aObiFPdNo+YwrpRhkdPu6M2DH8HeNuXKdprLwseOfcq iCeV5sytIGKko7/FVlSJJDjXIgnIw4D9j6NaNcCE2/YNnbhwYg3GMZfnq0BLdHoNy3+t M7HDoACugrGCrOyuFlW474YadtcG50O0rqjsrRkYUJK26sAforuqNjz4Tc/59ojGj8lf tmiJvG6NAm0O+jVOQ87U9Yf6arhJcLs8UBetuYNzFn/FKLgxja5BErqJvVWkoKDWA86q 8TEg== X-Forwarded-Encrypted: i=1; AJvYcCUW0i7k7pEyenZTrSaWe57HGCNYTFfN+99TzkHvctGJTSo7MPmftJfXiFyQuoeoDbAW5OjBw+8smso=@lists.php.net X-Gm-Message-State: AOJu0YyaU7RkgShM5lZJsyDDbB02k8BBoU527XFWyOq9UE1BbfHGNrFh tcU05eg+cznfQIpcKo7NEaOq1VZoPxSYUnuvsmwHc94j58WJTET+sndQlhZ0VhQ= X-Google-Smtp-Source: AGHT+IH90mbPRpujj7M+ea7eSQKKJ1hW6Pp5e+L2lxmEdEIgyRsi7YvK99IXdZw6N2Tj56FUgc64vg== X-Received: by 2002:a05:690c:48c7:b0:6b2:1b65:4c05 with SMTP id 00721157ae682-6cfb9eb9cc7mr17260507b3.17.1724732434072; Mon, 26 Aug 2024 21:20:34 -0700 (PDT) Received: from Johns-MacBook-Pro-2.local ([207.213.210.67]) by smtp.gmail.com with ESMTPSA id 00721157ae682-6c39df360dbsm17821157b3.112.2024.08.26.21.20.32 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Aug 2024 21:20:33 -0700 (PDT) Date: Tue, 27 Aug 2024 00:20:32 -0400 To: Matthew Weier O'Phinney Cc: Larry Garfield , php internals Message-ID: In-Reply-To: References: Subject: Re: [PHP-DEV] [RFC] Default expression X-Mailer: Mailspring Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="66cd5410_19495cff_12a23" From: john@coggeshall.org (John Coggeshall) --66cd5410_19495cff_12a23 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline On Aug 26 2024, at 5:27 pm, Matthew Weier O'Phinney wrote: > You'll likely identify the increased delay in such cases. Generally speaking these sorts of default values don't change a ton, but it's not unlikely that you may say "I'd like half that delay" or "twice that delay". But a better example would be introducing a backoff, which might look like this: > > > for ($i = 1; $i += 1 ; $i < 4) { > $result = call_some_client($url, default * $i); > if ($result->isSuccess()) { > break; > } > } > > This could, I'm sure you agree, be easily done without access to the default timeout. In fact, the default timeout itself is entirely unnecessary to know... And I know you and I both know that most default timeouts are ridiculously oversized anyway (e.g. 30, 60 sec) for real-world production environments. :) > In other words, you know that you want it to use the default, and then allow an increasing timeout duration between calls if it fails. For this, I don't necessarily want or need to know what the default is, only that I want to do _multiples_ of it in specific cases. > Is it a universally good idea? No. Does it have use cases? Yes. Putting aside timeouts being a bad example here IMO because almost all default timeout values are unreasonably high, I simply don't think the use cases that are "good" come anywhere near the potential for abuse -- especially when it comes to default being an object or other complex type. > > - decorating a default instance (e.g. to lazily create a proxy without knowing the default implementation used for an argument hinted against an interface) > This is exactly the usage I'm highlighted as problematic in my code example. You're introducing a new worry for the upstream API developer that doesn't need to exist, and violating a separation principle that has existed in PHP since default parameters were created 25+ years ago. > How exactly is this worrisome? Consider this: > class A { > public function __construct(private LogInterface $logger = new DefaultLogger()) { } > } > class ProxiedLogger implements LogInterface { ... } > $a = new A(new ProxyLogger(default)); > If class A is programming to the `LogInterface` contract, the fact that it gets a proxied version of the default should not matter in the least. Being able to proxy like this means that a _consumer_ of class A does not need to know or care what the default implementation is; they can assume it follows the same contract, and proxy to it regardless. The upstream developer doesn't need to care, because they are programming to the interface, not the implementation. This doesn't violate the separation of concerns principle, nor covariance. This example isn't worrisome. This one is (which I posted earlier in the thread). This patch creates a whole new BC issue for upstream APIs that callers use when they (ab)use default : https://gist.github.com/coogle/7c0fbb750288ebdd1feb8a5e9185ba8c In this Gist where before I didn't have to worry about changing the default value breaking downstream code (as long as the signature didn't change), I now do have to worry about changing the default value. This was an intentionally made example using strong typing, its even worse if the type is mixed. > If this feature is released with an overly broad scope in terms of expressions, etc. it's not like we can take it back at that point because now people are using it in unknown ways. It is not one I'm comfortable with a "let's move forward and see what happens" approach. > I didn't say that at all. I said we should identify the ones we absolutely know will be problematic, and restrict those from the outset. From there, we should identify the ones that _might_ be problematic, and determine on a case by case basis if the risks outweigh the use cases before Bilge brings it to a vote. The impression I've been getting from the conversations in this RFC is that there is no appetite for restrictions from Bilge or the supporters of the RFC. In fact Bilge said himself " there is no good reason, in my mind, to ever prohibit the expressiveness." https://externals.io/message/125183#125217 So taking them at their word, it seems like that conversation is off the table. The RFC based on this thread is an up or down vote on full-fledged expressiveness, or nothing based on what I'm reading and I certainly won't be supporting that personally. > But if we lock it down too tightly from the outset, expanding it, while being possible, will more than likely mean an RFC for every expansion, because it's unlikely somebody will do anything comprehensive towards opening it up in the future. I'd rather not leave some of these use cases as a TBD for a later RFC, because that's very likely going to mean "never". > I DO think there are likely whole categories of expressions we can likely say "no" to - anything where the default represents a union type (and _mixed_ is a union type) should likely only allow default by itself or as a bare value on the RHS of an expression. I think you and I are saying the same thing here - the expressions need to be restricted. I 100% do think we would need to get into specifics as to which bucket (yes/no/maybe) though before I'd say we totally agree :) I can say I 100% agree that union types including mixed need to be out of this equation per my code example above. This RFC and the follow-on discussion has made explicitly clear, however, that's not a compromise the author(s) / advocate(s) are willing to entertain. > The argument against the feature that it expands the public API is puzzling to me, particularly when the only other solutions are (a) Reflection, or (b) named arguments. Named arguments _are_ part of the public API, as the names themselves can change. Default values can change, but, importantly, a change in a default value does not change the actual signature of a function. Giving the ability to use `default` gives consumers of a function a far more stable API surface, particularly when they do not want to change a given default value, but _do_ want to provide a more specific value for a later argument. Right now, if not using named arguments (e.g., because you're worried the argument name could change), your only other option is to use the Reflection API, which is more expensive, introduces a whole set of other possible runtime issues, and is far more convoluted to achieve. I would argue the convolution is a feature, not a bug. The code example I provided in the gist above explains why I think it's an expansion of access into the API signature (specifically with union types). I of course concede named parameters also were an expansion of access into the API signature. These two things are not the same thing though in any other regard -- one had very clear wins and benefits (named parameters), this one feels more like syntax sugar that can be easily abused if left as a free-ranging expression. > Had this been only to allow the `default` keyword, I don't think we'd be having this discussion at all; I think it would be pretty self-evident that there's a need, and a lot of folks would be happy to sign on. I agree. > But the author took it a step further, and asked, "What if ...?", and as such, the RFC provides additional benefits beyond giving you a keyword for using the default value, as it expands to allowing expressions. This gives a tremendous amount of flexibility and power, and solves some additional issues some of us have noticed. and now there is a judgement call being made between these "additional benefits" (and I 100% concede there is an upside), and the costs. As presented IMO we've fallen far short of that being a winning proposition for PHP in part because it provides so much flexibility and power it starts feeling akin to introducing a new syntax to access private members of objects from outside those objects. Again, the issue being it is being proposed as a first-class citizen in terms of expression usage. > So I'd argue that what we need to weigh now is which of these expressions are truly benefits, which ones are side effects we can live with, and which will raise new problems we do not want to deal with. > But let's not just say "no expressions" - I think there's been some demonstrated value from a lot of these. Honest to god I don't think I've read from one person to come out and say "no expressions". I've personally made a number of suggestions on expression limitations that may or may not be a good idea, such as: https://externals.io/message/125183#125237 The problem is the RFC author has stated multiple times in their view that the expressions supported must be exhaustive and hasn't be willing to hear valid concerns to that. Coogle --66cd5410_19495cff_12a23 Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline

On Aug 26 2024, at= 5:27 pm, Matthew Weier O'Phinney <mweierophinney=40gmail.com> wrot= e:
You'll likely identify the increased d= elay in such cases. Generally speaking these sorts of default values don'= t change a ton, but it's not unlikely that you may say =22I'd like half t= hat delay=22 or =22twice that delay=22. But a better example would be int= roducing a backoff, which might look like this:

    for (=24i =3D 1; =24i&= nbsp;+=3D 1 ; =24i < 4) =7B
        =24r= esult =3D call=5Fsome=5Fclient(=24url, default * =24i);
  =       if (=24result->isSuccess()) =7B
  =           break;
      =   =7D
    =7D

This could, I'm sure you agree= , be easily  done without access to the default timeout. In= fact, the default timeout itself is entirely unnecessary to know... And = I know you and I both know that most default timeouts are ridiculously ov= ersized anyway (e.g. 30, 60 sec) for real-world production environments. = :) 

=
In other words, you know that you want it to use the default,= and then allow an increasing timeout duration between calls if it fails.= =46or this, I don't necessarily want or need to know what the default is= , only that I want to do =5Fmultiples=5F of it in specific cases.
Is it a universally = good idea=3F No. Does it have use cases=3F Yes.

Putt= ing aside timeouts being a bad example here IMO because almost all defaul= t timeout values are unreasonably high, I simply don't think the use case= s that are =22good=22 come anywhere near the potential for abuse -- e= specially  when it comes to default  being an= object or other complex type.

- decorating a default instance (e.g. to lazily create a proxy wit= hout knowing the default implementation used for an argument hinted again= st an interface)

This is exactly the usage I'm highl= ighted as problematic in my code example. You're introducing a new worry = for the upstream API developer that doesn't need to exist, and violating = a separation principle that has existed in PHP since default parameters w= ere created 25+ years ago.

How exactly is this worrisome=3F Consider this:
    class A =7B
        public function =5F=5Fconstr= uct(private LogInterface =24logger =3D new DefaultLogger()) =7B =7D
    =7D
    class ProxiedLogger implements LogI= nterface =7B ... =7D
    =24a =3D new A(new ProxyLogger(default));
If class A is programm= ing to the =60LogInterface=60 contract, the fact that it gets a proxied v= ersion of the default should not matter in the least. Being able to proxy= like this means that a =5Fconsumer=5F of class A does not need to know o= r care what the default implementation is; they can assume it follows the= same contract, and proxy to it regardless. The upstream developer doesn'= t need to care, because they are programming to the interface, not the im= plementation. This doesn't violate the separation of concerns principle, = nor covariance.

This example isn't worrisome. This o= ne is (which I posted earlier in the thread). This patch creates a whole = new BC issue for upstream APIs that callers use when they (ab)use d= efault :

In this Gist wher= e before I didn't have to worry about changing the default value breaking= downstream code (as long as the signature didn't change), I now do have = to worry about changing the default value. This was an intentionally made= example using strong typing, its even worse if the type is mixed.<= /code>

    
= If this feature is released with an overly broad scope in terms of expres= sions, etc. it's not like we can take it back at that point because now p= eople are using it in unknown ways. It is not one I'm comfortable with a = =22let's move forward and see what happens=22 approach.
=

I didn't say that at all. I said = we should identify the ones we absolutely know will be problematic, and r= estrict those from the outset. =46rom there, we should identify the ones = that =5Fmight=5F be problematic, and determine on a case by case basis if= the risks outweigh the use cases before Bilge brings it to a vote.
The impression I've been getting from the conversations i= n this R=46C is that there is no appetite for restrictions from Bilge or = the supporters of the R=46C. In fact Bilge said himself =22 there is no g= ood reason, in my mind, to ever prohibit the expressiveness.=22

So taking them at their word, it= seems like that conversation is off the table. The R=46C based on this t= hread is an up or down vote on full-fledged expressiveness, or nothing ba= sed on what I'm reading and I certainly won't be supporting that personal= ly.

But if we lock it down too tightly fr= om the outset, expanding it, while being possible, will more than likely = mean an R=46C for every expansion, because it's unlikely somebody will do= anything comprehensive towards opening it up in the future. I'd rather n= ot leave some of these use cases as a TBD for a later R=46C, because that= 's very likely going to mean =22never=22.
I DO think there are likely whole categories= of expressions we can likely say =22no=22 to - anything where the defaul= t represents a union type (and =5Fmixed=5F is a union type) should likely= only allow default by itself or as a bare value on the RHS of an express= ion.

I think you and I are saying the same thing her= e - the expressions need to be restricted. I 100% do think we would need = to get into specifics as to which bucket (yes/no/maybe) though before I'd= say we totally agree :) = ;I can say I 100% agree that union types including mixed need to be out o= f this equation per my code example above. This R=46C and the follow-on d= iscussion has made explicitly clear, however, that's not a compromise the= author(s) / advocate(s) are willing to entertain.

The argument against the feature that it expands the publi= c API is puzzling to me, particularly when the only other solutions are (= a) Reflection, or (b) named arguments. Named arguments =5Fare=5F part of = the public API, as the names themselves can change. Default values can ch= ange, but, importantly, a change in a default value does not change the a= ctual signature of a function. Giving the ability to use =60default=60 gi= ves consumers of a function a far more stable API surface, particularly w= hen they do not want to change a given default value, but =5Fdo=5F want t= o provide a more specific value for a later argument. Right now, if not u= sing named arguments (e.g., because you're worried the argument name coul= d change), your only other option is to use the Reflection API, which is = more expensive, introduces a whole set of other possible runtime issues, = and is far more convoluted to achieve.

I would argue= the convolution is a feature, not a bug. The code example I provided in = the gist above explains why I think it's an expansion of access into the = API signature (specifically with union types). I of course concede named = parameters also were an expansion of access into the API signature. These= two things are not the same thing though in any other regard -- one had = very clear wins and benefits (named parameters), this one feels more like= syntax sugar that can be easily abused if left as a free-ranging express= ion.

Had this been only to allow th= e =60default=60 keyword, I don't think we'd be having this discussion at = all; I think it would be pretty self-evident that there's a need, and a l= ot of folks would be happy to sign on.

I agree.

But the author took it a step further, and as= ked, =22What if ...=3F=22, and as such, the R=46C provides additional ben= efits beyond giving you a keyword for using the default value, as it expa= nds to allowing expressions. This gives a tremendous amount of flexibilit= y and power, and solves some additional issues some of us have noticed.
and now there is a judgement call being made between = these =22additional benefits=22 (and I 100% concede there is an upside), = and the costs. As presented IMO we've fallen far short of that being a wi= nning proposition for PHP in part because it provides so much flexibility= and power it starts feeling akin to introducing a new syntax to access p= rivate members of objects from outside those objects. Again, the issue be= ing it is being proposed as a first-class citizen in terms of expression = usage.

So I'd argue that what we need to = weigh now is which of these expressions are truly benefits, which ones ar= e side effects we can live with, and which will raise new problems we do = not want to deal with.

But let's n= ot just say =22no expressions=22 - I think there's been some demonstrated= value from a lot of these.

Honest to god I don't th= ink I've read from one person to come out and say =22no expressions=22. I= 've personally made a number of suggestions on expression limitations tha= t may or may not be a good idea, such as:

The problem is the R=46C author has stated multiple t= imes in their view that the expressions supported must be exhaustive and = hasn't be willing to hear valid concerns to that.

Coogle
--66cd5410_19495cff_12a23--