2018-06-21 11:27 GMT+02:00 Rudi Theunissen <rtheunis...@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_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

Reply via email to