rfc:comparable

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:comparable [2010/10/01 08:49] – Updated patch; added some more detail based on the Internals discussion. aharveyrfc:comparable [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 1: Line 1:
 ====== Request for Comments: Comparable ====== ====== Request for Comments: Comparable ======
-  * Version: 1.1 +  * Version: 7.0 
-  * Date: 2010-09-30+  * Date: 2010-09-30, updated 2015-02-19
   * Author: Adam Harvey <aharvey@php.net>   * Author: Adam Harvey <aharvey@php.net>
   * Status: Under Discussion   * Status: Under Discussion
Line 7: Line 7:
  
  
-This RFC offers a Comparable interface which can be used to implement userspace ordering of objects.+This RFC offers a Comparable interface which can be used to implement userspace comparison of objects to other values.
  
 ===== Introduction ===== ===== Introduction =====
  
-Many other languages offer the ability to provide a method on a class which will be used when instances of that class are compared via comparison or equality operators. For example, Java provides the [[http://download-llnw.oracle.com/javase/6/docs/api/java/lang/Comparable.html|Comparable]] interface, while Python provides the [[http://docs.python.org/reference/datamodel.html#object.__cmp__|__cmp__]] magic method.+Many other languages offer the ability to provide a method on a class which will be used when instances of that class are compared via comparison or equality operators. For example, Java provides the [[http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html|Comparable]] interface, while Python provides the [[http://docs.python.org/reference/datamodel.html#object.__cmp__|__cmp__]] magic method
 + 
 +The need for this has only increased as time has gone past, and particularly with the recent implementation of the spaceship operator.
  
 ===== Interface ===== ===== Interface =====
Line 20: Line 22:
 <?php <?php
 interface Comparable { interface Comparable {
-    public function compareTo($o);+    public function compareTo($other);
 } }
 ?> ?>
 </code> </code>
 +
 +This interface intentionally allows variables of any type to be passed to compareTo(): there are use cases where users may want to compare objects to non-object values, such as money and bigint types, where you may want to compare the object to a numeric value.
  
 ===== Sample Code ===== ===== Sample Code =====
Line 71: Line 75:
 ===== Implementation ===== ===== Implementation =====
  
-The patch below implements the Comparable interface within the Zend Engine in the same manner as interfaces such as Serializable. The changes to the Zend Engine are limited to the zend_interfaces.c and zend_operators.c files, and merely involve extending the zend_compare_objects() function to check if the first object implements the Countable interface, and if so, to call the compareTo() method, updating compare_function() to call zend_compare_objects() when appropriate, and the definition of the interface itself. Comparison cases not involving objects are unaffected.+The PR linked below implements the Comparable interface by providing a new standard object handler for the compare object handler which checks if the object implements Comparable, and if so, calls the compareTo() method
 + 
 +The only change to compare_function() is to ensure that the compare handler is called for the IS_NULL/IS_OBJECT pairs (which probably should have happened anyway), and to allow the compare_objects handler to be used if compare fails.
  
 ===== FAQ ===== ===== FAQ =====
  
-Is only $a checked for Comparable or also $b?+=== Is only $a checked for Comparable or also $b? ===
  
 Both $a and $b are checked. Both $a and $b are checked.
  
-How it is ensured that if $a < $b then $b > $a?+=== How it is ensured that if $a < $b then $b > $a? ===
  
 That's up to the userspace developer to get right when they're implementing their compareTo method. I expect the manual would have a dire warning about the possible consequences of not making them equivalent. That's up to the userspace developer to get right when they're implementing their compareTo method. I expect the manual would have a dire warning about the possible consequences of not making them equivalent.
  
-Would sorting work with it?+=== Would sorting work with it? ===
  
 Yes. Yes.
  
-If both $a and $b are objects with different compare functions, how it is determined whose function is used? Note that operators like == are assumed to be commutative, and less/more operators are assumed to be commutative in pairs, like above.+=== If both $a and $b are objects with different compare functions, how it is determined whose function is used? Note that operators like == are assumed to be commutative, and less/more operators are assumed to be commutative in pairs, like above. ===
  
 The left operand wins, so $a. The left operand wins, so $a.
  
-What if the objects are not of the same class? What if one is of a subclass of the other? Is equality not symmetric?+=== What if the objects are not of the same class? What if one is of a subclass of the other? Is equality not symmetric? ===
  
 Equality is symmetric to the extent that $a->compareTo($b) should return the inverse of $b->compareTo($a). Equality is not required to be symmetric in terms of both objects sharing the same compareTo() method, and comparisons across different class hierarchies are explicitly allowed. Equality is symmetric to the extent that $a->compareTo($b) should return the inverse of $b->compareTo($a). Equality is not required to be symmetric in terms of both objects sharing the same compareTo() method, and comparisons across different class hierarchies are explicitly allowed.
  
-How do you interact with 'get' and 'cast_object'/'__tostring'?+=== How does this interact with 'get' and 'cast_object'/'__tostring'? ===
  
 The tests for whether the operands implement Comparable occur before any potential calls to get and cast_object. The tests for whether the operands implement Comparable occur before any potential calls to get and cast_object.
 +
 +=== How does this interact with the compare_objects handler? ===
 +
 +This will take precedence over a compare_objects handler. This is consistent with the current compare_function() implementation, which calls the compare handler first.
 +
 +In practice, I think it's unlikely that an internal class (or a class extending such an internal class) with a compare_objects handler would also implement Comparable.
  
 ===== Concerns ===== ===== Concerns =====
Line 106: Line 118:
   * Comparison of objects with non-objects may become confusing, particularly if scalar casting is added to the mix.   * Comparison of objects with non-objects may become confusing, particularly if scalar casting is added to the mix.
   * Comparison of objects with objects of a different class may be confusing or ill-defined.   * Comparison of objects with objects of a different class may be confusing or ill-defined.
 +  * Why we use interface instead of magic method. Comparable is not reserved currently, but methods started with __ are always reserved.
  
 ===== Alternative Approaches ===== ===== Alternative Approaches =====
Line 117: Line 130:
 ===== Patches ===== ===== Patches =====
  
-  * Current patch: [[http://www.adamharvey.name/patches/comparable-v2.diff.txt]] +  * PR against master: [[https://github.com/php/php-src/pull/1097]] 
-  * Initial patch, now obsolete: [[http://www.adamharvey.name/patches/comparable.diff.txt]]+  * Obsolete v1.1 patch against 5.4: [[http://www.adamharvey.name/patches/comparable-v2.diff.txt]] 
 +  * Obsolete v1.0 patch against 5.4: [[http://www.adamharvey.name/patches/comparable.diff.txt]]
  
 ===== Changelog ===== ===== Changelog =====
  
 +  * 2015-02-19: Reanimated RFC; developed new patch that uses the compare handler instead of heavily changing compare_function().
   * 2010-10-01: Revised patch to remove SPL dependency; added a few questions and answers from the mailing list and a list of concerns raised.   * 2010-10-01: Revised patch to remove SPL dependency; added a few questions and answers from the mailing list and a list of concerns raised.
   * 2010-09-30: Initial proposal.   * 2010-09-30: Initial proposal.
rfc/comparable.1285922962.txt.gz · Last modified: 2017/09/22 13:28 (external edit)