Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:124015 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 612D31A009C for ; Sat, 29 Jun 2024 09:05:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1719652027; bh=wZDh7DX8dfZsL3HHUcYl1pHvIqrwLR9ipVI8seq4dt0=; h=In-Reply-To:References:Date:From:To:Cc:Subject:From; b=fhrbDYU67ERoUOylTJzeMASV7dpMxbF+o+hs6430JSSRUd/PcRcEXZsVNcQQkxG70 pcad6YStEqZ8YDqo/TlGQgbYLHJlSt9xvtxIUCRz+VYvA47WvpLv6lNJvulJPC5Y6O RJT2s+3kMZfJCA5jXvwLUoqPslWLypOcMvpeRGHI0LuSfo7JMc3YfXilfOg5reHQ8j vJW5tnfSebFEk78Ibw9V1K95w1+aXl0akHBCikIA3ww7AyqAwAyzW136t22kf3Pvpn VWQVqXxBvNXwznTseAoLQDsphTnvXTzanHUtfbZSY/V4pvTTiz82FNWPBElqbWKt76 LvW6Dx15nU4Uw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 2D6FC18059E for ; Sat, 29 Jun 2024 09:07:04 +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,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) 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)) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sat, 29 Jun 2024 09:07:01 +0000 (UTC) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailfhigh.nyi.internal (Postfix) with ESMTP id E2E831140285; Sat, 29 Jun 2024 05:05:41 -0400 (EDT) Received: from imap49 ([10.202.2.99]) by compute1.internal (MEProxy); Sat, 29 Jun 2024 05:05:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bottled.codes; h=cc: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=fm3; t=1719651941; x= 1719738341; bh=yklDkt8jB8ml8iyWcrRdORZ5Eyx4ew5o0WMLUDj3bVk=; b=R D2nBZT5fo3Tr6aF4SRrxCjMf2CYiHaq5uYbSNb73kcf3i7BRgLOrXr5Pk4HtsOht SwoAHDypkGs3V0oZVap7IqXzyYer2KE+841dur9UC9Ks6tm6ljb2YYk13nqapDkn e3Ud/KcgBMbiWJv7Gpj74YNdQIbCpE99rZgI7/bAkaCcp/OldBKvM8LAj4kIHaP+ mL5zz1MpxvLTyztDNjoic7esZyTgyqQqwl2ZDRK0mz4MEkW+I3jGzta2LzJ687Ul yCOEd1zDDCCeJCXN4EHByGNQNr5VlmjwJLWrLkf0APSSLbLrDCX18j6/dsAaERH0 Ms1GfiQhP6FfrL6J2oABA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc: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= fm2; t=1719651941; x=1719738341; bh=yklDkt8jB8ml8iyWcrRdORZ5Eyx4 ew5o0WMLUDj3bVk=; b=N/5qdEXxEsQ1FcUrVR351VX9TcZyl07owo9Cv7OvAEMr JR7D9dpX7ij00osCV4Dykr2z9ezk9JwBKKdCj2/mnlzuDMBxKNeYnrcVs4IYbisj Ir+ZUddxnKlqKgZxzBa519ddd8Acr99q1wmJD+RW4f2BJiyRt2rf9KpRqMb+B3+7 901GqfjfVezvsdVqJJ0pSjkbwclH8V49DSn2V4CSlEC48qlhEf4JGaD6jfzsbtrz X+x5Q/VEBRqJL5cV3y0A3bSpvSmwIZG0/y53RVO6bykjHuUIncAAksa6JW4EYJvf Q/KRUOfVSdlfKuVIbSsoxUU7aWcmH7GF8eoFWt0zIw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrtdelgdduudcutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefofgggkfgjfhffhffvvefutgesrgdtreerreerjeenucfhrhhomhepfdftohgs ucfnrghnuggvrhhsfdcuoehrohgssegsohhtthhlvggurdgtohguvghsqeenucggtffrrg htthgvrhhnpedvheekteelveetfeevgeekgfffvdeuhfelveehvdetiefggedtfeejheet gffhueenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrohgssegsohhtthhlvggurdgtohguvghs X-ME-Proxy: Feedback-ID: ifab94697:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id 9FD7F15A0093; Sat, 29 Jun 2024 05:05:41 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.11.0-alpha0-538-g1508afaa2-fm-20240616.001-g1508afaa Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net MIME-Version: 1.0 Message-ID: <60bd5a90-c344-4b54-9ff1-cca659209c43@app.fastmail.com> In-Reply-To: <33b14c2e-cf81-45c2-ae82-da40719827c6@app.fastmail.com> References: <8dc5393e-b552-465a-9237-9251e8bf1001@app.fastmail.com> <33b14c2e-cf81-45c2-ae82-da40719827c6@app.fastmail.com> Date: Sat, 29 Jun 2024 11:05:20 +0200 To: "Jordan LeDoux" Cc: internals@lists.php.net Subject: Re: [PHP-DEV] [RFC] Operator Overrides -- Lite Edition Content-Type: multipart/alternative; boundary=52133731c04b491eb31585c6de52f678 From: rob@bottled.codes ("Rob Landers") --52133731c04b491eb31585c6de52f678 Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable On Sat, Jun 29, 2024, at 11:01, Rob Landers wrote: > On Sat, Jun 29, 2024, at 02:13, Jordan LeDoux wrote: >>=20 >>=20 >> On Fri, Jun 28, 2024 at 12:55=E2=80=AFPM Rob Landers wrote: >>> __ >>>=20 >>>=20 >>>> 3. The private/protected distinction is fairly meaningless for the = functions that implement overloads, because the privacy of the function = is ignored completely when it is executed to evaluate an operator. >>>=20 >>> Hmm. I like the idea of protected, because it gives a structure to i= t that is apparent and usable right from the IDE. You just =E2=80=9Cfill= in the blanks=E2=80=9D or stick with the default behavior.=20 >>=20 >> I do not understand how the visibility has any impact on the usabilit= y you are seeking to provide. >=20 > I guess it depends on what you mean by usability. From a technical sta= ndpoint, it has zero usability, but from a dev-ex standpoint, it has a h= uge amount of usability. >=20 > If we add these as protected methods to the base class, I merely need = to write "protected static function" in my IDE and I will see all t= he methods I can write. It also lays bare "how it works" for a PHP devel= oper without any magic, making it easier to document. >=20 >>=20 >>>> 4. The `static` distinction is also fairly meaningless, as in PHP t= here is no situation possible where an operator overload can occur WITHO= UT it operating on objects themselves. >>>=20 >>> For this, that is the wrong approach. The actual behavior is on the = type, not the instance. The object instances may not even know their val= ue, they merely represent the value. >>=20 >> A GMP object instance that does not know its value? What are you even= talking about? Can you show me some code explaining what you mean? I ha= d literally months of this argument for the operator overloads RFC, and = studied the overload implementations in six other languages as part of w= riting that RFC, I feel like I understand this topic fairly well. But I = do not understand what you are saying here. >=20 > Heh, yeah, it's kinda weird. Let me explain. The GMP class hides its v= alue in a "private" member (because the value isn't actually a number, b= ut a GMP resource), so unless the programmer also sets the value to some= thing they have access to, they won't know the value (but they can alway= s cast $this to a number or operate on it directly). The only way they c= ould get the value is to cast $this to float, which may lose some precis= ion. The idea here is to "write the rules" where the value doesn't matte= r, or if it does, embed that as part of the rules. >=20 > For example, imagine we want to create a Field class, that takes a ran= ge for the field and keeps the value in the field. It might look somethi= ng like this: sigh: not enough coffee again and I saw the blunder as soon as I sent it= . Here's the more correct implementation. class IntField { public function __construct(private int $max, int $value) { parent::construct($value, 10); } protected static function add($left, $right): self { // todo: guard that left can be added to right -- ie, both are integ= ers $result =3D parent::add($left, $right); if ($result >=3D $left->max) return new IntField($left->max, $result= % $left->max); return new IntField($left->max, $result); } // todo: remaining implementation } =20 > I actually had a bit of a long-thought about it, and I think this is s= impler (both to implement and to use) than the traditional approach, and= more powerful. With the more traditional approach, how do define commun= itive rules? You are bound by traditional mathematics, more-or-less. Fro= m working in cryptography, a long time ago now, I can say that there are= non-communitive rings where having access to both "left" and "right" ca= n allow you to handle this quite well. >=20 >> =20 >>>=20 >>>> 6. The `comparable` function you propose doesn't actually have an o= perator it corresponds to. There is no operator in PHP for "is the left = value comparable with the right value". There are operators for comparis= ons themselves, which I assume you meant, but a bool is insufficient as = a return type for that. >>>=20 >>> In the engine, there=E2=80=99s just a compare function for internal = overrides. So we just check that everyone agrees that the two objects ar= e comparable and then pass it on to =E2=80=9Cbusiness as usual.=E2=80=9D >>=20 >> I'm aware of how the compare handler for class entries and zend_comp= are interact. What I am saying is that your design is insufficient for <= =3D>. You cannot return `false` from this method to mean uncomparable, a= nd `true` to mean comparable. The zend_compare function can validly retu= rn 0 or -1, with the -1 being used for both less than OR greater than be= cause the operands are reordered to always be a less than comparison. Th= en 1, which normally is used for greater than, is used to mean uncompara= ble. >=20 > Ah, I mean that it calls this as a guard, before ever doing a comparis= on, not that this output will be used for comparison itself. This is del= iberate, to keep it simple. If I get feedback that comparison should be = implemented vs. a guard for comparison, I'd be happy to add it. >=20 >> As you are proposing this without any genuine expectation you can pas= s it, this will be the last energy I will invest into helping. >=20 > I didn't mean it how I think you are taking it. To expand a bit on wha= t I meant, "we" (as in people who want this feature, like myself) can on= ly create RFCs for it. Maybe one day, the voters will change their mind,= "we" will find an implementation they agree with, or they'll forget to = vote "no" while enough people vote "yes." So, yes, I genuinely want this= feature and I want to propose a feature that works and is the best I ca= n come up with; at the same time, I don't expect it to pass, but I do ho= pe that negative feedback will drive the feature to a compromise or solu= tion that works. The only way to get there is by failing. >=20 > =E2=80=94 Rob =E2=80=94 Rob --52133731c04b491eb31585c6de52f678 Content-Type: text/html;charset=utf-8 Content-Transfer-Encoding: quoted-printable

=

On Sat, Jun 29, 2024, at 11:01, Rob Landers wrote:
On Sat, Jun = 29, 2024, at 02:13, Jordan LeDoux wrote:

=

On Fri, Jun 28, 2024 at 12:55=E2=80=AFPM Rob Landers = <rob@bottled.codes> wrote:



3. The private/protected distinction is fairly meani= ngless for the functions that implement overloads, because the privacy o= f the function is ignored completely when it is executed to evaluate an = operator.

Hmm. I l= ike the idea of protected, because it gives a structure to it that is ap= parent and usable right from the IDE. You just =E2=80=9Cfill in the blan= ks=E2=80=9D or stick with the default behavior. 

I do not understand how the visibili= ty has any impact on the usability you are seeking to provide.
=

I guess it depends on what = you mean by usability. From a technical standpoint, it has zero usabilit= y, but from a dev-ex standpoint, it has a huge amount of usability.
<= /div>

If we add these as protected methods to the bas= e class, I merely need to write "protected static function<tab>" i= n my IDE and I will see all the methods I can write. It also lays bare "= how it works" for a PHP developer without any magic, making it easier to= document.


=
<= div>4. The `static` distinction is also fairly meaningless, as in PHP th= ere is no situation possible where an operator overload can occur WITHOU= T it operating on objects themselves.
=

For this, that is the wrong approach. The actual beh= avior is on the type, not the instance. The object instances may not eve= n know their value, they merely represent the value.

A GMP object instance that does not k= now its value? What are you even talking about? Can you show me some cod= e explaining what you mean? I had literally months of this argument for = the operator overloads RFC, and studied the overload implementations in = six other languages as part of writing that RFC, I feel like I understan= d this topic fairly well. But I do not understand what you are saying he= re.

Heh, yeah, it'= s kinda weird. Let me explain. The GMP class hides its value in a "priva= te" member (because the value isn't actually a number, but a GMP resourc= e), so unless the programmer also sets the value to something they have = access to, they won't know the value (but they can always cast $this to = a number or operate on it directly). The only way they could get the val= ue is to cast $this to float, which may lose some precision. The idea he= re is to "write the rules" where the value doesn't matter, or if it does= , embed that as part of the rules.

For exam= ple, imagine we want to create a Field class, that takes a range for the= field and keeps the value in the field. It might look something like th= is:

sigh: not enough coffee ag= ain and I saw the blunder as soon as I sent it. Here's the more correct = implementation.

class IntField {
<= div>  public function __construct(private int $max, int $value) {
    parent::construct($value, 10);
=   }
  protected static function add($left, $righ= t): self {
    // todo: guard that left can be a= dded to right -- ie, both are integers
    $resu= lt =3D parent::add($left, $right);
    if ($resu= lt >=3D $left->max) return new IntField($left->max, $result % $= left->max);
    return new IntField($left->= ;max, $result);
  }
  // todo: rem= aining implementation
}
 
I actually had a bit of = a long-thought about it, and I think this is simpler (both to implement = and to use) than the traditional approach, and more powerful. With the m= ore traditional approach, how do define communitive rules? You are bound= by traditional mathematics, more-or-less. From working in cryptography,= a long time ago now, I can say that there are non-communitive rings whe= re having access to both "left" and "right" can allow you to handle this= quite well.

&n= bsp;
<= br>
=
6. The `comparable` function you propose does= n't actually have an operator it corresponds to. There is no operator in= PHP for "is the left value comparable with the right value". There are = operators for comparisons themselves, which I assume you meant, but a bo= ol is insufficient as a return type for that.

In the engine, there=E2=80=99s just a compar= e function for internal overrides. So we just check that everyone agrees= that the two objects are comparable and then pass it on to =E2=80=9Cbus= iness as usual.=E2=80=9D

 I'm aware of how the compare handler for class entries and = zend_compare interact. What I am saying is that your design is insuffici= ent for <=3D>. You cannot return `false` from this method to mean = uncomparable, and `true` to mean comparable. The zend_compare function c= an validly return 0 or -1, with the -1 being used for both less than OR = greater than because the operands are reordered to always be a less than= comparison. Then 1, which normally is used for greater than, is used to= mean uncomparable.

Ah, I mean that it calls this as a guard, before ever doing a comparis= on, not that this output will be used for comparison itself. This is del= iberate, to keep it simple. If I get feedback that comparison should be = implemented vs. a guard for comparison, I'd be happy to add it.

As you are proposing th= is without any genuine expectation you can pass it, this will be the las= t energy I will invest into helping.
<= div>
I didn't mean it how I think you are taking it. To ex= pand a bit on what I meant, "we" (as in people who want this feature, li= ke myself) can only create RFCs for it. Maybe one day, the voters will c= hange their mind, "we" will find an implementation they agree with, or t= hey'll forget to vote "no" while enough people vote "yes." So, yes, I ge= nuinely want this feature and I want to propose a feature that works and= is the best I can come up with; at the same time, I don't expect it to = pass, but I do hope that negative feedback will drive the feature to a c= ompromise or solution that works. The only way to get there is by failin= g.

=E2=80=94 Rob
=

=E2=80=94 Rob=
--52133731c04b491eb31585c6de52f678--