@@ -131,15 +131,41 @@ type Comparable interface {
131131 CompareSameType (op syntax.Token , y Value , depth int ) (bool , error )
132132}
133133
134+ // A TotallyOrdered is a type whose values form a total order:
135+ // if x and y are of the same TotallyOrdered type, then x must be less than y,
136+ // greater than y, or equal to y.
137+ //
138+ // It is simpler than Comparable and should be preferred in new code,
139+ // but if a type implements both interfaces, Comparable takes precedence.
140+ type TotallyOrdered interface {
141+ Value
142+ // Cmp compares two values x and y of the same totally ordered type.
143+ // It returns negative if x < y, positive if x > y, and zero if the values are equal.
144+ //
145+ // Implementations that recursively compare subcomponents of
146+ // the value should use the CompareDepth function, not Cmp, to
147+ // avoid infinite recursion on cyclic structures.
148+ //
149+ // The depth parameter is used to bound comparisons of cyclic
150+ // data structures. Implementations should decrement depth
151+ // before calling CompareDepth and should return an error if depth
152+ // < 1.
153+ //
154+ // Client code should not call this method. Instead, use the
155+ // standalone Compare or Equals functions, which are defined for
156+ // all pairs of operands.
157+ Cmp (y Value , depth int ) (int , error )
158+ }
159+
134160var (
135- _ Comparable = Int {}
136- _ Comparable = False
137- _ Comparable = Float ( 0 )
138- _ Comparable = String ("" )
139- _ Comparable = (* Dict )(nil )
140- _ Comparable = (* List )(nil )
141- _ Comparable = Tuple (nil )
142- _ Comparable = (* Set )(nil )
161+ _ TotallyOrdered = Int {}
162+ _ TotallyOrdered = Float ( 0 )
163+ _ Comparable = False
164+ _ Comparable = String ("" )
165+ _ Comparable = (* Dict )(nil )
166+ _ Comparable = (* List )(nil )
167+ _ Comparable = Tuple (nil )
168+ _ Comparable = (* Set )(nil )
143169)
144170
145171// A Callable value f may be the operand of a function call, f(x).
@@ -439,9 +465,9 @@ func isFinite(f float64) bool {
439465 return math .Abs (f ) <= math .MaxFloat64
440466}
441467
442- func (x Float ) CompareSameType ( op syntax. Token , y_ Value , depth int ) (bool , error ) {
468+ func (x Float ) Cmp ( y_ Value , depth int ) (int , error ) {
443469 y := y_ .(Float )
444- return threeway ( op , floatCmp (x , y ) ), nil
470+ return floatCmp (x , y ), nil
445471}
446472
447473// floatCmp performs a three-valued comparison on floats,
@@ -1299,6 +1325,14 @@ func CompareDepth(op syntax.Token, x, y Value, depth int) (bool, error) {
12991325 return xcomp .CompareSameType (op , y , depth )
13001326 }
13011327
1328+ if xcomp , ok := x .(TotallyOrdered ); ok {
1329+ t , err := xcomp .Cmp (y , depth )
1330+ if err != nil {
1331+ return false , err
1332+ }
1333+ return threeway (op , t ), nil
1334+ }
1335+
13021336 // use identity comparison
13031337 switch op {
13041338 case syntax .EQL :
0 commit comments