Re: Custom object equality
| From: | Robert Landers | Date: | Wed, 18 Oct 2023 13:12:34 +0000 |
| Subject: | Re: Custom object equality | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-121391@lists.php.net to get a copy of this message | ||
On Wed, Oct 18, 2023 at 2:51 PM someniatko <someniatko@gmail.com> wrote:
>
> Hi internals,
>
> There is often a need to compare whether two objects are equal. For
> example, a popular [brick/money](https://packagist.org/packages/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
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