Hi internals,
There is often a need to compare whether two objects are equal. For
example, a popular brick/money
library has a Money
class, which has an equals()
method. However, this
becomes tedious to implement such methods, when multiple nested objects are
involved. For instance, Money has an amount and a currency.
There were already suggestions on the mailing list to allow "overloading"
existing ==
operator, and some suggestions went even as far as
overloading <
, >=
etc operators. However, overloading existing
operators may lead to a BC break between the PHP version which does support
the functionality, and which doesn't. It won't result in a BC break in case
it's an entirely new syntax, because a library or a project won't be able
to write code which overloads ==
in say PHP 8.4, but with code which
still works in PHP 8.3 - it will have to require PHP 8.4+. But if it is
implemented as a magic method, then ==
will work differently for 8.3 and
8.4.
I suggest thinking about introducing a new operator ~=
, which signifies
that custom equality is requested. In such a case, ==
will work as it
works now, and by default ~=
will work also like ==
, unless its
behavior is overwritten via a magic method. If a magic method is not
present in a class being compared, ~=
will compare two objects field by
field, but using ~=
comparison rather than ==
comparison, recursively.
For instance, a Money object may consist of Amount and Currency. If two
Moneys are compared using ~=
, and Money does not implement a magic
method, Amount also doesn't implement it, but Currency does, then Amounts
are compared using ~=
which is equal to ==
comparison in this case,
but Currencies are compared using their custom comparison logic.
This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions - explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one - allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects - standardize such comparisons on the language level
Of course how exactly this operator looks may be changed, ~=
is just an
example.
WDYT?
Regards,
Illia / someniatko
Le 18/10/2023 à 14:50, someniatko a écrit :
Hi internals,
This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects- standardize such comparisons on the language level
Of course how exactly this operator looks may be changed,
~=
is just an
example.WDYT?
I'm not fond of operator overloading, I actually quite hate it, I like
the expressiveness of an equals() method.
I would very much prefer to have a set of standard interfaces such as
Comparable { compareTo($other): int } or Equatable { equals($other):
bool; } which the standard API and userland libraries could make use of.
In all cases, I don't like the ~= choice because in my mind it literally
translates to "is approximately/barely/maybe comparable to".
By the way, please do not use abbreviations such as WDYT, I'm not a
native english speaker and I don't know all abbreviations, I had to
duckduckgo' it.
Regards,
--
Pierre
Le 18/10/2023 à 14:50, someniatko a écrit :
Hi internals,
This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects- standardize such comparisons on the language level
Of course how exactly this operator looks may be changed,
~=
is just an
example.WDYT?
I'm not fond of operator overloading, I actually quite hate it, I like
the expressiveness of an equals() method.I would very much prefer to have a set of standard interfaces such as
Comparable { compareTo($other): int } or Equatable { equals($other):
bool; } which the standard API and userland libraries could make use of.In all cases, I don't like the ~= choice because in my mind it literally
translates to "is approximately/barely/maybe comparable to".By the way, please do not use abbreviations such as WDYT, I'm not a
native english speaker and I don't know all abbreviations, I had to
duckduckgo' it.Regards,
--
Pierre
--
To unsubscribe, visit: https://www.php.net/unsub.php
While I (obviously) appreciate the goal of the proposal here since I wrote
the gigantic operator overload RFC the last time it was proposed, I do not
support this idea here for one very simple reason: it is a clunky,
work-around implementation to try and get the benefits of operator
overloads without actually doing it.
The need to control comparisons is real and obvious. So long as voters are
categorically opposed to actual operator overloads no matter the
implementation, as represented here by you Pierre but by no means a
position that only you hold, I don't think we should be looking for ways to
get the functionality through hacks like this. It may get passed in the
short term and get PHP developers the equality comparison control that
objects desperately need, but it makes all future improvements almost
impossible to do.
someniatko:
If voters don't want operator overloads, then voters don't get the features
of operator overloads. It's very much that simple. If you want this
feature, try and change minds (ha ha good luck). "Operator overloads don't
fit a language like PHP"... despite the fact that Python is the language
most like PHP in many ways and has some absolutely crazy operator
overloads. "Operator overloads make operators impossible to understand"...
despite the fact that this is already the case with existing operators and
magic methods. "There is no use case"... despite the fact that this gets
suggested by a different person like clockwork AT LEAST every version
because it is something they would use.
Honestly I would give up on advocating for operator overloads someniatko
and just move to a language that has them like Python. That's what I did.
Your sanity will thank me.
Jordan
Le 18/10/2023 à 14:50, someniatko a écrit :
Hi internals,
This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects- standardize such comparisons on the language level
Of course how exactly this operator looks may be changed,
~=
is just an
example.WDYT?
I'm not fond of operator overloading, I actually quite hate it, I like
the expressiveness of an equals() method.I would very much prefer to have a set of standard interfaces such as
Comparable { compareTo($other): int } or Equatable { equals($other):
bool; } which the standard API and userland libraries could make use of.In all cases, I don't like the ~= choice because in my mind it literally
translates to "is approximately/barely/maybe comparable to".By the way, please do not use abbreviations such as WDYT, I'm not a
native english speaker and I don't know all abbreviations, I had to
duckduckgo' it.Regards,
--
Pierre
--
To unsubscribe, visit: https://www.php.net/unsub.php
While I (obviously) appreciate the goal of the proposal here since I wrote
the gigantic operator overload RFC the last time it was proposed, I do not
support this idea here for one very simple reason: it is a clunky,
work-around implementation to try and get the benefits of operator
overloads without actually doing it.The need to control comparisons is real and obvious. So long as voters are
categorically opposed to actual operator overloads no matter the
implementation, as represented here by you Pierre but by no means a
position that only you hold, I don't think we should be looking for ways to
get the functionality through hacks like this. It may get passed in the
short term and get PHP developers the equality comparison control that
objects desperately need, but it makes all future improvements almost
impossible to do.someniatko:
If voters don't want operator overloads, then voters don't get the features
of operator overloads. It's very much that simple. If you want this
feature, try and change minds (ha ha good luck). "Operator overloads don't
fit a language like PHP"... despite the fact that Python is the language
most like PHP in many ways and has some absolutely crazy operator
overloads. "Operator overloads make operators impossible to understand"...
despite the fact that this is already the case with existing operators and
magic methods. "There is no use case"... despite the fact that this gets
suggested by a different person like clockwork AT LEAST every version
because it is something they would use.Honestly I would give up on advocating for operator overloads someniatko
and just move to a language that has them like Python. That's what I did.
Your sanity will thank me.Jordan
As a user of PHP, it was sad to see that fail. There are no "unsigned
longs" in PHP, and I had to create a library that emulated them using
GMP. There is no way to describe how terrible using that library
was... simply because you couldn't overload a plus sign or an equals
sign. Accidentally using real operators could cause all kinds of
shenanigans and invalid math being done. Fun times.
If it had been a possibility, we would have ditched PHP immediately.
We almost did anyway, even if it meant rewriting everything.
People seem to be hung up on "people might abuse it" and forget there
are real-world, somewhat niche problems that are True Pain (TM) to
solve without overloading. Pain enough to leave the language entirely.
Thank you for your contribution, it was a really well-put-together
RFC, IMHO. I would have voted for it if I could have.
Robert Landers
Software Engineer
Utrecht NL
Le 18/10/2023 à 22:22, Jordan LeDoux a écrit :
While I (obviously) appreciate the goal of the proposal here since I
wrote the gigantic operator overload RFC the last time it was
proposed, I do not support this idea here for one very simple reason:
it is a clunky, work-around implementation to try and get the benefits
of operator overloads without actually doing it.
Even if I don't really like operator overload, I would very much prefer
the gigantic operator overload to pass than a band-aid patch with a new
operator, I'm all in for consistency.The need to control comparisons is real and obvious. So long as voters
are categorically opposed to actual operator overloads no matter the
implementation, as represented here by you Pierre but by no means a
position that only you hold, I don't think we should be looking for
ways to get the functionality through hacks like this. It may get
passed in the short term and get PHP developers the equality
comparison control that objects desperately need, but it makes all
future improvements almost impossible to do.
Maybe I don't master english enough and I can speak to strictly
sometime. If an operator overload RFC that doesn't have any blind spot
or weird edge case happens, I'd be happy to see it pass, at least it
would close bike shedding around this topic and life would continue happily.
I can't vote, but if I could, I wouldn't vote against a proper, robust,
and easy to debug for developers operator overload RFC, I would simply
abstain, because even if I personally don't like it, lots of people want
it and I'm simply one among millions of PHP users, I don't want anyone
to be frustrated.
The most important thing in my previous message I wanted to say was that
the "~" symbol refers to something "approximate" in many contexts, in my
opinion it's not the right choice for an equality operator. My opinion
is either go for a full-on proper operator overload or simply don't.
Regards,
--
Pierre
Maybe I don't master english enough and I can speak to strictly
sometime. If an operator overload RFC that doesn't have any blind spot
or weird edge case happens, I'd be happy to see it pass, at least it
would close bike shedding around this topic and life would continue
happily.I can't vote, but if I could, I wouldn't vote against a proper, robust,
and easy to debug for developers operator overload RFC, I would simply
abstain, because even if I personally don't like it, lots of people want
it and I'm simply one among millions of PHP users, I don't want anyone
to be frustrated.The most important thing in my previous message I wanted to say was that
the "~" symbol refers to something "approximate" in many contexts, in my
opinion it's not the right choice for an equality operator. My opinion
is either go for a full-on proper operator overload or simply don't.Regards,
--
Pierre
I tried to make sure this was clear, but I will say it explicitly just to
make sure: I am not at all criticizing you, I was just saying that the
opinion you expressed is one that is shared by many voters so it cannot be
simply dismissed, and that I disagree with it personally.
Jordan
Hi internals,
There is often a need to compare whether two objects are equal. For
example, a popular brick/money
library has aMoney
class, which has anequals()
method. However, this
becomes tedious to implement such methods, when multiple nested objects are
involved. For instance, Money has an amount and a currency.There were already suggestions on the mailing list to allow "overloading"
existing==
operator, and some suggestions went even as far as
overloading<
,>=
etc operators. However, overloading existing
operators may lead to a BC break between the PHP version which does support
the functionality, and which doesn't. It won't result in a BC break in case
it's an entirely new syntax, because a library or a project won't be able
to write code which overloads==
in say PHP 8.4, but with code which
still works in PHP 8.3 - it will have to require PHP 8.4+. But if it is
implemented as a magic method, then==
will work differently for 8.3 and
8.4.I suggest thinking about introducing a new operator
~=
, which signifies
that custom equality is requested. In such a case,==
will work as it
works now, and by default~=
will work also like==
, unless its
behavior is overwritten via a magic method. If a magic method is not
present in a class being compared,~=
will compare two objects field by
field, but using~=
comparison rather than==
comparison, recursively.For instance, a Money object may consist of Amount and Currency. If two
Moneys are compared using~=
, and Money does not implement a magic
method, Amount also doesn't implement it, but Currency does, then Amounts
are compared using~=
which is equal to==
comparison in this case,
but Currencies are compared using their custom comparison logic.This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects- standardize such comparisons on the language level
Of course how exactly this operator looks may be changed,
~=
is just an
example.WDYT?
Regards,
Illia / someniatko
I like it.
One thing I really like about this proposal is that, in theory, it
could open the door to new operators like ~<, ~<=, ~!, ~= which can be
similarly implemented.
It also makes me wonder if something similar to scala can be
implemented, where any operator beginning with "~" can just call an
associated magic method. I'm not sure how it would be implemented
though, since I don't think you can use symbols/operators in method
names. But if you wanted a pipe operator, you could add one via ~|.
It'd allow for more useful DSL's that are implemented in PHP, as
currently, it doesn't really make sense to create a DSL that is
actually PHP since you can't override any operators.
That being said, my only criticism is that it will be really easy to
forget the ~ when writing code. It's a true shame that overloading
wasn't added to the language, as it makes it an impractical language
for entire classes of problems/solutions.
Robert Landers
Software Engineer
Utrecht NL
Hi internals,
There is often a need to compare whether two objects are equal. For
example, a popular brick/money
library has aMoney
class, which has anequals()
method. However, this
becomes tedious to implement such methods, when multiple nested objects are
involved. For instance, Money has an amount and a currency.There were already suggestions on the mailing list to allow "overloading"
existing==
operator, and some suggestions went even as far as
overloading<
,>=
etc operators. However, overloading existing
operators may lead to a BC break between the PHP version which does support
the functionality, and which doesn't. It won't result in a BC break in case
it's an entirely new syntax, because a library or a project won't be able
to write code which overloads==
in say PHP 8.4, but with code which
still works in PHP 8.3 - it will have to require PHP 8.4+. But if it is
implemented as a magic method, then==
will work differently for 8.3 and
8.4.I suggest thinking about introducing a new operator
~=
, which signifies
that custom equality is requested. In such a case,==
will work as it
works now, and by default~=
will work also like==
, unless its
behavior is overwritten via a magic method. If a magic method is not
present in a class being compared,~=
will compare two objects field by
field, but using~=
comparison rather than==
comparison, recursively.For instance, a Money object may consist of Amount and Currency. If two
Moneys are compared using~=
, and Money does not implement a magic
method, Amount also doesn't implement it, but Currency does, then Amounts
are compared using~=
which is equal to==
comparison in this case,
but Currencies are compared using their custom comparison logic.This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects- standardize such comparisons on the language level
Of course how exactly this operator looks may be changed,
~=
is just an
example.WDYT?
Regards,
Illia / someniatkoI like it.
One thing I really like about this proposal is that, in theory, it
could open the door to new operators like ~<, ~<=, ~!, ~= which can be
similarly implemented.It also makes me wonder if something similar to scala can be
implemented, where any operator beginning with "~" can just call an
associated magic method. I'm not sure how it would be implemented
though, since I don't think you can use symbols/operators in method
names. But if you wanted a pipe operator, you could add one via ~|.
It'd allow for more useful DSL's that are implemented in PHP, as
currently, it doesn't really make sense to create a DSL that is
actually PHP since you can't override any operators.That being said, my only criticism is that it will be really easy to
forget the ~ when writing code. It's a true shame that overloading
wasn't added to the language, as it makes it an impractical language
for entire classes of problems/solutions.Robert Landers
Software Engineer
Utrecht NL
Honestly I'm still on team operator-override. Most major languages have operator overloading, and it doesn't seem to cause a problem. (According to my research, C++, Kotlin, Swift, Rust, C#, Haskell, Python, and Ruby all have operator overloading. Go, TypeScript, PHP, and Javascript do not. Java has comparison-only overloading so it's in the middle.) Most of the "it causes so many problems" arguments are, from what I can tell, greatly over-exaggerated.
More to the point, the key question is whether anyone who voted No on the previous operator overloading RFC would vote Yes on an operator-overloading-but-only-with-an-opt-in-prefix RFC. If not, then it doesn't really buy us anything. If so, then it's possible as a compromise but would, frankly, be strictly inferior to just using the native operators we already have.
So the real question is: Would anyone who voted No on operator overloading before vote Yes on it if it used ~=, ~>, ~+, etc. instead?
---Larry Garfield
Am 18.10.2023 um 18:42 schrieb Larry Garfield larry@garfieldtech.com:
So the real question is: Would anyone who voted No on operator overloading before vote Yes on it if it used ~=, ~>, ~+, etc. instead?
I confess that I'm not a fan of operator overloading for a language like PHP but introducing new operators on top of making them overloadable seems a bad idea. Operators have the problem of being hard to look up and prefixing them with ~ feels like the worst of both worlds.
Regards,
- Chris
On Wed, Oct 18, 2023 at 7:05 PM Christian Schneider
cschneid@cschneid.com wrote:
Am 18.10.2023 um 18:42 schrieb Larry Garfield larry@garfieldtech.com:
So the real question is: Would anyone who voted No on operator overloading before vote Yes on it if it used ~=, ~>, ~+, etc. instead?
I confess that I'm not a fan of operator overloading for a language like PHP but introducing new operators on top of making them overloadable seems a bad idea. Operators have the problem of being hard to look up and prefixing them with ~ feels like the worst of both worlds.
Regards,
- Chris
--
To unsubscribe, visit: https://www.php.net/unsub.php
I suspect xdebug would work fine if you can't use the IDE to
ctrl-click on the operator. I highly suspect you'd never even use them
except in specific cases where it would feel natural to do so (such as
the money example, a units library, a matrix mathematics library, or a
real number field library).
Robert Landers
Software Engineer
Utrecht NL
On Wed, Oct 18, 2023 at 2:05 PM Christian Schneider cschneid@cschneid.com
wrote:
Am 18.10.2023 um 18:42 schrieb Larry Garfield larry@garfieldtech.com:
So the real question is: Would anyone who voted No on operator
overloading before vote Yes on it if it used ~=, ~>, ~+, etc. instead?I confess that I'm not a fan of operator overloading for a language like
PHP but introducing new operators on top of making them overloadable seems
a bad idea. Operators have the problem of being hard to look up and
prefixing them with ~ feels like the worst of both worlds.Regards,
- Chris
To add on to this, the proposal side-steps a potential BC break issue while
introducing a collection of problems for libraries using PHP Tokens, Static
Analysers, IDEs and more importantly the ability to grep your codebase
looking for ==
.
From what I understood about the BC break concern, it's the fact that IF:
- Existing code is comparing objects (relying on potentially
non-deterministic behavior?) - PHP introduces operator overload
- A library releases a new major version implementing operator overload
- Existing code breaks
Sounds to me that this is more between Library authors and Library users.
Yes, PHP would be opening the door for potential BC breaks, but the
stability of Composer packages and the adoption of Semantic Versioning
throughout the industry makes this look like PHP is trying to protect
grown, trained, mentally stable adults from running with knives.
On Wed, Oct 18, 2023 at 1:43 PM Larry Garfield larry@garfieldtech.com
wrote:
Honestly I'm still on team operator-override. Most major languages have
operator overloading, and it doesn't seem to cause a problem. (According
to my research, C++, Kotlin, Swift, Rust, C#, Haskell, Python, and Ruby all
have operator overloading. Go, TypeScript, PHP, and Javascript do not.
Java has comparison-only overloading so it's in the middle.) Most of the
"it causes so many problems" arguments are, from what I can tell, greatly
over-exaggerated.---Larry Garfield
To argue against myself, I think Larry has a killer point in the language
comparison. I think it's fair to say PHP is the weird one out for not
having Operator Overload when even Python and Ruby (languages more similar
to PHP than Kotlin or Rust) have them.
Ultimately, if voters think it's best to overload ~=
instead of ==
, I
think we bite the bullet and deal with the consequences. Even though I have
every reason not to want ~=
, PHP deserves method overloading unless folks
can show facts as to why nearly every other major programming language is
wrong or why they can have it and we can't.
--
Marco Deleu
Hi
Honestly I'm still on team operator-override. Most major languages have operator overloading, and it doesn't seem to cause a problem. (According to my research, C++, Kotlin, Swift, Rust, C#, Haskell, Python, and Ruby all have operator overloading. Go, TypeScript, PHP, and Javascript do not. Java has comparison-only overloading so it's in the middle.) Most of the "it causes so many problems" arguments are, from what I can tell, greatly over-exaggerated.
To clarify here: Haskell does not have operators per se. It has
functions whose name may consist of symbols only. It also has function
overloading via its typeclass feature (roughly comparable to
interfaces). It also allows to write any binary function in infix form
by wrapping it into backticks.
More to the point, the key question is whether anyone who voted No on the previous operator overloading RFC would vote Yes on an operator-overloading-but-only-with-an-opt-in-prefix RFC. If not, then it doesn't really buy us anything. If so, then it's possible as a compromise but would, frankly, be strictly inferior to just using the native operators we already have.
So the real question is: Would anyone who voted No on operator overloading before vote Yes on it if it used ~=, ~>, ~+, etc. instead?
I did not vote, but I would not vote in favor of operator overloading
with a different syntax. My main issue with operator overloading via
instance methods is that it's too easy to achieve a non-symmetric
equality, i.e. $a == $b
!= $b == $a
.
This is a somewhat common problem of Java's .equals()
method, unless
you are careful with how you write the implementation (e.g.
https://stackoverflow.com/a/6518645). At least for .equals()
it would
be obvious that it would be an instance method and that it might not be
symmetric.
Operator overloading is only a value-add to me, if it would be realized
via free-standing functions to ensure there is a single canonical
implementation for a given operator, instead two different ones with
inverted parameter order. And yes, I realize that this would require
function overloading.
I would be in favor of allowing writing binary functions in infix
position to allow stuff like '($foo bcadd 5)', because I can see how
that is more readable than bcadd($foo, 5)
Best regards
Tim Düsterhus
Hi internals,
There is often a need to compare whether two objects are equal. For
example, a popular brick/money
library has aMoney
class, which has anequals()
method. However, this
becomes tedious to implement such methods, when multiple nested objects are
involved. For instance, Money has an amount and a currency.There were already suggestions on the mailing list to allow "overloading"
existing==
operator, and some suggestions went even as far as
overloading<
,>=
etc operators. However, overloading existing
operators may lead to a BC break between the PHP version which does support
the functionality, and which doesn't. It won't result in a BC break in case
it's an entirely new syntax, because a library or a project won't be able
to write code which overloads==
in say PHP 8.4, but with code which
still works in PHP 8.3 - it will have to require PHP 8.4+. But if it is
implemented as a magic method, then==
will work differently for 8.3 and
8.4.I suggest thinking about introducing a new operator
~=
, which signifies
that custom equality is requested. In such a case,==
will work as it
works now, and by default~=
will work also like==
, unless its
behavior is overwritten via a magic method. If a magic method is not
present in a class being compared,~=
will compare two objects field by
field, but using~=
comparison rather than==
comparison, recursively.For instance, a Money object may consist of Amount and Currency. If two
Moneys are compared using~=
, and Money does not implement a magic
method, Amount also doesn't implement it, but Currency does, then Amounts
are compared using~=
which is equal to==
comparison in this case,
but Currencies are compared using their custom comparison logic.This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects- standardize such comparisons on the language level
Of course how exactly this operator looks may be changed,
~=
is just an
example.WDYT?
Regards,
Illia / someniatko
Note that ~=
is used in Lua instead of !=
. Having this operator be an
overloading == would feel really counterintuitive to me. We have
"instanceof", and I've seen "is" ideas floating around. Could also look
into the direction of "equals" for this.
I believe it's time to shift our focus away from backward compatibility
(BC) concerns in major versions. In my opinion, genuine operator
overloading is incomparable to the pseudo operator. I genuinely see the
operator overloads as an invaluable addition to PHP 9
Lanre
Hi internals,
There is often a need to compare whether two objects are equal. For
example, a popular brick/money
library has aMoney
class, which has anequals()
method. However, this
becomes tedious to implement such methods, when multiple nested objects are
involved. For instance, Money has an amount and a currency.There were already suggestions on the mailing list to allow "overloading"
existing==
operator, and some suggestions went even as far as
overloading<
,>=
etc operators. However, overloading existing
operators may lead to a BC break between the PHP version which does support
the functionality, and which doesn't. It won't result in a BC break in case
it's an entirely new syntax, because a library or a project won't be able
to write code which overloads==
in say PHP 8.4, but with code which
still works in PHP 8.3 - it will have to require PHP 8.4+. But if it is
implemented as a magic method, then==
will work differently for 8.3 and
8.4.I suggest thinking about introducing a new operator
~=
, which signifies
that custom equality is requested. In such a case,==
will work as it
works now, and by default~=
will work also like==
, unless its
behavior is overwritten via a magic method. If a magic method is not
present in a class being compared,~=
will compare two objects field by
field, but using~=
comparison rather than==
comparison, recursively.For instance, a Money object may consist of Amount and Currency. If two
Moneys are compared using~=
, and Money does not implement a magic
method, Amount also doesn't implement it, but Currency does, then Amounts
are compared using~=
which is equal to==
comparison in this case,
but Currencies are compared using their custom comparison logic.This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects- standardize such comparisons on the language level
Of course how exactly this operator looks may be changed,
~=
is just an
example.WDYT?
Regards,
Illia / someniatko
I believe it's time to shift our focus away from backward compatibility
(BC) concerns in major versions. In my opinion, genuine operator
overloading is incomparable to the pseudo operator. I genuinely see the
operator overloads as an invaluable addition to PHP 9Lanre
I definitely agree with everything you wrote with enthusiastic attitude.
Less BC could lead to awesome improvements in the future. PHP version
checks could be added to applications instead then.
pixel
--
phone: ++49 / (0)172 / 44 1 88 56
There were already suggestions on the mailing list to allow "overloading" existing
==
operator, and some suggestions went even as far as overloading<
,>=
etc operators.
Slightly off-topic, but concatenation?
Just as a possible feature... for my sins I'm the database component maintainer for WordPress, and I'm currently getting wpdb::prepare()
to work with the literal-string
type, where I added support for escaping identifiers (field/table names). This function works like sprintf()
, with the SQL being the $format
argument, and then user values; from that it returns an SQL string with escaped values (yes, I know, parameterised queries are better, but we work with what we have)... developers often concatenate these together, but I was wondering if I could return a stringable value-object, so when they are concatenated, a new value-object could be created instead, so we can verify (ideally at runtime) that all values have been escaped correctly (and maybe use parameterised queries).
Craig
This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects- standardize such comparisons on the language level
Of course how exactly this operator looks may be changed,
~=
is just an
example.WDYT?
Regards,
Illia / someniatko
One thing to keep in mind is that operator overloading already exists in
PHP. And it is already in use in userland PHP too, for example when
comparing DateTime objects. The limitation is that it only works for
some objects: Those that are implemented in an extension.
To me, the obvious way forward would be to lift this limitation. But...
several attempts to do so have failed to pass. People are hesitant to
unleash full operator overloading power to PHP developers.
So, perhaps a simplified version of the RFC by Jordan LeDoux, limited to
the ==
operator only, would stand a chance? It would allow the
community to try their hands on this one (highly valuable) operator
overload. PHP 9 is coming and provides a great opportunity.
I also like the idea from Pierre to provide interfaces. Some people
prefer an explicit method call over an operator doing magic things,
which I fully understand. Perhaps we could allow both?
Regards,
Dik
This approach allows combining
- no BC break -
~=
is a new syntax which is unavailable in older PHP
versions- explicitly showing an intent that objects are compared using a custom
comparison, rather than standard PHP one- allow to skip writing boilerplate equals() methods which just forward
equals() to the nested objects- standardize such comparisons on the language level
Of course how exactly this operator looks may be changed,
~=
is just an
example.WDYT?
Regards,
Illia / someniatkoOne thing to keep in mind is that operator overloading already exists in
PHP. And it is already in use in userland PHP too, for example when
comparing DateTime objects. The limitation is that it only works for
some objects: Those that are implemented in an extension.To me, the obvious way forward would be to lift this limitation. But...
several attempts to do so have failed to pass. People are hesitant to
unleash full operator overloading power to PHP developers.So, perhaps a simplified version of the RFC by Jordan LeDoux, limited to
the==
operator only, would stand a chance? It would allow the
community to try their hands on this one (highly valuable) operator
overload. PHP 9 is coming and provides a great opportunity.I also like the idea from Pierre to provide interfaces. Some people
prefer an explicit method call over an operator doing magic things,
which I fully understand. Perhaps we could allow both?Regards,
Dik
I would recommend including ==, <, >, <=, >= all in the initial design, as they do interact. I've said in the past that I'd welcome a reduced-scope version as a stepping stone.
Jordan's RFC explained in detail why interfaces are not viable, which is why we have to use magic methods (with or without a special keyword) instead:
https://wiki.php.net/rfc/user_defined_operator_overloads#why_not_interfaces
(Seriously, it has an extensive FAQ. It's one of the more detailed and supported RFCs we've seen.)
--Larry Garfield
Jordan's RFC explained in detail why interfaces are not viable, which is why we have to use magic methods (with or without a special keyword) instead:
https://wiki.php.net/rfc/user_defined_operator_overloads#why_not_interfaces
(Seriously, it has an extensive FAQ. It's one of the more detailed and supported RFCs we've seen.)
Yes, I know the RFC, it's a great piece of work! The use of interfaces
as mentioned in this RFC is however completely different from what
Pierre and I are talking about. If I understand Pierre correctly, that
is. The suggestion to include interfaces simply meant to allow freedom
of choice. Choice between using an operator (==
) or calling the
equivalent method on the object (->equals()
). That may get more people
on board with operator overloading.
Regards,
Dik
Jordan's RFC explained in detail why interfaces are not viable, which is
why we have to use magic methods (with or without a special keyword)
instead:https://wiki.php.net/rfc/user_defined_operator_overloads#why_not_interfaces
(Seriously, it has an extensive FAQ. It's one of the more detailed and
supported RFCs we've seen.)Yes, I know the RFC, it's a great piece of work! The use of interfaces
as mentioned in this RFC is however completely different from what
Pierre and I are talking about. If I understand Pierre correctly, that
is. The suggestion to include interfaces simply meant to allow freedom
of choice. Choice between using an operator (==
) or calling the
equivalent method on the object (->equals()
). That may get more people
on board with operator overloading.Regards,
Dik
I don't quite follow. The interface would cause the engine to use the
result of an equals()
function on the object if it implements an
interface as part of zend_compare
? Internally there is no ==
function,
there is only the equivalent of <=>
. To implement it ONLY for ==
would
require a trapdoor of some kind in the do_operation
handler that would
also affect the way the existing extensions work, such as the DateTime
class which implements a custom handler for the compare
handler on the
zend class entry.
This might be easier to do once a few comparison improvements to separate
"comparable" and "equatable" are done, but the PR I submitted two years ago
to handle that got kind of mired in bike shedding about the implementation
and I lost interest in continuing to push it.
Implementing the compare handler for an overload requires adding two new
entries to ZEND_AST_BINARY_OP because the >
and <
comparisons have to
be preserved in the AST in order to call the correct object handler. THAT
requires updating OpCache and JIT since all such comparisons are currently
reordered to use <
, and though I spent quite a while looking at it, I
think Dmitry might be the only person that could really implement that
fully. At least, I never found anyone that had the expertise to actually
help me with it.
Jordan
Hi Jordan,
Implementing the compare handler for an overload requires adding two new
entries to ZEND_AST_BINARY_OP because the>
and<
comparisons have to
be preserved in the AST in order to call the correct object handler. THAT
requires updating OpCache and JIT since all such comparisons are currently
reordered to use<
, and though I spent quite a while looking at it, I
think Dmitry might be the only person that could really implement that
fully. At least, I never found anyone that had the expertise to actually
help me with it.
17 years ago Sara was working on it, too ;)
https://externals.io/message/21883
Jordan
Best,
Marc
I don't quite follow. The interface would cause the engine to use the
result of anequals()
function on the object if it implements an
interface as part ofzend_compare
? Internally there is no==
function,
there is only the equivalent of<=>
. To implement it ONLY for==
would
require a trapdoor of some kind in thedo_operation
handler that would
also affect the way the existing extensions work, such as theDateTime
class which implements a custom handler for thecompare
handler on the
zend class entry.
No, the interface would not cause anything to happen in zend_compare
.
It would simply serve to make explicit that an object has a custom
implementation of a (set of) operators and that the implementing method
can be called directly. So the developer can choose to either use the
operator or call the implementing method on the object. Both styles
would be supported and the following two expressions would be equivalent:
$a == $b
$a->equals($b)
(the method name is just an example)
Regarding your (Jordan's) RFC on the subject: The method call style
would not yield readable code in this case, as the 'methods' are named
after the operators. So that part of the RFC would need to change to
make both styles work.
Regards,
Dik
I am just going to put this out there, but I will vote against any RFC
which provides access to userland to overload == and <=> until the base
semantics of PHP comparisons are fixed and the necessary engine
prerequisite work is done.
I am working on such an RFC, as I frankly do not trust people to think
stuff through and handle things like polymorphic comparisons.
Also, introducing some new kind of weird operator is just... bad.
Best regards,
George P. Banyard