Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:102340 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 60896 invoked from network); 21 Jun 2018 12:31:34 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 21 Jun 2018 12:31:34 -0000 Authentication-Results: pb1.pair.com smtp.mail=michal@brzuchalski.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=michal@brzuchalski.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain brzuchalski.com from 188.165.245.118 cause and error) X-PHP-List-Original-Sender: michal@brzuchalski.com X-Host-Fingerprint: 188.165.245.118 ns220893.ip-188-165-245.eu Received: from [188.165.245.118] ([188.165.245.118:41470] helo=poczta.brzuchalski.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 40/8E-32156-1AA9B2B5 for ; Thu, 21 Jun 2018 08:31:31 -0400 Received: from localhost (localhost.localdomain [127.0.0.1]) by poczta.brzuchalski.com (Postfix) with ESMTP id A93DB298423B for ; Thu, 21 Jun 2018 14:31:25 +0200 (CEST) Received: from poczta.brzuchalski.com ([127.0.0.1]) by localhost (poczta.brzuchalski.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id S_ouyKIKk4he for ; Thu, 21 Jun 2018 14:31:21 +0200 (CEST) Received: from mail-ot0-f180.google.com (unknown [74.125.82.180]) by poczta.brzuchalski.com (Postfix) with ESMTPSA id 8EA26298423A for ; Thu, 21 Jun 2018 14:31:21 +0200 (CEST) Received: by mail-ot0-f180.google.com with SMTP id l15-v6so3343415oth.6 for ; Thu, 21 Jun 2018 05:31:21 -0700 (PDT) X-Gm-Message-State: APt69E0wbNEG6Dqd96E5iwBliD9M2+j+q2zMsnU+hmsj0gekFfuZftQp ckCufq0iEq0//dqRLl/10fGdXxtADzMTOhkuSkc= X-Google-Smtp-Source: ADUXVKJGZf68zjMsLnJygCvA6sdfwojZ0AxdUuWEOhmT0nNaYf32yAU5P6wIg5FyI7fRCbJ5NnNpj3MuRIypN5RSpqA= X-Received: by 2002:a9d:38aa:: with SMTP id p39-v6mr16696591otc.349.1529584280512; Thu, 21 Jun 2018 05:31:20 -0700 (PDT) MIME-Version: 1.0 Received: by 2002:a9d:27c5:0:0:0:0:0 with HTTP; Thu, 21 Jun 2018 05:31:19 -0700 (PDT) In-Reply-To: References: Date: Thu, 21 Jun 2018 14:31:19 +0200 X-Gmail-Original-Message-ID: Message-ID: To: Rudi Theunissen Cc: PHP Internals List Content-Type: multipart/alternative; boundary="000000000000b1b60c056f26178d" Subject: Re: [PHP-DEV] Equality and relative ordering of objects From: michal@brzuchalski.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=) --000000000000b1b60c056f26178d Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable 2018-06-21 11:27 GMT+02:00 Rudi Theunissen : > 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 the= ir > 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 databa= se > 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 compa= re > 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 bu= t > one of them (perhaps a subclass) has a private property. These two object= s > could be considered equal to the outside world, but `=3D=3D` would return > `false`. When a developer added this private property, it might not have > been obvious that they were affecting equality. This makes `=3D=3D` check= s 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 =3D new stdClass(); > $b =3D new stdClass(); > > $a->prop =3D 1; > $b->prop =3D true; > > $a =3D=3D $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 amou= nt > 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 i= f > 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 checkin= g > 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. Al= l > 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 t= he > apple does not equal the orange. However, comparing the apple to an orang= e > 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 `=3D=3D` or in funct= ions > 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 valu= es > using `<`, `>`, or in functions like `sort`. > > > Issues to be discussed: > > 1. What happens when we use `<=3D` and `>=3D`? Does the "or equal to" par= t call > `__equals` or does it check if `__compareTo` returns 0? > > 2. Should we also expose strict comparison, ie. `=3D=3D=3D` ? > > 3. Naming: > - `__eq` > - `__equalTo` > - `__equals` > - `__compareTo` > - `__comparedTo` > - `__compare` > - `__cmp` > Thanks for reanimating this subject. --=20 regards / pozdrawiam, -- Micha=C5=82 Brzuchalski about.me/brzuchal brzuchalski.com --000000000000b1b60c056f26178d--