> On Aug 8, 2021, at 3:41 AM, Jordan LeDoux <jordan.led...@gmail.com> wrote:
> 
> Off the top of my head here are some of the use cases that I think benefit 
> greatly from this:
> 
> - Complex number objects
> - Fractions objects
> - Matrix objects (math)
> - Vector objects (math)
> - Time/Date intervals
> - Collections
> - Arbitrary precision numbers (which are usually represented as a string in 
> PHP)

Thank you for going to the effort to list those out.  I'd like to categorize 
them, if I may?

------------------------
General Purpose
- Collections

I'm not sure if you there is something about Collections related to Math that 
makes them applicable for operator overloading but otherwise I would be 
question whether there would be a strong consensus around what operators a 
collection would implement and how those operators would behave.  

If you think there would be a strong consensus regarding collections and 
operators maybe you could elaborate on which operators would apply and what 
each would do?

------------------------
Date/Time
- Time/Date intervals

This seems to me to be a great use-case. Ironically we already have the 
DateInterval class as well as methods that operate on DateTime objects that add 
and subtract DateIntervals as well as proving the different between two dates.

Because we already have the classes, this seems to be a perfect place to start 
with an RFC to introduce operators to PHP for DateTime and DateInterval 
objects.  

More on this in a bit.

------------------------
Math
- Complex number objects
- Fractions objects
- Matrix objects (math)
- Vector objects (math)
- Arbitrary precision numbers (which are usually represented as a string in PHP)

And these all seem like strong candidates for classes that could use operators. 
 

But mathematical concepts are pretty well set in stone; are there really this 
many different ways to implement them (rhetorical question)?:

> Here are some actual user libraries which would probably use them:
> 
> - samsara/fermat (this library is mine as a matter of disclosure)
> - brick/math
> - markbaker/complex
> - markbaker/matrix
> - krowinski/bcmath-extended
> - malenki/math
> - markrogoyski/math-php
> - rubix/tensor
> - numphp/numphp
> - mcordingley/linear-algebra

Looking at the tests for just complex numbers in just three (3) of these I see 
distinctly different choices, choices which appear to be arbitrarily made by 
each developer:

1. 
https://github.com/SamsaraLabs/FermatComplexNumbers/blob/master/tests/Samsara/Fermat/Values/ImmutableComplexNumberTest.php
2. 
https://github.com/MarkBaker/PHPComplex/blob/3.0/unitTests/classes/src/ComplexOperationTest.php
3. https://github.com/malenkiki/math/blob/master/tests/Number/ComplexTest.php

I really can't critique the math aspects nor fully grok your use-cases, but do 
I understand the benefit of standardization, and it seems like PHP would gain 
greatly for use in the math domain by introducing classes written in C and 
baked into core for each of your math use-cases.

And the same with the Money classes that Rowan proposed.

But I know you objected to that approach....more on that at the end.

> As for constraints... well, if I had absolutely no concern for implementation 
> at all, and was just designing what constraints to put on the magic methods, 
> they would be:

> 1. void is an unsupported return, and failing to return a value results in an 
> error.
> 2. Variables outside the scope of the method cannot be set. This includes 
> properties on the object which is defining the magic method, and includes 
> sets that occur in called functions and methods.

When I mentioned "constrained" I was referring to Rowan's distinction:

> On Aug 7, 2021, at 3:07 PM, Rowan Tommins <rowan.coll...@gmail.com> wrote:
> In a previous thread [1], I wrote about two fundamental design approaches to 
> operator overloading:
> 
> a) Treating operators as arbitrary symbols, which can be assigned any 
> operation which makes sense in a particular domain.
> b) Treating operators as having a fixed meaning, and allowing custom types to 
> implement them with that meaning.

Where a) would be "unconstrained" and b) would be "constrained."  I think you 
assumed I was referring to something else.

> In any case, it is certainly possible that we could instead implement some 
> magic *objects* which can be extended that have built-in overloading in 
> specific ways. I think this is actually worse for the following reasons:
> 
> 1. It would be far less obvious to the programmer that an object would behave 
> differently with a given operator, because the behavior wouldn't be 
> documented in the code itself.
> 2. It would require many different implementations, some of them very close 
> to each other, to cover the same set of use cases.
> 3. It would likely result in some maintainability concerns as more users 
> demanded different DSL type implementations be included in core, and the 
> existing ones would need to be maintained.

I am going to challenge your justifications:

-----
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 functions 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.

-----
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.

-----
3. Regarding maintainability concerns. Code generally doesn't rot unless the 
requirements change. Are requirements going to change? If yes, then its 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 fleshed 
out, to the best of the list's collective ability.

> As I've mentioned, while I understand that to many programmers commutativity 
> is a requirement of a good language, it is explicitly incorrect to require 
> commutativity for math operations.

I only mentioned commutativity because others mentioned it. I personally don't 
have the math chops so I defer to you here.

> On Aug 8, 2021, at 7:25 AM, Jordan LeDoux <jordan.led...@gmail.com> wrote:
> On Sun, Aug 8, 2021 at 3:08 AM Deleu <deleu...@gmail.com> wrote:
>> However my biased still exists: it would be awful to have to understand
>> what `+` is doing for every file of every library or even different objects
>> in the same project.
> 
> May I ask why? Python does not get much criticism that I can find for its
> implementation of operator overloading.
> ...
> There are many languages that provide operator overloading, and I've never
> seen it described as a bad feature in any of them.

While it is hard to objectively quantify how much is "much" this gentlemen — a 
programming teacher — had some choice words to say about 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’s an aberration to be shunned."

He feels even more strongly about the perils of userland operator overloading 
than I do!

> So while I'm aware of the concerns, I'm unconvinced they are founded in
> reality. That is, I think the concerns about maintainability and complexity
> may be unfounded in real world scenarios. However it is an extremely
> consistent opinion here, and I would like to understand *why* it is viewed
> as bad for the language in a more concrete way if that is possible.

Similarly I am unconvinced that adding operator overloading who not end up 
making PHP programs brittle and that the community would come to loath and wish 
we could turn back time to remove.

Using operators for most classes would be a leaky abstraction. Developers under 
the gun to deliver projects for their employers or client are rarely going to 
take the in-depth time required to fully understand the abstraction and all the 
ramifications of adding  operators, they are just going to do it because "it 
will seem like a good idea at the time."  And that will result in code using 
operators where the concept of add, subtract, multiply, divide etc will be 
constantly shifting as a project evolves. Just like what a method means is 
constantly shifting.

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 should always be 
implemented as a named function.  A first I was annoyed that the 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?

Most use-cases are not clear and compelling enough to elevate a named function 
call to an operator. And for the relatively few use-cases that *are* clear and 
compelling it would make sense for the use-case to be fully fleshed out and 
then an object created in C and added to PHP, just like DateTime and 
DateInterval were created.

> If I wrote that in my RFC just to get the overrides that benefited the work
> I do, primarily around math, accepted into core, it would virtually
> guarantee that actual operator overrides would never come for other types
> of applications. Every future RFC on this topic would be riddled with
> comments about the existing abstract classes, and how all future
> implementations have to be done in a similar way. This would artificially
> increase the barrier to acceptance for other domains in a way that I do not
> believe improves the language, serves the users of the language, or allows
> for flexible development of the language into the future.
> 
> So while I acknowledge that it may be a good middle ground (and even one
> that I personally would accept for my own implementations and code), I am
> unwilling to be the person that locks everyone *else* out of this language
> feature by making future RFCs more constrained and difficult to pass.
> 
> I constrained this RFC to math operators not because it's the only domain
> that would benefit, but because I think it's the one with the most
> straightforward and understandable domain uses for everyone on this list
> and represents the "minimum" version of the feature.


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.  

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.

Given some people feel operator overloading is problematic in other languages 
and some languages like Go explicitly chose not to add it it would behoove us 
to tread very conservatively instead of just adding it before we have any 
experience with operator overloading in PHP. Right now we don't know what we 
don't yet know.

If we were to — for example — 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.

After a while, we'd have numerous classes in PHP supporting operators. At that 
people we could have the  confidence needed to decide it and how to implement 
general-purpose operator overloading.

But one thing is certain. While we can go from special one-off classes that 
support operator overloading to later adding general-purpose operator 
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.

-Mike
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to