Hello all,
I took a while away after my operator overload RFC was declined. I've been
mulling for the last few months how to move forward while respecting the
concerns and feedback of those who abstained and those who voted against.
But I feel like a separate discussion needs to happen first after
considering many different approaches.
There is Considerable Demand For Improved Control of Operators with
Objects
This doesn't apply to all operators. I have not seen any comments in the
last few months of digging of people who are desperate for the pow operator
( ** ) for instance. However, many people who work with math in PHP have
use for at least the arithmetic operators and I see this comment frequently.
Totally separate from the math domain, I've seen many comments about the
desire to control the comparison operators: >, >=, ==, <=, <, !=, <>. This
is something that would have numerous applications outside of mathematics,
and there's even been an RFC worked on (that was declined in 2018) by Rudi
to implement just comparisons.
Different Voters Have Different Concerns
This is an issue that almost all RFC authors must deal with of course, but
this particular subject suffers from it more severely than most. For
instance, in some of the past proposals that were more limited than mine,
there were comments that a full operator overloading solution should be
provided instead of something halfway.
However one of the comments I received more than once was that I should
separate out the comparison operators into its own RFC, since those have
applications outside the math domain.
Is Math A Valid Use Case?
One of the more shocking (to me personally) pieces of feedback that I
received from more than one person is that math is not a valid use case in
PHP. I am... unsure about what to think of this opinion. I guess I would
like to discuss and find out if this is widely believed among voters.
Non-Breaking Engine Changes
The way that equality and comparison evaluation is done in the engine makes
it impossible for certain kinds of overloading to be done, even in
extensions. This isn't because that was an intended restriction, I
discussed this issue with CMB and provided a PR a few months ago to resolve
this, however it has remained in limbo:
https://github.com/php/php-src/pull/7973
Overall Vision
I'm not sure at this point how voters think objects and operators should
work together into the future. I'd like to see if anyone is willing to have
high-level discussion about the ideas, instead of picking at the
implementation or details of a particular RFC.
Jordan
Hello all,
I took a while away after my operator overload RFC was declined. I've been
mulling for the last few months how to move forward while respecting the
concerns and feedback of those who abstained and those who voted against.
But I feel like a separate discussion needs to happen first after
considering many different approaches.
Speaking only for myself, of course...
There is Considerable Demand For Improved Control of Operators with
Objects
This doesn't apply to all operators. I have not seen any comments in the
last few months of digging of people who are desperate for the pow operator
( ** ) for instance. However, many people who work with math in PHP have
use for at least the arithmetic operators and I see this comment frequently.Totally separate from the math domain, I've seen many comments about the
desire to control the comparison operators: >, >=, ==, <=, <, !=, <>. This
is something that would have numerous applications outside of mathematics,
and there's even been an RFC worked on (that was declined in 2018) by Rudi
to implement just comparisons.
I would group object operators into 4 categories/levels.
- Object-universal operators. This would be support for operators that make sense in all domains. Mainly this is the comparison operators but there may be others.
- Arithmetic operators. The 4 basic operations. Maybe even just 3 (excluding division as it's a bit more complex than the others conceptually).
- Full operator overloading: If an operator exists, a class can override it, on principle, even if there's no obvious common use case.
- Custom overloading: User-space can define additional operators for specific objects.
Jordan's RFC was effectively level 3, with a syntax designed to be extensible to level 4 in the future if desired. Naturally the line between these levels if a little bit fuzzy and there's some overlap.
Different Voters Have Different Concerns
This is an issue that almost all RFC authors must deal with of course, but
this particular subject suffers from it more severely than most. For
instance, in some of the past proposals that were more limited than mine,
there were comments that a full operator overloading solution should be
provided instead of something halfway.However one of the comments I received more than once was that I should
separate out the comparison operators into its own RFC, since those have
applications outside the math domain.
See above regarding "levels" of support.
Is Math A Valid Use Case?
One of the more shocking (to me personally) pieces of feedback that I
received from more than one person is that math is not a valid use case in
PHP. I am... unsure about what to think of this opinion. I guess I would
like to discuss and find out if this is widely believed among voters.
PHP is today rarely used for heavy-math use cases. It's mostly line-of-business applications, aka "over-engineered ways of concatenating strings out of a database." Historically it's been too slow for that, which lead to no community around it, so no one did it, so no focused improvements in that area, so... Infinite loop. Python got most of that attention instead.
However, the JIT and FFI work have quite frankly very little use other than computation intensive (ie, math) use cases, and those were added without issue despite having APIs that are extremely crappy. :-) So I don't understand the "math doesn't matter" argument either; if it doesn't matter, we wouldn't have needed JIT or FFI either.
I frankly think this is a red herring; it's a "I don't do heavy math work in PHP, so arguing that feature X makes PHP better for math carries no weight." It shouldn't be read as "PHP being good at complex computations is bad in itself." (If anyone does actually believe that, I'd say speak up but I'd just tell you that you're wrong from the get-go, so maybe let's not pick that fight and leave it as a hypothetical. :-) )
Non-Breaking Engine Changes
The way that equality and comparison evaluation is done in the engine makes
it impossible for certain kinds of overloading to be done, even in
extensions. This isn't because that was an intended restriction, I
discussed this issue with CMB and provided a PR a few months ago to resolve
this, however it has remained in limbo:
https://github.com/php/php-src/pull/7973Overall Vision
I'm not sure at this point how voters think objects and operators should
work together into the future. I'd like to see if anyone is willing to have
high-level discussion about the ideas, instead of picking at the
implementation or details of a particular RFC.Jordan
I am always down for high-level ideas discussions. :-P
As even the detractors noted, the previous RFC is probably the best design that could be done, given PHP's existing nature. So aside from the operator
syntax for semi-methods, I don't think there's much to discuss there.
Conceptually, it is mostly true that any operator overload is simply syntactic sugar for a method call, and thus there's nothing that operator overloading enables that you can't do otherwise in more "self-documenting" ways (ie, methods). I think that was the main pushback, that overloading just adds less self-documenting syntactic sugar over stuff you can already do.
However, there are 2 holes in that argument.
One, the same is true of all operators on scalars, too. At a conceptual, computer-science-y level, all operators are shorthands for function calls. 5 + 3
is simply a shorthand for add(int, int)
called with 5 and 3. (In some languages, scalar operators are literally implemented as functions/methods.) The only reason some common functions get magical short-hand operator syntax is historical precedent. A very common historical precedent, but still, there's nothing intrinsic in integer addition that makes it necessarily have a magic symbol shorthand for its function. In a pure sense, all operators are optional syntactic sugar. (Give or take language-specific optimization that could be designed any way you want it to.)
Two, it's not entirely true that operator overloading offers no new functionality. PHP has a number of operations that rely on comparisons in particular that do not have any override mechanism. For example, in_array()
with weak comparison can kinda-sorta work on arrays of objects, but only using the native "are each of the properties ==" algorithm. There is no way to override that to some other definition of equal, the way the usort()
family of functions allows for custom user-space comparisons. in_array()
offers no equivalent. So if you wanted to have a unique-list of objects (a set), you need to do an awful lot of manual work with custom object identity logic and avoiding all of PHP's built-in list handling features. It's technically possible to do, but at this point it's disingenuous to call it simply "syntactic sugar." What's missing is, effectively, an engine-hook for equality.
That argument is less persuasive for the higher-level operators, like arithmetic or pow or modulus, as I am not aware of any missing "engine hook" situations for those.
My recommendation would be to use the same syntax and model as before and just target object-universal operators, ie, comparisons. (Level 1 from above.) That gets the syntax in place, and lets us flush out the engine hook weirdness. If we could get that to pass, it would at least get people comfortable with the idea and concept. The higher level parts could then be an easier sell in the future in a version or two once people have gotten more used to the idea.
On the topic of the specific syntax, the trade-offs of magic methods would be:
- The names tell you what it is for, not what it looks like. This may or may not be a good thing.
- It doesn't extend nicely to level 4 if we ever decide to go there. (Whether you consider this good or bad is subjective.)
For the operator
syntax, it's the other way around:
- The name tells you what it looks like without restricting what you can use it for. This may or may not be a good thing.
- Extending to later levels is syntactically trivial, including to level 4 if we want. (Again, whether that's a pro or a con is subjective.)
I don't know if that particular syntax choice was a deal breaker for anyone but Nikita, though.
--Larry Garfield
On Sat, May 7, 2022 at 11:40 AM Larry Garfield larry@garfieldtech.com
wrote:
I would group object operators into 4 categories/levels.
- Object-universal operators. This would be support for operators that
make sense in all domains. Mainly this is the comparison operators but
there may be others.- Arithmetic operators. The 4 basic operations. Maybe even just 3
(excluding division as it's a bit more complex than the others
conceptually).- Full operator overloading: If an operator exists, a class can override
it, on principle, even if there's no obvious common use case.- Custom overloading: User-space can define additional operators for
specific objects.Jordan's RFC was effectively level 3, with a syntax designed to be
extensible to level 4 in the future if desired. Naturally the line between
these levels if a little bit fuzzy and there's some overlap.
...
I frankly think this is a red herring; it's a "I don't do heavy math work
in PHP, so arguing that feature X makes PHP better for math carries no
weight." It shouldn't be read as "PHP being good at complex computations
is bad in itself." (If anyone does actually believe that, I'd say speak up
but I'd just tell you that you're wrong from the get-go, so maybe let's not
pick that fight and leave it as a hypothetical. :-) )
...
My recommendation would be to use the same syntax and model as before and
just target object-universal operators, ie, comparisons. (Level 1 from
above.) That gets the syntax in place, and lets us flush out the engine
hook weirdness. If we could get that to pass, it would at least get people
comfortable with the idea and concept. The higher level parts could then
be an easier sell in the future in a version or two once people have gotten
more used to the idea.
Of the people who did vote no and also provided me feedback, there were
mainly three reasons given (some in public such as on this list, and some
in private in more direct conversation):
- Math is not a valid use case.
- Operator overloading for objects is something I will vote against in any
context for any design, no matter the argument or evidence provided. - Operator overloading presents problems for static analysis and tooling
which are more significant than the benefits.
I could argue against all three positions, but as you noted, I don't think
argument or debate is really helpful right now. Instead I'd like to talk at
a more high level about what sort of long-term future PHP contributors and
voters see for objects when it comes to allowing developers to control
object behavior.
I like the way you organized the different levels of support within the
feature, it's a good organizational structure for thinking about the
feature-set. Given the feedback though, I found myself a little concerned
that if I created a Level 1 proposal, it's very possible that the people in
groups 1 and 3 above might vote for it. However, in doing so it's also very
possible that all the use-cases those voters care about would then be
covered, and many would then block anything which helps use-cases they do
not commonly use. In essence, the particular feedback I received made me
concerned that passing a Level 1 RFC would basically guarantee that Level
2+ would never happen until the voter base itself was significantly changed.
Even so... I think I agree with your suggestion at this point. At the very
least, even if my concern above was proven true, it would then at least be
possible for me to provide an extension for PHP which addresses some of
the shortcomings for math.
The main issue when it comes to comparisons is addressed in the PR I
linked, which basically boils down to "for objects, it makes sense for
equatable and comparable to be separated sometimes". Whether this involves
a fall-through in the VM for objects as done in my linked PR, or involves
new handlers for objects as CMB commented on that PR instead, it's actually
a very minor change technically within the engine to implement Level 1
support as you described it.
Jordan
I like the way you organized the different levels of support within the
feature, it's a good organizational structure for thinking about the
feature-set. Given the feedback though, I found myself a little concerned
that if I created a Level 1 proposal, it's very possible that the people in
groups 1 and 3 above might vote for it. However, in doing so it's also very
possible that all the use-cases those voters care about would then be
covered, and many would then block anything which helps use-cases they do
not commonly use. In essence, the particular feedback I received made me
concerned that passing a Level 1 RFC would basically guarantee that Level
2+ would never happen until the voter base itself was significantly changed.
Creating "smaller steps" (within a certain feature set) seems to have
been the more successful route for PHP RFCs and not necessarily slowed
down further enhancements, in my estimation. The more one single RFC is
about, the more there is to possibly dislike. It is also easier to
reason about less changes at any one point in time and make a more
compelling case for the changes. So I think your overall goal of more
feature-complete operator overloading remains viable even if you start
"small" with a level 1 proposal.
Of the people who did vote no and also provided me feedback, there were
mainly three reasons given (some in public such as on this list, and some
in private in more direct conversation):
- Math is not a valid use case.
- Operator overloading for objects is something I will vote against in any
context for any design, no matter the argument or evidence provided.- Operator overloading presents problems for static analysis and tooling
which are more significant than the benefits.I could argue against all three positions, but as you noted, I don't think
argument or debate is really helpful right now. Instead I'd like to talk at
a more high level about what sort of long-term future PHP contributors and
voters see for objects when it comes to allowing developers to control
object behavior.I like the way you organized the different levels of support within the
feature, it's a good organizational structure for thinking about the
feature-set. Given the feedback though, I found myself a little concerned
that if I created a Level 1 proposal, it's very possible that the people in
groups 1 and 3 above might vote for it. However, in doing so it's also very
possible that all the use-cases those voters care about would then be
covered, and many would then block anything which helps use-cases they do
not commonly use. In essence, the particular feedback I received made me
concerned that passing a Level 1 RFC would basically guarantee that Level
2+ would never happen until the voter base itself was significantly changed.
It's possible. However, it wouldn't be the first feature that has laid dormant for several years until the voting population turned over. (Scalar types and attributes are the first such examples that come to mind, but I'm sure there's others.)
Also, not proposing level 1 on the grounds that it would reduce the argument for level 2/3 in the future would effectively be holding level 1 functionality "hostage" for the more advanced versions, which... would probably not work out well. :-) (Even if that's not your intent, it would come off that way.)
Conversely, giving people a version or three to work with level 1 operator overloads may get more people comfortable with the concept and thus make them more amenable to levels 2 or 3 in the future.
Whether there's enough support for level 1 for it to pass at the moment, I honestly don't know.
Even so... I think I agree with your suggestion at this point. At the very
least, even if my concern above was proven true, it would then at least be
possible for me to provide an extension for PHP which addresses some of
the shortcomings for math.The main issue when it comes to comparisons is addressed in the PR I
linked, which basically boils down to "for objects, it makes sense for
equatable and comparable to be separated sometimes". Whether this involves
a fall-through in the VM for objects as done in my linked PR, or involves
new handlers for objects as CMB commented on that PR instead, it's actually
a very minor change technically within the engine to implement Level 1
support as you described it.Jordan
I defer to you and others on the technical implementation, as it's well outside my wheelhouse.
--Larry Garfield
On Mon, May 9, 2022 at 2:25 PM Larry Garfield larry@garfieldtech.com
wrote:
Also, not proposing level 1 on the grounds that it would reduce the
argument for level 2/3 in the future would effectively be holding level 1
functionality "hostage" for the more advanced versions, which... would
probably not work out well. :-) (Even if that's not your intent, it would
come off that way.)
Yes, I also realize that, which is another reason I'm thinking that doing
comparison-only overloads first might be the better way forward.
Hello all,
I took a while away after my operator overload RFC was declined. I've been
mulling for the last few months how to move forward while respecting the
concerns and feedback of those who abstained and those who voted against.
But I feel like a separate discussion needs to happen first after
considering many different approaches.There is Considerable Demand For Improved Control of Operators with
Objects
This doesn't apply to all operators. I have not seen any comments in the
last few months of digging of people who are desperate for the pow operator
( ** ) for instance. However, many people who work with math in PHP have
use for at least the arithmetic operators and I see this comment frequently.Totally separate from the math domain, I've seen many comments about the
desire to control the comparison operators: >, >=, ==, <=, <, !=, <>. This
is something that would have numerous applications outside of mathematics,
and there's even been an RFC worked on (that was declined in 2018) by Rudi
to implement just comparisons.Different Voters Have Different Concerns
This is an issue that almost all RFC authors must deal with of course, but
this particular subject suffers from it more severely than most. For
instance, in some of the past proposals that were more limited than mine,
there were comments that a full operator overloading solution should be
provided instead of something halfway.However one of the comments I received more than once was that I should
separate out the comparison operators into its own RFC, since those have
applications outside the math domain.Is Math A Valid Use Case?
One of the more shocking (to me personally) pieces of feedback that I
received from more than one person is that math is not a valid use case in
PHP. I am... unsure about what to think of this opinion. I guess I would
like to discuss and find out if this is widely believed among voters.
I will repeat what I suggested back before the RFC was voted on, and that is you consider starting your campaign for operator overloads with an RFC to add a built-in Math class (or set of classes) to PHP, one(s) that can have all the operator overloading it/they need(s).
Minimally the design process in the open would be insightful for everyone interested in the topic even if the RFC did not get accepted — although the intent should be that it would — because it would change the operator overload discussion from a very abstract one to a very concrete one.
It could also illustrate the benefit for operator overloading, and illustrate the design process of deciding on how operators are overloaded and what the benefits and tradeoffs are of different choices.
If the RFC did not pass, at least it could result in an understanding of which operators minimally need to be overloaded for the Math use-case and serve as a blueprint for adding Math objects in userland if and when sufficient general-purpose operator overloading could get added to PHP.
Further, if an RFC to add a built-in Math object to PHP passed it would effectively eliminate the red-herring of "I don't do heavy math work." Such an RFC would also, of course, not have the other two (2) categories of objections that you named in your other email.
Again, #jmtcw
-Mike
Hi
Overall Vision
Even though I'm just a PHP pleb I thought I give you my opinion on the
matter. If the following arguments is nothing but a repetition of what
is argued in the RFC or in previous discussions I apologize.
Introduction
Historically I have been against operator overloading, however since
Jordan posted his first RFC on the subject I started to reevaluate my
position. What I realized is that I had just accepted the argument that
operator overloading creates unnecessary complexity, why? Because C++
has operator overloading and we all know that C++ is a very complex
language and therefore it is an bad idea, however that argument is
somewhat of fallacy.
Reevaluating operator overloading I came to the conclusion that many of
the issues that has been discussed within the PHP community can be
solved with operator overloading. What operator overloading enables us
to do is to let the community to evolve the language without the
formalities of the RFC process, it is a true decentralized governance,
which is a good fit for a community based language like PHP.
Lets go over some of the recurring issues that has been discussed within
the PHP community over the years. I assume here is what Larry specifies
as object operators level 3 and optionally 4. I try to keep this as an
high-level discussion to avoid any technical arguments regarding the PHP
engine because that is outside of my expertise.
Object primitives (scalar objects)
One recurring criticism against PHP is that it doesn't have methods
attached to primitive types like other dynamic languages has, e.g.
strpos($haystack, $needle)
instead of
$haystack->strpos($needle)
Nikic implemented a branch where he tested this
https://github.com/nikic/scalar_objects
With operator overloading we can implement this in user land and still
use our object primitives together with normal primitives.
And it would also be possible to inherit these object primitives for
custom object primitives, like an int range.
Strict comparison
Another issue is that every comparison, except for strict equal, is a
loose comparison with implicit type casting. If I remember correctly
someone suggested that we could add another declare directive, similar
to strict_types, to enable strict comparison per php file. With operator
overloading there is no need to add another directive.
Assume the following
(new Integer(3)) * 3 < $x
if the multiplication returns an Integer instance that is then used in
the following comparison step, Integer can enforce strict typing and
throw a TypeError on mismatch.
Tainted input
Another issue is to handle tainted input, e.g. from query parameters, to
avoid injection attacks when doing SQL queries. What I can see is that
this is something that has been discussed for quite a long time.
Currently there is no way for user land code to detect where a string
originated from.
With operator overloading a framework could at least within the confines
of the framework start to somewhat handle this issue.
Assume we have following two classes
class SafeString
{
// ...
}
class UnsafeString
{
// ...
}
Both implement the string append operator (.), on append both return the
same type of instance as them selves except that appending with
UnsafeString must always return UnsafeString. string literals could be
assumed to be SafeString.
Now the framework could have these two functions
function queryParam(string $name): UnsafeString;
function executeSqlQuery(SafeString $query, array $params): int;
The GET queryParam() returns an UnsafeString that is incompatible with
the $query argument for executeSqlQuery(). A programmer can still of
course escape out to the standard library and avoid this, but it gives a
least frameworks some tools to avoid the most common mistakes.
Escaped output
Assume we could add a custom operator that is the echo operator (note
this is not the same as _toString()). When doing PHP templating with <?=
$foo ?> we could then automatically escape string objects.
A new standard library
What all of these gives us is actually a new standard library driven by
the community. It is an recurring theme to complain on the standard
library, parameter order, function naming, lack of namespaces, not OOP
etc. You all have heard it. But with operator overloading we give the
community a chance to build something better without breaking the
current one.
And perhaps over the years the community has produced something good
that could be merged into PHP.
Currently I think the standard library is one of the biggest weaknesses
of PHP, it is not bad, it is actually quite good, but the packaging has
a big negative effect, especially on newcomers. There is almost no
benefit of cleaning up the current standard library by renaming
functions and reordering parameters, that would only create havoc with
minimal benefits, but unfortunately that also stops us from actually
getting a better designed standard library.
Operator overloading could be a way out of this dilemma, where we can
implement a new powerful standard library without breaking the past and
at the same time offer more expressiveness.
Conclusion
These are just a few things I have been thinking of the past months, I
have not properly tested the feasibility of them, thus there may be some
flaws in them, but you are free to comment on it. Thanks.
Tor
I'm not sure at this point how voters think objects and operators should
work together into the future. I'd like to see if anyone is willing to have
high-level discussion about the ideas, instead of picking at the
implementation or details of a particular RFC.
Hi Jordan,
I like Larry's "4 levels", but I've been thinking that there's some existing functionality in PHP which takes a different direction: rather than overloading operators, the language lets you overload behaviour. We have magic methods like __get and __call, and interfaces like Iterator, Countable, and ArrayAccess. Some hook into a particular function, or even operator, but they're generally described in terms of what they do, not what they look like, if you see what I mean.
From that point of view, overloading comparison and equality behaviour makes sense - it could affect not just the == and <=> operators, but things like in_array()
and sort()
. I think this distinction is more pronounced in PHP than some languages, because the standard library isn't "self-hosted": a sort()
call doesn't literally compile to a call to $a <=> $b
It's less obvious how that applies to mathematical operators - should implementing "addition" allow an object to be used with array_sum()
perhaps? And what about deriving one operation from another, e.g. $foo3 running $foo+$foo+$foo, or $foo**3 running $foo$foo*$foo?
I don't really have a conclusion here, I just wanted to throw it out there as a different mental model to consider.
Regards,
--
Rowan Tommins
[IMSoP]
I'm not sure at this point how voters think objects and operators should
work together into the future. I'd like to see if anyone is willing to have
high-level discussion about the ideas, instead of picking at the
implementation or details of a particular RFC.Hi Jordan,
I like Larry's "4 levels", but I've been thinking that there's some
existing functionality in PHP which takes a different direction: rather
than overloading operators, the language lets you overload
behaviour. We have magic methods like __get and __call, and
interfaces like Iterator, Countable, and ArrayAccess. Some hook into a
particular function, or even operator, but they're generally described
in terms of what they do, not what they look like, if you see what I
mean.From that point of view, overloading comparison and equality
behaviour makes sense - it could affect not just the == and <=>
operators, but things likein_array()
andsort()
. I think this
distinction is more pronounced in PHP than some languages, because the
standard library isn't "self-hosted": asort()
call doesn't literally
compile to a call to $a <=> $bIt's less obvious how that applies to mathematical operators - should
implementing "addition" allow an object to be used witharray_sum()
perhaps? And what about deriving one operation from another, e.g.
$foo3 running $foo+$foo+$foo, or $foo**3 running $foo$foo*$foo?I don't really have a conclusion here, I just wanted to throw it out
there as a different mental model to consider.
Interesting point. I think that's the most compelling argument I've heard for using public function __lessThan
rather than operator <
. I'm not sure if it's enough to change my own preference on that front, but it's an interesting point. Working with in_array()
and sort()
is a necessary feature for comparison overloading, IMO. I'm unsure about something like array_sum()
, but could be convinced.
Hum.
--Larry Garfield
On Fri, May 13, 2022 at 7:05 AM Rowan Tommins rowan.collins@gmail.com
wrote:
I like Larry's "4 levels", but I've been thinking that there's some
existing functionality in PHP which takes a different direction: rather
than overloading operators, the language lets you overload behaviour.
We have magic methods like __get and __call, and interfaces like Iterator,
Countable, and ArrayAccess. Some hook into a particular function, or even
operator, but they're generally described in terms of what they do, not
what they look like, if you see what I mean.From that point of view, overloading comparison and equality behaviour
makes sense - it could affect not just the == and <=> operators, but things
likein_array()
andsort()
. I think this distinction is more pronounced in
PHP than some languages, because the standard library isn't "self-hosted":
asort()
call doesn't literally compile to a call to $a <=> $b
I have been thinking about something similar, but not in the context of
making operator overloads more like behavior overloads. Rather, I've been
considering the idea that operator overloads are a subset of engine
overloads. Ways that the developer can provide additional details to the
engine about the behavior of their code that allows the engine to make more
concrete assumptions about how it should be processed and interpreted.
I started thinking about this mainly from the perspective of the syntax. I
proposed the operator +()
syntax in my overloads RFC, but my most
compelling argument about the reason for it was sort of obscured because it
was wrapped up in only overloads. To that end, I was considering more
broadly what all magic methods are on objects: handlers. In fact, in the
Zend engine that's how many of the same sorts of behaviors are described,
as object handlers.
Most of the standard library functions don't make calls for such handlers.
For instance, sort()
makes a call to zend_compare, and zend_compare ends up
making a call to the compare handler on the relevant object. So I was at
least considering the idea of a more broad replacement of the syntax for
object behaviors, just not for an RFC related to overloads... such an RFC
would have its own difficulties and controversy, and would almost certainly
require a period of dual syntax support for old magic method syntax, making
the arguments against very easy while the benefits would be more long term
and less immediately apparent.
It's less obvious how that applies to mathematical operators - should
implementing "addition" allow an object to be used witharray_sum()
perhaps? And what about deriving one operation from another, e.g. $foo3
running $foo+$foo+$foo, or $foo**3 running $foo$foo*$foo?I don't really have a conclusion here, I just wanted to throw it out there
as a different mental model to consider.
This would only be true for numerics, but not other kinds of math, such as
matrices. Mathematical operators really are something that require direct
calls and direct overloads if they are supported in any way, unless the
language is willing to essentially never have things like complex numbers,
matrices, etc. even in extensions.
Still, it's an interesting thought and definitely the kind of high-level
discussion I was looking for.
Jordan
On Fri, May 13, 2022 at 7:05 AM Rowan Tommins rowan.collins@gmail.com
wrote:I like Larry's "4 levels", but I've been thinking that there's some
existing functionality in PHP which takes a different direction: rather
than overloading operators, the language lets you overload behaviour.
We have magic methods like __get and __call, and interfaces like Iterator,
Countable, and ArrayAccess. Some hook into a particular function, or even
operator, but they're generally described in terms of what they do, not
what they look like, if you see what I mean.From that point of view, overloading comparison and equality behaviour
makes sense - it could affect not just the == and <=> operators, but things
likein_array()
andsort()
. I think this distinction is more pronounced in
PHP than some languages, because the standard library isn't "self-hosted":
asort()
call doesn't literally compile to a call to $a <=> $bI have been thinking about something similar, but not in the context of
making operator overloads more like behavior overloads. Rather, I've been
considering the idea that operator overloads are a subset of engine
overloads. Ways that the developer can provide additional details to the
engine about the behavior of their code that allows the engine to make more
concrete assumptions about how it should be processed and interpreted.I started thinking about this mainly from the perspective of the syntax. I
proposed theoperator +()
syntax in my overloads RFC, but my most
compelling argument about the reason for it was sort of obscured because it
was wrapped up in only overloads. To that end, I was considering more
broadly what all magic methods are on objects: handlers. In fact, in the
Zend engine that's how many of the same sorts of behaviors are described,
as object handlers.Most of the standard library functions don't make calls for such handlers.
For instance,sort()
makes a call to zend_compare, and zend_compare ends up
making a call to the compare handler on the relevant object. So I was at
least considering the idea of a more broad replacement of the syntax for
object behaviors, just not for an RFC related to overloads... such an RFC
would have its own difficulties and controversy, and would almost certainly
require a period of dual syntax support for old magic method syntax, making
the arguments against very easy while the benefits would be more long term
and less immediately apparent.It's less obvious how that applies to mathematical operators - should
implementing "addition" allow an object to be used witharray_sum()
perhaps? And what about deriving one operation from another, e.g. $foo3
running $foo+$foo+$foo, or $foo**3 running $foo$foo*$foo?I don't really have a conclusion here, I just wanted to throw it out there
as a different mental model to consider.This would only be true for numerics, but not other kinds of math, such as
matrices. Mathematical operators really are something that require direct
calls and direct overloads if they are supported in any way, unless the
language is willing to essentially never have things like complex numbers,
matrices, etc. even in extensions.Still, it's an interesting thought and definitely the kind of high-level
discussion I was looking for.Jordan
Sorry to resurrect an old conversation, but today I'm doing some
complex/big-number math (with a compatibility layer around GMP) in
PHP, and it made me realize how much I'd appreciate at least some
operator support in PHP.
Current code:
function modNear(BN $a, BN $b): BN {
$res = $a->mod($b);
if($res->gt($b->shrn(1))) {
return $res->sub($b);
}
return $res;
}
Desired code:
function modNear(BN $a, BN $b): BN {
$res = $a % $b;
if($res > ($b >> 1)) {
return $res - $b;
}
return $res;
}
The latter is much easier to grok at a glance.