Re: Equality and relative ordering of objects

From: Date: Thu, 21 Jun 2018 12:31:19 +0000
Subject: Re: Equality and relative ordering of objects
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-102340@lists.php.net to get a copy of this message
2018-06-21 11:27 GMT+02:00 Rudi Theunissen <rtheunissen@php.net>: > The Comparable RFC (http://wiki.php.net/rfc/comparable) was written in > 2010 > and > revised in 2015 by Adam Harvey, but was not conclusive. I would like to > take > on some shared responsibility to push this forward and re-open the > discussion. > > Why is this useful, and why should it be added to PHP? > > > 1. The default comparison of objects can be expensive. > > Objects are compared and tested for equality by recursively comparing their > properties. If an object has many properties, or properties that are > objects > or have large arrays, this comparison may dive very deep. > > It may not be necessary to do all this work to determine whether two > objects > are equal. For example, if you have a data model that represents a database > entity, you're only concerned about the data attributes, and there's no > need > to compare the database connection or other internal metadata. > > Objects that have a defining value (like a number type), can simply compare > itself in value to the other object (if also a number type), and can skip > checking other properties. This has the potential to save a lot of > unnecessary comparisons. > > > 2. The default comparison of objects can be risky. > > There could be cases where two objects have the same public properties but > one of them (perhaps a subclass) has a private property. These two objects > could be considered equal to the outside world, but == would > return > false. When a developer added this private property, it might > not have > been obvious that they were affecting equality. This makes == > checks on > objects very fragile where it could be explictly defined and controlled. > > > 3. There is no way to specify strict comparison. > > With PHP becoming more type-safe since PHP 7 with strict mode and scalar > type-hints, the current behaviour feels out of date. For example: > > ``` > $a = new stdClass(); > $b = new stdClass(); > > $a->prop = 1; > $b->prop = true; > > $a == $b; // true > ``` > > 4. Adding this functionality does not affect backwards-compatibility and > could > probably be implemented in 5.x as well. To my knowledge, The only major > changes required are in the default object handlers. This would > automatically affect functions like array_search and > sort. > > > 5. Other major languages support this and there seems to be a decent amount > of > public support for it. > > > What is the proposed API for this? > > Magic methods. Objects that don't implement them maintain the current > behaviour. > > ``` > /** > * @returns -1 if less than, > * 0 if equal to, > * 1 if greater than the other value (in terms of relative ordering). > */ > __compareTo(mixed $other): int; > When comparing objects should be obvoius to use object type hint not mixed > > /** > * @returns true if this instance is equal to the given value, or false if > not. > */ > __equals(mixed $other): bool; ``` > If __compareTo($other) gives 0 then there is no justification for additional method. IMO you're duplicating functionality here. > > > Why magic methods? > > - No risk of breaking backwards compatibility because method names that > start > with __ are always reserved. > > - All objects can already be compared and tested for equality, so checking > if > an object implements an interface would not give you any useful > information. > Alternatively, we could introduce a function like "ÅIs > K-Ù*™ß�ÂÓis_comparable. > > - Python uses magic methods because there are no interfaces. Java has a > Comparable interface because not all objects are comparable by default. > It's > important to note that we're not exposing the ability to make an object > comparable, but instead to change the default behaviour when compared. All > objects are technically already comparable. > > - PHP already uses magic methods to change the default behaviour of > objects. > > - Interfaces like Iterable or > IteratorAggregate must be interfaces > because > not all objects are iterable. > > > Why do we need __equals when > __compareTo can just return 0? > > 1. Anything can be tested for equality, but all things are not comparable.. > For example, an apple can be equated with an orange and we can say that the > apple does not equal the orange. However, comparing the apple to an orange > makes no logical sense. There is nothing about either object that would > allow us to say that the apple is greater or less than the orange. > > 2. Some things that are not equal have the same relative ordering. For > example, > a floating point value of 2.0 does not equal the integer > 2, but > their > relative ordering is the same, and a comparison would return > 0. > That's true, but you want to compare objects not scalar types, right? > > 3. The contexts in which they are called are not the same. Testing for > equality > occurs when an object is compared with another using == or in > functions > like array_search. The question we're asking is whether > the two values > are > considered equal, and we're not concerned with ordering. The context for > comparison is when we need to determine the relative ordering of two values > using <, >, or in > functions like sort. > > > Issues to be discussed: > > 1. What happens when we use <= and > >=? Does the "or equal to" part call > __equals or does it check if > __compareTo returns 0? > > 2. Should we also expose strict comparison, ie. === ? > > 3. Naming: > - __eq > - __equalTo > - __equals > - __compareTo > - __comparedTo > - __compare > - __cmp > Thanks for reanimating this subject. -- regards / pozdrawiam, -- MichaÅ‚ Brzuchalski about.me/brzuchal brzuchalski.com

« previous php.internals (#102340) next »