Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:115672 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 45613 invoked from network); 9 Aug 2021 17:18:05 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 9 Aug 2021 17:18:05 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 2556818053C for ; Mon, 9 Aug 2021 10:48:22 -0700 (PDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,HTML_MESSAGE, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-lf1-f53.google.com (mail-lf1-f53.google.com [209.85.167.53]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 9 Aug 2021 10:48:21 -0700 (PDT) Received: by mail-lf1-f53.google.com with SMTP id w20so8995663lfu.7 for ; Mon, 09 Aug 2021 10:48:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=+1QkBoTEp/zrTCdoMElm5TODP1Y6X7A2LKNRB0EKDe4=; b=f/lhL8Vgk6DJxyGyJdveXnPYFYXVsl5gqwEbfLiOdUlA5/zeCQgaOu0eNuVgIVUbY1 zHuV7wyUxVFEQ37kvINNqjDOPE7mr7AP95P5ue7z5mCMZdXqdisl9nfci3Ldh6ZNV/V8 e8TagNe1AcNszfZBYQBZNuRjr5Gif6wdPxIjZWO0tGRo97YQfvbuQUIcBd22P14GJ//N Rl0fjn/Ugc9Z2n0E/doyizv9cItpajrB1Br6SKzz6G+vWVU1xBlGbU5n1mDb79bPwn7Z pWs7Jt1Jg//bCWcuf4treHSGOHD2VmTmqFYaelCagFwG9JbXPsZ+pAyHbtbU434AtUV9 5UHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=+1QkBoTEp/zrTCdoMElm5TODP1Y6X7A2LKNRB0EKDe4=; b=SxhN4RlR5ua0ZK/KV46Sp2Nzvzy9OoUlrB5WnE8I1eMq8R5l+e52n9sNjbzrz1aFjG 6IRP5QPkgFVXUI2OiTZkxowpgH6dxXNdhE/HrYdk12/G/ySjIniOoUFhn3Xtvxyr8XGQ Rr0573295r1PCp+nfndHADc5mptwHffnFrGwh72Cg8jUeJsJkIsCWzHppZVtGAu2IskQ 4QAsWMmUwRecJE/J0soj0+EbL2anyzjUIMrvUcOxPo2LcxWZSwJNO2qmIFZI+vPiWx/z MXpslpC4kWysta8/8LkfkyIiJJvYE6uQkq4Nr9dl+xIzBS1CODlgiJOrGQd0KkcsCabQ L9Hg== X-Gm-Message-State: AOAM533LMggp/8YDfOGT5JFN8bJbsfJTjeVbXFvQmt0H+fV0YA1bYFLl 8TFs84wJHmmVm6vtV4wsaLIr1bwFrwBKMw0jJEM= X-Google-Smtp-Source: ABdhPJznbunvbUCeiQhDfOJh7wyfBgwZiN1ZldKV1pt2pVQwZ8hWi4iIwOErKKKzbNagulBi98frOQhoLY6GrTMRdOw= X-Received: by 2002:ac2:41c2:: with SMTP id d2mr1501740lfi.241.1628531299306; Mon, 09 Aug 2021 10:48:19 -0700 (PDT) MIME-Version: 1.0 References: <94696d46-c4e6-406a-b859-89144bff31bf@www.fastmail.com> In-Reply-To: Date: Mon, 9 Aug 2021 10:48:20 -0700 Message-ID: To: Mike Schinkel Cc: php internals Content-Type: multipart/alternative; boundary="00000000000099d21a05c923fd2a" Subject: Re: [PHP-DEV] Revisiting Userland Operator Overloads From: jordan.ledoux@gmail.com (Jordan LeDoux) --00000000000099d21a05c923fd2a Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Mon, Aug 9, 2021 at 3:49 AM Mike Schinkel wrote: > 1. When you speak of "not documented in the code" do you mean the > implementation would not be in PHP code? Okay, yet none of these function= s > are documented in PHP code and they are all available in PHP: > > https://www.php.net/manual/en/ref.math.php > > AFAIK few people who do not struggle with programming or math have any > problem with these functions, because they are all documented. > Yes, that is precisely what I mean. Operator overloading is a complex feature, I have never pretended otherwise. Having the behavior documented in the code base you are working on, in the code itself, is FAR more useful. My primary example of that is this: You claim that this would be documented on php.net and this would be sufficient. Yet the DateTime class has had operator overloads for comparison operators since 5.2 and there is still *zero* mention on php.net (that I am aware of or can find) of this. Not even a mention that it exists, let alone what the override behavior is. *Not even in the god-awful comments on the manual.* Simply put, as someone who has spent my entire career working primarily in PHP and been working in it since PHP 4, it has one of the very best free and online manuals for any language I've worked in, and I would still 10 times out of 10 prefer to be able to see the implementation in my IDE than have to look it up on php.net. > 2. Yes, it would require many different implementations, one for each > use-case. Unique logic has to be implemented. Somebody has to do it. Why = is > that a problem? > > I am not sure what you mean by being "very close to each other to cover > the same set of use-cases" unless you are talking about many different > arbitrarily different userland implementations, which I doubt since that > would be a reason not do add operator overloading. > > What I mean is that there would be multiple "number like" abstract classes that would be 80% to 90% similar. That is, if it actually correctly represented the core math ideas. This method however would utterly fail for unit based value overloads, of which Rowan's money example is a specific case. > 3. Regarding maintainability concerns. Code generally doesn't rot unless > the requirements change. Are requirements going to change? If yes, then i= ts > not a strong use-case for operator overloading, in core or userland. We > should guard against operators used for convenience that are leaky > abstractions. > > BTW nobody can "demand" new features in PHP and be effective. But if they > propose them in an RFC it helps ensure these new features are fully flesh= ed > out, to the best of the list's collective ability. > > Yes, I'm aware. :) The process that PHP employs with internals to maintain the language is one of its greatest strengths in my personal opinion. I shouldn't be able to simply open a PR and have the maintainer be the only one that looks at it. My RFC, whether it is accepted or not, will be better because of this process. It has already been improved by this thread. However, creating abstract classes simply for custom operator overloads would signal to users that this is something internals is willing to do. Despite the fact that I am confident the process would continue to work, I would very much anticipate multiple and continuous threads opened by users wondering when "their" operator overloads are going to be included. While this obviously doesn't force anything, it absolutely is a distraction. > While it is hard to objectively quantify how much is "much" this gentleme= n > =E2=80=94 a programming teacher =E2=80=94 had some choice words to say ab= out operator > overloading specifically related to Python: > > https://medium.com/@rwxrob/operator-overloading-is-evil-8052a8ae6c3a > > A pull quote from his blog post: > > "You wanna know what is not simple? Operator overloading. It has no place > in any language. It=E2=80=99s an aberration to be shunned." > > He feels even more strongly about the perils of userland operator > overloading than I do! > :/ I was hoping for something more concrete than what he said in this article, especially when the one and only comment on the article succinctly expresses why it's incorrect. Python's major "selling point" over other languages, especially for its initial adoption and wide use in teaching, is its power in scientific computing, and those libraries 100% *depend* on Python's operator overloading. > A while back someone proposed __ToArray and Rowan (among others) fought > back hard saying that the problem is that exporting an object to array > could mean different things to different people and there is often a need > to export to multiple different array format, and thus the use-case shoul= d > always be implemented as a named function. A first I was annoyed that th= e > list was pushing back because I wanted to use __ToArray, but the more I > thought about it the more I realized that Rowan and others were right. > > Overloaded operators are no different than a __ToArray method. What does > __add() really mean for most classes? > > Respectfully I disagree. There can be different meanings for __add() with different operands, just like `2 + 3` is different than `2.1 + 3.1`. But an operator heavily implies the idea that there is a single and deterministic result for a given set of input values and input types. I do not believe that these are at all similar to _toArray(). The fact that internals cannot anticipate what they are because the domains and context are varied is not the same as the results being non-deterministic or usage dependent. They are not arbitrary in the same way that array structure is. > I appreciate that you have anxiety that if you don't get it all now, you > never will. I understand that, I feel the same way about the things I'd > like to see added to PHP. > That's not exactly what my concern is, though I can also understand that concern. My concern is that I think I can properly advocate for and explain the use cases and implementations that would benefit my own work, but I do not know that others could be able to do so. > But I have also realized that pushing through a feature too quickly can > have far reaching consequences and a damaging outcome. Better to take > small steps and allow time for the features to mature than to dive in and > make a mistake and have to live with it for the rest of PHP's useful life= . > This is why I'm targeting this for 8.2 and started this conversation nearly a full year before the feature freeze for 8.2. I am not going to come through with the RFC vote in a few weeks, this is going to be slow, deliberate, and inclusive, because that is the only sensible way that a change as complex and impactful as what I'm proposing could be done correctly. If we were to =E2=80=94 for example =E2=80=94 start by adding operators to = DateTime and > DateInterval it would give us real-world experience with operators and > objects before we fully commit to adding operator overloading for all > classes. > > We could then take our learning for DateTime and DateInterval and add > another class, maybe ComplexNumber. > Heck, we might even recognize value in creating an imaginary number > literal to support it; that type of domain-specific value won't happen if > we just focus on generic operator overloading. > > Once we have ComplexNumber down, maybe we tackle a few more Math classes, > and many we even tackle Money. > This is interesting, since we *do* have operator overloads for DateTime already and have for quite a long while. This is covered briefly in the draft RFC I linked in my last message. An imaginary number literal couldn't really be supported without either a fully-featured complex number library in core (not just an abstract stub with operator overloading), or errors/exceptions on multiple operator combinations. For instance, `int + imaginary` would require some representation of complex number as a result type. This is, to my understanding, why this is usually left to userland implementations in most languages, particularly since complex numbers are advantageous to represent as `int + imaginary` in some circumstances and `(r, theta)` in other circumstances. > But one thing is certain. While we can go from special one-off classes > that support operator overloading to later adding general-purpose operato= r > overloading, we cannot go the opposite direction. That makes the idea of > first testing out operator overloading on specific use-cases a much less > risky proposition that just adding general purpose operator overloading > from the start. > This is a point that I obviously can't casually dismiss, because it's simply a fact. Once user defined operator overloading exists, it can't reasonably be undone, however it can always be added on top of abstract classes in the future. That being said, this is not something that internals hasn't considered before *and* there already are custom operator overloads in C implementations in PHP. There are also extensions that cover more domain specific C implementations, such as ext-decimal and ext-gmp. The first version of this feature that I'm aware of was worked on for 7.1. So while your point is valid and powerful, my contention isn't that you're wrong, but rather that now *is* later for this feature. Internals has looked at this feature before, nearly accepted it into core for 8.0, and provided a great deal of feedback and discussion on its benefits and problems. Multiple examples of it in PHP exist in C implementations. Arrays treat `+` as a union operator. Strings and arrays both work with `<=3D>` and execute some fairly complicated (and opinionated) logic to determine sort order of those types. DateTime already has overloads for comparison operators and has for a long time. Both ext-decimal and ext-gmp have implemented domain-specific operator overloads. In fact, the operator overloading for GMP done by Nikita for 5.6 covered much of the same arguments (though it obviously didn't include userland operator overloading). I am not dismissing your point here, but I'd like to respectfully suggest that we now have the information to address the topic, instead of needing further use cases to consider. Finally, as I mentioned I won't be entertaining that format for this RFC. While I have said that I understand the argument, I would suggest that those who feel it is a better alternative work on it as an RFC if they believe it is a better route. This RFC may take me the entire year and still get rejected, and I understand that. I would simply not be a good advocate for such an approach, because the very first objection is going to be "why is this use case given preferential treatment?" and I will be unable to answer because I would raise the same objection myself. Jordan --00000000000099d21a05c923fd2a--