On Mon, Dec 20, 2021 at 4:43 PM Andreas Hennings <andr...@dqxtech.net>
wrote:

> > The exact position of where that trade-off is 'worth it' is going to
> > be different for different people. But one of the areas where PHP is
> > 'losing ground' to Python is how Python is better at processing data
> > with maths, and part of that is how even trivial things, such as
> > complex numbers, are quite difficult to implement and/or use in
> > userland PHP.
>
> Could be interesting to look for examples in Python.
> I was not lucky so far, but there must be something..
> ...
> Btw it would be really interesting to find such a list of
> recommendations for Python.
> The reference you added,
> https://isocpp.org/wiki/faq/operator-overloading#op-ov-rules, is for
> C++, which is less comparable to PHP than Python is.
>

During my research phase of this RFC I was able to review many different
takes on this from the Python space. Here is one example of a community
discussion about it:

https://stackoverflow.com/questions/1552260/rules-of-thumb-for-when-to-use-operator-overloading-in-python

One of the interesting things here is that *most* of the warnings for
Python users discussed at the link are actually *designed* to not be issues
within this RFC. That's on purpose of course, I tried to think about how
some of the design issues in Python could be improved.

In Python, the +, +=, and ++ operators are implemented independently. In
this RFC, you may only overload the + operator, and then the VM handles the
appropriate surrounding logic for the other operators. For instance, with
++$obj or $obj++, you want to return either a reference or a copy,
depending on if it's a pre- or post-increment. In this RFC, the handling of
when the ZVAL is returned is handled by the VM automatically, and a
subordinate call to the opcode for + is made when appropriate. The
reassignment += works similarly, with the ZVAL's being assigned
automatically and a subordinate call. This vastly reduces the surface for
inconsistency.

Another warning that is discussed is around overloading the == operator. A
big reason for this is that the Python overloads do NOT require the ==
overload to return a particular type. Because of this, overloading the ==
operator can result in situations in Python where it is difficult to
compare objects for equality. However, in this RFC the == operator can only
be overloaded to return a boolean, so the semantic meaning of the operator
remains the same. Though you could of course do something terrible and
mutate the object during an equality comparison, you must return a boolean
value, ensuring that the operator cannot be co-opted for other purposes
easily. Additionally, the != and == cannot be independently implemented in
this RFC, but can in Python.

In Python the inequality operators can be implemented independently: >, >=,
<=, <. They *also* are not required to return a boolean value. In this RFC,
independent overloads for the different comparisons are not provided.
Instead, you must implement the <=> operator and return an int. Further,
the int value you return is normalized to -1, 0, 1 within the engine. This
ensures that someone could not repurpose the > operator to pull something
out of a queue, for instance. (They could still repurpose >> to do so, but
since the shift left and shift right operators are not used in the context
of boolean algebra often in PHP, that's far less dangerous.) A future scope
that I plan on working on is actually having an Ordering enum that must be
returned by the <=> overload instead, that even more explicitly defines
what sorts of states can be returned from this overload.

A lot of years of language design experience have been invested into
operator overloading across various languages. I wanted to at least try to
take advantage of all this experience when writing this RFC. It's why I say
that PHP will end up with the most restrictive operator overloads of any
language I'm aware of. There will still be pain points (returning union
types is not an easy thing to eliminate without full compile time type
resolution), but as far as buggy or problematic code, there's a lot about
this RFC that works to prevent it.

A determined programmer can still create problems, but I find this
(personally) an uncompelling argument against the feature. There are *many*
features in PHP that a determined programmer can create problems with. The
__get, __set, __call, and __callStatic magic methods can actually allow you
to overload the *assignment* operator for certain contexts. The __toString
magic method can already be used to mutate the object through a simple
concatenation. The ArrayAccess interface forces you to deal with the union
of *all* types (mixed), even when that doesn't make sense. And these are
just the PHP features that in some way already interact with operators and
objects in special circumstances.

Jordan

Reply via email to