Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:125606 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 72ED61A00BD for ; Tue, 17 Sep 2024 22:44:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1726613220; bh=/9FhNa+lTKZsDhsCOY83u6MYJI2QdtQUlAgXcxGDYBw=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=Pc55Z2WnT/vQj2wX6Z4xYC4UoAYrQg+3q1+pwthPlKYukPhB91zDbm/CIRxaGpvLe 2fY14PjOGn69vvk+i97yWQA7lvWJxWgV9+anAQo8ryL2BhoBrnijgs6uQdrDVfTdIz kO3BCHZI34E72AKoDnp6WFnBZ6hoGbCI8PxFtsdnTUnflQ5EZbOCBzx8dihHzIMp42 pIouwlK82hAar0mG3RBrBIKUH0F0wzuD4xKSBqhnynwjcQXNM16EVevhZWuZAp36YG ucOtiw/Rcv1E1cK0Dhb+37UiLZWgnSr1VJKa+jKdfu+8aYD9dkBijYSsjq5/7gb4Kp sU76Xth7CmN8w== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 38114180032 for ; Tue, 17 Sep 2024 22:46:59 +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.8 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DMARC_MISSING,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-yb1-f182.google.com (mail-yb1-f182.google.com [209.85.219.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, 17 Sep 2024 22:46:58 +0000 (UTC) Received: by mail-yb1-f182.google.com with SMTP id 3f1490d57ef6-e1a8e305da0so5568308276.3 for ; Tue, 17 Sep 2024 15:44:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=newclarity-net.20230601.gappssmtp.com; s=20230601; t=1726613093; x=1727217893; darn=lists.php.net; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=K3h4Fn+zI2gEZizWXA2VztUTB7UtyLu7Lxcv7d1Vby0=; b=TpYO0zKZLUp+UWA7wV6e4eZB0JSdHM6F87FTYQj5p13vYJUOqsV2ZJWTjfB/YwZ7us xXjNvJJx1yr34s+qsiYioourmIjDUkY7ulUzJVyU8XxqjgJZlyjF78zwJZKnBXJm9cKT U9DmO2jG3ihGomw0YfyPL8izD/4whJTCM8CWl9wDIKeAzkOuT3XwrUhgjW4W0LoVdqnv y7Dl84Bu604XkaS9RIHLEEQSS7PfPr5Kaq8DhnmvhunDi5oXwslmeFCwisrhaClnZQXk q5dfRauWWHSbxsUYTa+1M2R+sC4V1jgGBQkBEldgGTCfsdBGXmETrbumc3/QyHDr9Vsa PdPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726613093; x=1727217893; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=K3h4Fn+zI2gEZizWXA2VztUTB7UtyLu7Lxcv7d1Vby0=; b=rHvhRVsXBTJDakrVyHJMcNzB3052aeBwM1QzxORNJpNHursyJcnyo88YSLWoOoIrBN OtfY7oURQnZJaT9EdYxA7UUbWn7XhIRtIeLeaN+EC29FU0GUQt+bPU29JUhCUMvCad/n oT67l31y9VYQ/sm8RwVzhEi5uFH7goW0lG8mySfYG2z/mIfsiXxRdLgL6Nig2r0QBLuG kR1Cx5Mgot10cTEIGoSK/pe2crf1caK2CiS9ZQVuVGPpK7XLXOcl6JcQp9KX9TjODGUY g/uEY9zg1aWhoSBegVyU6e23RL1zcF8W3k4xsTZgcRaNSHenkrqjc9JTvSH0GAD61exh vX8w== X-Gm-Message-State: AOJu0Yyk4mI1qRLnB8fJuFOgB9jYb/KbzEsjWRtxy2a+KfhCmpTEgOFw BBYoX02LA/3UQMmnJKHR0QllWr6FkSiMUBBrRgi8Q2STYvik92kH1wiJCZ1Kj2U= X-Google-Smtp-Source: AGHT+IHlphdtNcA3e28JQb2yZHComshOnOCQb7dphMTzkq+kqLQ1svtptxKo+vreLF1aIxQCCYF7Jg== X-Received: by 2002:a25:ae83:0:b0:e1d:af44:46b5 with SMTP id 3f1490d57ef6-e1daf44479dmr9934979276.2.1726613092512; Tue, 17 Sep 2024 15:44:52 -0700 (PDT) Received: from smtpclient.apple (c-98-252-216-111.hsd1.ga.comcast.net. [98.252.216.111]) by smtp.gmail.com with ESMTPSA id 3f1490d57ef6-e1dc1380673sm1614571276.40.2024.09.17.15.44.51 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2024 15:44:52 -0700 (PDT) Message-ID: Content-Type: multipart/alternative; boundary="Apple-Mail=_0AC6DC6E-4F2D-4025-BE87-6D54AE8E55F8" Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3696.120.41.1.10\)) Subject: Re: [PHP-DEV] [Pre-RFC Discussion] User Defined Operator Overloads (again) Date: Tue, 17 Sep 2024 18:44:51 -0400 In-Reply-To: <430bc224-c8b2-4b29-a896-b92a156babcb@gmx.net> Cc: internals@lists.php.net To: Andreas Leathley , Jordan LeDoux References: <18603813-9ECB-4486-95EE-08BEDECAB88D@newclarity.net> <430bc224-c8b2-4b29-a896-b92a156babcb@gmx.net> X-Mailer: Apple Mail (2.3696.120.41.1.10) From: mike@newclarity.net (Mike Schinkel) --Apple-Mail=_0AC6DC6E-4F2D-4025-BE87-6D54AE8E55F8 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Sep 17, 2024, at 6:04 AM, Andreas Leathley = wrote: >=20 > On 17.09.24 11:14, Mike Schinkel wrote: >> How would a developer know if they are using an object that has = operators, unless they study all the source code or at least the docs = (assuming there are good docs, which there probably are not?)=20 > How is that different from using a method on an object? Operators are = roughly speaking a different syntax for methods, and if you use an = object method, you have to know about it or look up what it does. >=20 When you see a method call, you know 100% of the time that it calls a = method. Assuming operator overloading, when you see an operator used with = variables, you will no longer be able to rely on your knowledge of how = the operator work as it might use the built-in operator OR it might call = a method. Most of the time it will be the former, occasionally the = latter. =20 And since a method would only be called occasionally I would likely get = tired of searching to see if there is a method being called and just = assume there isn't. Not smart, but having to track down potential = methods for every operator use would just be far too tedious. > Also, getting to the implementation of operators would likely be just = as easy as looking up methods nowadays, because IDEs would support = that kind of lookup. >=20 The more generic named the method, the more IDEs struggle with finding = methods, and operators are about as generic as you can get. > Most framework and library code is by now type-hinted - I would have = understood this argument when operator overloading would be implemented = into PHP 5.x, where many classes and functions got values and had no = enforced types, so they might have expected an int, yet an object with = operator overloading might work but in weird ways, because there were no = type hints for int. I cannot see this situation now at all - if a = Symfony component wants an int, you cannot pass in an object. If a = Symfony component wants a Request object, it will not use operators that = it does not expect to be there, even if you would extend the class and = add operator support. Using operators implies you know you can use = operators, otherwise it will be a fatal error (except for comparisons). >=20 ANY object could have an operator overload on `=3D=3D` and/or `=3D=3D=3D` = and have those behave differently. I also just checked and Symfony has many parameters type hinted as = Stringable and numerous interfaces that extend Stringable. Any object = that implements Stringable could also add operator overloads and = introduce subtle bugs into those functions. Symfony has numerous interfaces that extend Countable. Any object that = implements Countable could also add operator overloads and introduce = subtle bugs into those functions. Symfony has numerous interfaces that extend ArrayAccess. Any object = that implements ArrayAccess could also add operator overloads and = introduce subtle bugs into those functions. Further =E2=80=94 if operator overloads are added =E2=80=94 there will = likely be demand for more "-able" type interfaces, or some other way to = make objects behave more like scalar types. If we have opt-in then code = is safe. If we do not have opt-in then unintended consequences are = possible, if not likely. > =46rom your arguments it also seems you are afraid everybody will use = operator overloading excessively and unnecessarily. This seems very = unlikely to me - it is not that useful a feature, except for certain = situations. >=20 We will have to agree to disagree on that then. Look at what happened = when is was added to C++; people when crazy with it and it was numerous = years before the community moderated their behavior. > Many other languages have had operator overloading for many years of = even decades - are there really huge problems in those languages? >=20 Depends on what you consider to be "huge" problems. Many people feel = operator overloading is a cure for an ailment where the medicine is the = worse than the disease. =20 Just google "operator overloading considered harmful." But in case you = can't be bothered to google, here are just three of many opinions: - = https://medium.com/@fmmarzoa/say-no-to-operator-overloading-7b21aa06c518 = = - = https://cafe.elharo.com/programming/operator-overloading-considered-harmfu= l/ = - = https://www.oreilly.com/library/view/sams-teach-yourself/0672324253/067232= 4253_ch21lev1sec4.html = =20 > If yes, maybe PHP can learn from some of the problems there (which I = think the original RFC tried to carefully consider), but as far as I = know the usage of operator overloading is niche in languages which = support it, depending on use case - some people like it, some don't, but = they do not seem to be a big problem for these languages or their code = in general. Maybe you have some sources on actual problems in other = languages? >=20 Besides the links above, my sources are personal experience over 30+ = years of programming. > Personally I would love my Money class to finally have operators = instead of the current "plus", "minus", "multipliedBy" (and so on) = methods which are far less readable. I would only use operator = overloading on a few specific classes, but for those the readability = improvement would be huge. Also, being able to override comparison = operators for objects would be very useful, because currently using =3D=3D= and =3D=3D=3D with objects is almost never helpful or sufficient. >=20 And I support that. Just have developers or yourself opt-in to use = operators on your Money class. =20 Requiring an opt-in is a safer way to go, and NOT requiring an opt-in = means we would forever have to live with any downsides that opt-in would = reign in.=20 So how is requiring an opt-in a bad idea and not a reasonable = compromise? =20 > On Sep 17, 2024, at 1:22 PM, Jordan LeDoux = wrote: > While I do not presume to speak for all voters (I don't even have = voting rights myself), my feeling from all of the conversations I have = had over almost the last 4 years is that implementing your suggestion = would virtually guarantee that the RFC is declined. Well, given that few have commented on the idea yet, it seems premature = to make that assumption.=20 Why not wait until we get more feedback rather than nix it up front? > You are suggesting providing a new syntax (which voters tend to be = skeptical of) to create a situation where more errors occur > (which voters tend to be skeptical of) So, type hinting is all about creating errors. Yet almost everyone on = the list is super excited about adding more and better type hinting. =20 Given that, I would argue that you are claim is, if not false, at least = far too simplistic to be a valid claim. > to solve a problem which can be solved with existing syntax by simply = type guarding your code to not allow any objects near your operators = (which voters tend to be skeptical of) You mean you assume it can be solved with existing syntax. > for which I cannot find any code examples that explain the problem it = is solving (which voters tend to skeptical of). Frankly, it is difficult to come up with examples because examples are = predicating on junior developers doing dumb things that would never = occur to a senior developer because they know better. =20 But I prepared one such hypothetical example using `function equals()` = as a stand-in for `operator =3D=3D` so the code will run:=20 https://3v4l.org/6GTKb#v8.3.11 I feel certain I could come up with several others, but I unfortunately = have already exceeded my time allotment for the day. > On Sep 17, 2024, at 1:43 PM, Jordan LeDoux = wrote: >=20 > The problem I was trying to solve involved lots of things that cannot = be represented well by primitive types (which is presumably why they are = classes in the first place). Things like Complex Numbers, Matrices, or = Money. Money can be converted to a float of course (or an int depending = on implementation), but Money does not want to be added with something = like request count, which might also be an int. Or if it does, it = probably wants to know exactly what the context is. There are lots of = these kinds of value classes that might be representable with scalars, = but would lose a lot of their context and safety if that is done. >=20 > On the other hand, Money would probably not want to be multiplied with = other Money values. What would Money squared mean exactly? Things like = this are very difficult to control for if all you provide is a way to = control casting to scaar types. Given your pushback you had on even having an opt-in for operator = overload, why not instead prepare RFCs for built-in Complex Number, = Matrix, and Money classes? =20 That was what I argued three years ago yet no action was taken on it so = I get the impression that not having operator overloading for those kind = of classes is actually not that big of a deal as someone would have = pushed a class-specific RFC in that 3 years time. As an aside, I think it would be a LOT more valuable to have a built-in = standard that becomes always available as a starting point for everyone = doing maths rather than having a bunch of different, incompatible and = non-composable and edge-case buggy classes for these uses out on Github. -Mike= --Apple-Mail=_0AC6DC6E-4F2D-4025-BE87-6D54AE8E55F8 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8
On = Sep 17, 2024, at 6:04 AM, Andreas Leathley <a.leathley@gmx.net> = wrote:

=20 =20
On 17.09.24 11:14, Mike Schinkel = wrote:
How would a = developer know if they are using an object that has operators, unless = they study all the source code or at least the docs (assuming there are = good docs, which there probably are not?)

How is that different from using a method on an object? = Operators are roughly speaking a different syntax for methods, and if you use an object method, you have to know about it or look up what it does.

When you see a method call, you = know 100% of the time that it calls a method.

Assuming operator overloading, when you see an = operator used with variables, you will no longer be able to rely on your = knowledge of how the operator work as it might use the built-in operator = OR it might call a method. Most of the time it will be the former, = occasionally the latter.  

And = since a method would only be called occasionally I would likely get = tired of searching to see if there is a method being called and just = assume there isn't. Not smart, but having to track down potential = methods for every operator use would just be far too tedious.

Also, getting to the implementation of = operators would likely be just as easy as looking up methods nowadays, because IDEs would support that kind of lookup.

The more generic named the = method, the more IDEs struggle with finding methods, and operators are = about as generic as you can get.

Most framework and library code = is by now type-hinted - I would have understood this argument when operator overloading would be implemented into PHP 5.x, where many classes and functions got values and had no enforced types, so they might have expected an int, yet an object with operator overloading might work but in weird ways, because there were no type hints for int. I cannot see this situation now at all - if a Symfony component wants an int, you cannot pass in an object. If a Symfony component wants a Request object, it will not use operators that it does not expect to be there, even if you would extend the class and add operator support. Using operators implies you know you can use operators, otherwise it will be a fatal error (except for = comparisons).

ANY object could have an = operator overload on `=3D=3D` and/or `=3D=3D=3D` and have those behave = differently.

I also just checked and = Symfony has many parameters type hinted as Stringable and numerous = interfaces that extend Stringable.  Any object = that implements Stringable could also add operator overloads = and introduce subtle bugs into those functions.

Symfony has numerous interfaces that extend = Countable.  Any object that implements Countable could = also add operator overloads and introduce subtle bugs into those = functions.

Symfony = has numerous interfaces that extend ArrayAccess.  Any object = that implements ArrayAccess could also add operator = overloads and introduce subtle bugs into those = functions.

Further =E2=80=94= if operator overloads are added =E2=80=94 there will likely be demand = for more "-able" type interfaces, or some other way to make objects = behave more like scalar types. If we have opt-in then code is safe. If = we do not have opt-in then unintended consequences are possible, if not = likely.

=46rom your arguments it also seems you are afraid everybody = will use operator overloading excessively and unnecessarily. This seems very unlikely to me - it is not that useful a feature, except for certain situations.

We will have to = agree to disagree on that then. Look at what happened when is was added = to C++; people when crazy with it and it was numerous years before the = community moderated their behavior.

Many other = languages have had operator overloading for many years of even decades - are there really huge problems in those languages?

Depends = on what you consider to be "huge" problems.  Many people feel = operator overloading is a cure for an ailment where the medicine is the = worse than the disease.  

Just = google "operator overloading considered harmful."  But in case you = can't be bothered to google, here are just three of many = opinions:


If yes, maybe PHP can learn from some of the problems there (which I think the original RFC tried to carefully consider), but as far as I know the usage of operator overloading is niche in languages which support it, depending on use case - some people like it, some don't, but they do not seem to be a big problem for these languages or their code in general. Maybe you have some sources on actual problems in other = languages?

Besides the links = above, my sources are personal experience over 30+ years of = programming.

Personally I would love my Money class to finally = have operators instead of the current "plus", "minus", "multipliedBy" (and so on) methods which are far less readable. I would only use operator overloading on a few specific classes, but for those the readability improvement would be huge. Also, being able to override comparison operators for objects would be very useful, because currently using =3D=3D and =3D=3D=3D with objects is = almost never helpful or sufficient.

And I support that.  Just have developers or yourself = opt-in to use operators on your Money class.  

Requiring an opt-in is a safer way to go, and NOT = requiring an opt-in means we would forever have to live with any = downsides that opt-in would reign in. 

So how is requiring an opt-in a bad idea and not a = reasonable compromise?  

On Sep 17, 2024, at 1:22 PM, Jordan LeDoux = <jordan.ledoux@gmail.com> wrote:
While I = do not presume to speak for all voters (I don't even have voting rights = myself), my feeling from all of the conversations I have had over = almost the last 4 years is that implementing your suggestion would = virtually guarantee that the RFC is declined.

Well, given that few have = commented on the idea yet, it seems premature to make that = assumption. 

Why not wait until we get = more feedback rather than nix it up front?

You are suggesting = providing a new syntax (which voters tend to be skeptical of) to create = a situation where more errors occur
(which voters tend to be skeptical of)

So, type hinting is all about = creating errors.  Yet almost everyone on the list is super excited = about adding more and better type hinting.  

Given that, I would argue that you are claim = is, if not false, at least far too simplistic to be a valid claim.

to solve = a problem which can be solved with existing syntax by simply type = guarding your code to not allow any objects near your operators = (which voters tend to be skeptical of)

You mean you assume it can be solved with existing syntax.

for which = I cannot find any code examples that explain the problem it is solving = (which voters tend to skeptical of).

Frankly, it is difficult to come up with examples because = examples are predicating on junior developers doing dumb things that = would never occur to a senior developer because they know = better.  

But I prepared one such = hypothetical example using `function equals()` as a stand-in for = `operator =3D=3D` so the code will run: 

https://3v4l.org/6GTKb#v8.3.11

I feel certain I could come up with several others, but I = unfortunately have already exceeded my time allotment for the day.

On Sep 17, 2024, at 1:43 PM, Jordan LeDoux = <jordan.ledoux@gmail.com> wrote:

The = problem I was trying to solve involved lots of things that cannot be = represented well by primitive types (which is presumably why they are = classes in the first place). Things like Complex Numbers, Matrices, or = Money. Money can be converted to a float of course (or an int depending = on implementation), but Money does not want to be added with something = like request count, which might also be an int. Or if it does, it = probably wants to know exactly what the context is. There are lots of = these kinds of value classes that might be representable with scalars, = but would lose a lot of their context and safety if that is = done.

On the = other hand, Money would probably not want to be multiplied with other = Money values. What would Money squared mean exactly? Things like this = are very difficult to control for if all you provide is a way to control = casting to scaar types.

Given your pushback you had on even having an = opt-in for operator overload, why not instead prepare RFCs for built-in = Complex Number, Matrix, and Money classes?  

That was what I argued three years ago yet no = action was taken on it so I get the impression that not having operator = overloading for those kind of classes is actually not that big of a deal = as someone would have pushed a class-specific RFC in that 3 years = time.

As an aside, I think it would = be a LOT more valuable to have a built-in standard that becomes always = available as a starting point for everyone doing maths rather than = having a bunch of different, incompatible and non-composable and = edge-case buggy classes for these uses out on Github.

-Mike
= --Apple-Mail=_0AC6DC6E-4F2D-4025-BE87-6D54AE8E55F8--