Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125560 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 056E11A00BD for <internals@lists.php.net>; Mon, 16 Sep 2024 04:10:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1726459955; bh=U5SO71P2RWw6Jjj8jrw6tPd8nQetyqrgQy+aVzErq7A=; h=Date:From:To:In-Reply-To:References:Subject:From; b=Nw3DgiFyngl9/fG2TPyJ4wbI+zMSTzREaRRorhYu0NxwQgBT1/h8fDFVA9KfomgKe yzLmGoNjePjHwl1yyidaF1790QKCblv4GUkuzTAr266JOw69Vi6B4BhY4ETtMidCwV kqnD+kVlHJepTBL4Wse2Qurm++h/QBl0pwSXtDuiw4ModyQbHBiJyhDz6YFHIuCCB+ LY3irwrI/LjYaO0SL2HdyYMXLHGTvgjEmJJTB7ivVU2eI5H8QwaYMZ6RVmGlTzDViQ qNpfJwc51kwsyNfEC/CNxRmvpLgmHoJDNjeMSHun3Ql3thfy5lD8fjsOZqK0yK8x0d IHgRuUuIH2rNg== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id DD572180042 for <internals@lists.php.net>; Mon, 16 Sep 2024 04:12:33 +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,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: <larry@garfieldtech.com> Received: from fout8-smtp.messagingengine.com (fout8-smtp.messagingengine.com [103.168.172.151]) (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 <internals@lists.php.net>; Mon, 16 Sep 2024 04:12:33 +0000 (UTC) Received: from phl-compute-01.internal (phl-compute-01.phl.internal [10.202.2.41]) by mailfout.phl.internal (Postfix) with ESMTP id 961101380279 for <internals@lists.php.net>; Mon, 16 Sep 2024 00:10:28 -0400 (EDT) Received: from phl-imap-06 ([10.202.2.83]) by phl-compute-01.internal (MEProxy); Mon, 16 Sep 2024 00:10:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= garfieldtech.com; h=cc:content-transfer-encoding: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=1726459828; x=1726546228; bh=NBcdpphpgzL8/1SZ+c0qK JPGR28MIMylYaG/wd1Fv1g=; b=K7QLk8fHRA/dB7eNj2hkPDg00ak582RsqsTuw Ao7ghTek/yC0UQBmhZL8uG0PacmidPX106oc66wbtbz69qpThC5ONj3hHoW+1f6N FagbzNRCrbiq58LbKPlpV3uysSzroxzrSEkJeIuIdJwMQoW8DEL0SLqi5q7t1QK2 xelOi2os255y72jWrhWNlFZxfxmR4TSPdMU5KyWu9TBRUi4Lc2D0zPqDECe96qXS x/IFNv1IhuopnkOaMNTbLJCcVJ309SsKbbi1R9kb3fOPb+jRnr5rQMERAMPs270O oFND8LUsH/ESEjuGrUp+AdTGZLgJBJ3VLM4cucXarqbm7VcYQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding: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=fm1; t=1726459828; x= 1726546228; bh=NBcdpphpgzL8/1SZ+c0qKJPGR28MIMylYaG/wd1Fv1g=; b=N ZQWqca+cTNP+extm5IJpVgZoOFmDnLk8KRn3zkZeMBKa6Pka9u1cPPP5WMlrCpqO Wn2CZ6i6fW/v0FYzI0kdkHv/4alEuLTSldlY5s5h6oy27PS85ul8Dz++reZJhr7C 02n/Zy52Ars/sxPW6THMHsHa184w7H8zRWCArpcd+TSuAexPCRPGHVo+bnQcT3tE 5pBGd7LUKkJMuyvRG8EKYokeIwoFRX05EaEcy20xRzODTyzOgMvcKd2q2EUdy9u2 qQCSuFcIZAxWBkHtOmLYEfLNtVS8u49ub9Cr8EFhGx5LBqREexAPQwCjccfF+6hl pfbZjz7JW04SJ3s+WP6tA== X-ME-Sender: <xms:tK_nZjpriPsfTyFBXNzvU2sFjumsOmvSU1FC8zGMr3W1z7492fT19A> <xme:tK_nZtrf2RY8983b05APjnLLBwvB0Ic3xKRrflp_AcXX-uC-LI5G6k6i2c3H3zjT5 fgXOehHTS64rQ> X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrudekgedgkedvucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggvpdfu rfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnh htshculddquddttddmnecujfgurhepofggfffhvffkjghfufgtgfesthejredtredttden ucfhrhhomhepfdfnrghrrhihucfirghrfhhivghlugdfuceolhgrrhhrhiesghgrrhhfih gvlhguthgvtghhrdgtohhmqeenucggtffrrghtthgvrhhnpeffieelvdejiefhvdevveef udfgleethedvgfevteeiudfhkeekveejkeeiveegjeenucffohhmrghinhepphhhphdrnh gvthdpghhithhhuhgsrdgtohhmpdgtohhmphgrrhhishhonhdqvghquhgrlhhithihqdhs vghmrghnthhitghsrdhmugenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmh grihhlfhhrohhmpehlrghrrhihsehgrghrfhhivghlughtvggthhdrtghomhdpnhgspghr tghpthhtohepuddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepihhnthgvrhhnrg hlsheslhhishhtshdrphhhphdrnhgvth X-ME-Proxy: <xmx:tK_nZgOEOtpwBP7SXUXrKsJJjh5psPGBasXELqK8gV_h9VK2ty3Hsw> <xmx:tK_nZm5TLA-kEQ6Ae5qqMJO2jKR0e4pye_NyGOfMuz6DIMp602vtlA> <xmx:tK_nZi4egNKt_aLd1-hL8ffP9dBFYy-px16SiHR2dVSrrGCmwD7vIQ> <xmx:tK_nZujJ-PIkG8esq2FGTk685qiwYgppJNXFiwxHmTqavW1tvsjoTg> <xmx:tK_nZvVzZHSqq9z0yzH1cJgvNSfHhknNhPCZHPSFZUf62r3R44JlWtfo> Feedback-ID: i8414410d:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 4121329C006F; Mon, 16 Sep 2024 00:10:28 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Precedence: bulk list-help: <mailto:internals+help@lists.php.net list-unsubscribe: <mailto:internals+unsubscribe@lists.php.net> list-post: <mailto:internals@lists.php.net> List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 Date: Sun, 15 Sep 2024 23:10:01 -0500 To: "php internals" <internals@lists.php.net> Message-ID: <ca0336fc-a6ed-4ced-a3e4-2322bfa6dc76@app.fastmail.com> In-Reply-To: <CAMrTa2E2m00gOoGy5FbvkrLwM1AUP3ZmJXHkxh_R2qEszQ=NWA@mail.gmail.com> References: <CAMrTa2E2m00gOoGy5FbvkrLwM1AUP3ZmJXHkxh_R2qEszQ=NWA@mail.gmail.com> Subject: Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again) Content-Type: text/plain Content-Transfer-Encoding: 7bit From: larry@garfieldtech.com ("Larry Garfield") On Sat, Sep 14, 2024, at 4:48 PM, Jordan LeDoux wrote: > Hello internals, > > > This discussion will use my previous RFC as the starting point for > conversation: https://wiki.php.net/rfc/user_defined_operator_overloads > > > There has been discussion on list recently about revisiting the topic > of operator overloads after the previous effort which I proposed was > declined. There are a variety of reasons, I think, this is being > discussed, both on list and off list. > > > 1. As time has gone on, more people have come forward with use cases. > Often they are use cases that have been mentioned before, but it has > become more clear that these use cases are more common than was > suggested previously. > > 2. Several voters, contributors, and participants have had more time > (years now) to investigate and research some of the related issues, > which naturally leads to changes in opinion or perspective. > > 3. PHP has considered and been receptive toward several RFCs since my > original proposal which update the style of PHP in ways which are > congruent with the KIND of language that has operator overloads. > > > I mentioned recently that I would not participate in another operator > overload RFC unless I felt that the views of internals had become more > receptive to the topic, and after some discussion with several people > off-list, I feel that it is at least worth discussing for the next > version. > > > Operator overloads has come up as a missing feature in several > discussions on list since the previous proposal was declined. This > includes: > > > [RFC] [Discussion] Support object type in BCMath [1] > > Native decimal scalar support and object types in BcMath [2] > > Custom object equality [3] > > pipes, scalar objects and on? [4] > > [RFC][Discussion] Object can be declared falsifiable [5] > > > The request to support comparison operators (>, >=, ==, !=, <=, <, <=>) > has come up more frequently, but particularly in discussion around > linear algebra, arbitrary precision mathematics, and dimensional > numbers (such as currency or time), the rest of the operators have also > come up. > > > Typically, these use cases are themselves very niche, but the > capabilities operator overloads enable would be much more widely used. > From discussion on list, it seems likely that very few libraries would > need to implement operator overloads, but the libraries that do would > be well used and thus MANY devs would be consumers of operator > overloads. > > > I want to discuss what changes to the previous proposal people would be > seeking, and why. The most contentious design choice of the previous > proposal was undoubtedly the `operator` keyword and the decision to > make operator overload implementations distinct from normal magic > methods. For some of the voters who voted yes on the previous RFC, this > was a "killer feature" of the proposal, while for some of the voters > who voted no it was the primary reason they were against the feature. > > > There are also several technical and tangentially related items that > are being worked on that would be necessary for operator overloads (and > were originally included in my implementation of the previous RFC). > This includes: > > > 1. Adding a new opcode for LARGER and LARGER_OR_EQUAL so that operand > position can be preserved during ALL comparisons. > > 2. Updating ZEND_UNCOMPARABLE such that it has a value other than -1, > 0, or 1 which are typically reserved during an ordering comparison. > > 3. Allowing values to be equatable without also being orderable (such > as with matrices, or complex numbers). > > > These changes could and should be provided independent of operator > overloads. Gina has been working on a separate RFC which would cover > all three of these issues. You can view the work-in-progress on that > RFC here: > https://github.com/Girgias/php-rfcs/blob/master/comparison-equality-semantics.md > > > I hope to start off this discussion productively and work towards > improving the previous proposal into something that voters are willing > to pass. To do that, I think these are the things that need to be > discussed in this thread: I voted in favor of the RFC last time around, and assuming an essentially similar RFC is submitted again will most likely vote in favor again. I do believe this is a useful "surgical" feature; not typically used, but when used, very valuable. > 1. Should the next version of this RFC use the `operator` keyword, or > should that approach be abandoned for something more familiar? Why do > you feel that way? IIRC, the main argument against `operator` was that it was a new keyword people would need to learn, and tools would need to adapt to understand. That is... a curious argument, to me, as it applies to nearly every new language feature that gets added. We just voted in property hooks and asymmetric visibility. Both introduce new syntax for both users and tooling to adapt to. Both passed by substantial margins. For me, the main argument in favor of the `operator` keyword is that it allows us to sidestep a particular challenge: Is the method to override the + operator named __plus() or __add()? Do those words even mean the right thing? Should * be named __times(), __multiply(), or __dotproduct()? Depending on what type of data you're working on, any of those could be accurate, or completely wrong and misleading. Instead writing operator +(...) means I know precisely which symbol I'm defining. As a side benefit, we also don't have to think about what visibility means on an operator, which is just kinda weird. As an extreme example, Python's popular PathLib uses `/` as a concatenation operator, because it "looks like" a path. A PHP implementation of the same could be something like this: class Path { private array $parts; public function __construct(string $path) { $this->parts = array_filter(explode('/', $path)); } public function __toString() { return implode('/', $this->parts); } // And then one of these: public function __divide(...) { ... } // or operator /(...) { ... } } One of those is horribly misleading about what's going on. The other is extremely descriptive. Now, opponents of operator overloading, or just the `operator` keyword, would argue that the above is exactly what they want to avoid. For me, that's exactly what I want to enable. At some level, it's just a basic philosophical difference. Another argument I recall is that the `operator` syntax makes it "natural" and tempting to extend to user-defined operators, so you could define your own operator+-*&() for an object to do god knows what. I fully agree, there is a risk to doing that. However, that is not what this RFC was, and I presume will be, suggesting: The available operators are a built-in fixed list. If we want to add some new operator that only makes sense for objects (such as a bind operator, something I'd love), that would be its own RFC that we could argue about. And those who don't want user-definable operators can readily vote against any future proposal to do so, while still giving us the benefit of the known operators. I will also note that, in my research into collections in other languages, providing operator overloads for collections is extremely common, and in practice I find it very ergonomic. We will probably want collections as built in classes for performance anyway (whether using a custom syntax or generics), but I note that as another datapoint where operator overloads make a great deal of sense, but their "standard arithmetic names" would be very misleading. (They often use the boolean & and | operators, too, which results in some really nice and very readable code.) > 2. Should the capability to overload comparison operators be provided > in the same RFC, or would it be better to separate that into its own > RFC? Why do you feel that way? My sense, which I've written about before, is that there are different "sets" of operators that cluster together. IIRC, I said something like: A. Comparisons. (<=>, ==, etc.) B. Arithmetic operators (+, -, *, /). C. Everything else (concat, etc.) I personally believe that's the order of importance. If we wanted to just dip our toes into operator overloading, we could do just set A for now. I'm fine with all three groups being approved, as I have uses for all of them. I could see having A be the main vote, and B and C being secondary votes on the same RFC. > 3. Do you feel there were any glaring design weaknesses in the previous > RFC that should be addressed before it is re-proposed? Only minor things, I think. "OperandPosition" is a very long name to type all the time, even if I can't come up with something better. The operand ordering is kinda weird, but given how much discussion went into it last time I don't have any alternative that isn't either worse or more weird, or both. The "multiply by -1 for <=>" bit I don't fully understand the point of. The RFC tries to explain, but I don't quite grok it. For reflection, I'd be inclined to make ReflectionOperator extends ReflectionMethod, rather than an isOperator() method. That is largely stylistic, I suppose, as I am generally a fan of making the type system do the work for us whenever possible. > 4. Do you feel that there is ANY design, version, or implementation of > operator overloads possible that you would support and be in favor of, > regardless of whether it matches the approach taken previously? If so, > can you describe any of the core ideas you feel are most important? I was fairly happy with the previous version, so proposing that as-is would have my vote. I would probably oppose including arbitrary symbol overloading at this time. To me, the most important factors are: 1. It's type-safe, and leverages the type system to "make invalid states unrepresentable" as much as possible. (I'd put the rules around <=> into this category.) 2. It allows me to opt-in piecemeal to just those operators that make sense. 3. The performance overhead compared to using a method is minimal. 4. It is future-compatible with further language evolution, to the extent possible. (The `operator` keyword helps here.) I'd love to see this brought up again, and hope there is sufficient interest to do so. --Larry Garfield