about summary refs log tree commit diff
path: root/src/libstd/cmp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/cmp.rs')
-rw-r--r--src/libstd/cmp.rs118
1 files changed, 91 insertions, 27 deletions
diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs
index e956a1cdf1d..6e62cd42e2c 100644
--- a/src/libstd/cmp.rs
+++ b/src/libstd/cmp.rs
@@ -10,17 +10,36 @@
 
 /*!
 
-The `Ord` and `Eq` comparison traits
+Defines the `Ord` and `Eq` comparison traits.
 
-This module contains the definition of both `Ord` and `Eq` which define
-the common interfaces for doing comparison. Both are language items
-that the compiler uses to implement the comparison operators. Rust code
-may implement `Ord` to overload the `<`, `<=`, `>`, and `>=` operators,
-and `Eq` to overload the `==` and `!=` operators.
+This module defines both `Ord` and `Eq` traits which are used by the compiler
+to implement comparison operators.
+Rust programs may implement `Ord` to overload the `<`, `<=`, `>`, and `>=` operators,
+and may implement `Eq` to overload the `==` and `!=` operators.
 
-*/
+For example, to define a type with a customized definition for the Eq operators,
+you could do the following:
+
+```rust
+// Our type.
+struct SketchyNum {
+    num : int
+}
+
+// Our implementation of `Eq` to support `==` and `!=`.
+impl Eq for SketchyNum {
+    // Our custom eq allows numbers which are near eachother to be equal! :D
+    fn eq(&self, other: &SketchyNum) -> bool {
+        (self.num - other.num).abs() < 5
+    }
+}
 
-#[allow(missing_doc)];
+// Now these binary operators will work when applied!
+assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
+assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
+```
+
+*/
 
 /**
 * Trait for values that can be compared for equality and inequality.
@@ -35,14 +54,15 @@ and `Eq` to overload the `==` and `!=` operators.
 */
 #[lang="eq"]
 pub trait Eq {
+    /// This method tests for `self` and `other` values to be equal, and is used by `==`.
     fn eq(&self, other: &Self) -> bool;
 
+    /// This method tests for `!=`.
     #[inline]
     fn ne(&self, other: &Self) -> bool { !self.eq(other) }
 }
 
 /// Trait for equality comparisons where `a == b` and `a != b` are strict inverses.
-#[cfg(not(stage0))]
 pub trait TotalEq: Eq {
     // FIXME #13101: this method is used solely by #[deriving] to
     // assert that every component of a type implements #[deriving]
@@ -56,15 +76,7 @@ pub trait TotalEq: Eq {
     fn assert_receiver_is_total_eq(&self) {}
 }
 
-#[cfg(stage0)]
-pub trait TotalEq: Eq {
-    /// This method must return the same value as `eq`. It exists to prevent
-    /// deriving `TotalEq` from fields not implementing the `TotalEq` trait.
-    fn equals(&self, other: &Self) -> bool {
-        self.eq(other)
-    }
-}
-
+/// A macro which defines an implementation of TotalEq for a given type.
 macro_rules! totaleq_impl(
     ($t:ty) => {
         impl TotalEq for $t {}
@@ -88,11 +100,29 @@ totaleq_impl!(uint)
 
 totaleq_impl!(char)
 
+/// An ordering is, e.g, a result of a comparison between two values.
 #[deriving(Clone, Eq, Show)]
-pub enum Ordering { Less = -1, Equal = 0, Greater = 1 }
+pub enum Ordering {
+   /// An ordering where a compared value is less [than another].
+   Less = -1,
+   /// An ordering where a compared value is equal [to another].
+   Equal = 0,
+   /// An ordering where a compared value is greater [than another].
+   Greater = 1
+}
 
-/// Trait for types that form a total order
+/// Trait for types that form a total order.
 pub trait TotalOrd: TotalEq + Ord {
+    /// This method returns an ordering between `self` and `other` values.
+    ///
+    /// By convention, `self.cmp(&other)` returns the ordering matching
+    /// the expression `self <operator> other` if true.  For example:
+    ///
+    /// ```
+    /// assert_eq!( 5u.cmp(&10), Less);     // because 5 < 10
+    /// assert_eq!(10u.cmp(&5),  Greater);  // because 10 > 5
+    /// assert_eq!( 5u.cmp(&5),  Equal);    // because 5 == 5
+    /// ```
     fn cmp(&self, other: &Self) -> Ordering;
 }
 
@@ -109,6 +139,7 @@ impl Ord for Ordering {
     fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) }
 }
 
+/// A macro which defines an implementation of TotalOrd for a given type.
 macro_rules! totalord_impl(
     ($t:ty) => {
         impl TotalOrd for $t {
@@ -138,8 +169,11 @@ totalord_impl!(uint)
 totalord_impl!(char)
 
 /**
-Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the
-lexical ordering on a type `(int, int)`.
+ * Combine orderings, lexically.
+ *
+ * For example for a type `(int, int)`, two comparisons could be done.
+ * If the first ordering is different, the first ordering is all that must be returned.
+ * If the first ordering is equal, then second ordering is returned.
 */
 #[inline]
 pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
@@ -161,11 +195,18 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
 */
 #[lang="ord"]
 pub trait Ord: Eq {
+    /// This method tests less than (for `self` and `other`) and is used by the `<` operator.
     fn lt(&self, other: &Self) -> bool;
+
+    /// This method tests less than or equal to (`<=`).
     #[inline]
     fn le(&self, other: &Self) -> bool { !other.lt(self) }
+
+    /// This method tests greater than (`>`).
     #[inline]
     fn gt(&self, other: &Self) -> bool {  other.lt(self) }
+
+    /// This method tests greater than or equal to (`>=`).
     #[inline]
     fn ge(&self, other: &Self) -> bool { !self.lt(other) }
 }
@@ -175,14 +216,17 @@ pub trait Ord: Eq {
 /// container types; e.g. it is often desirable to be able to use `&str`
 /// values to look up entries in a container with `~str` keys.
 pub trait Equiv<T> {
+    /// Implement this function to decide equivalent values.
     fn equiv(&self, other: &T) -> bool;
 }
 
+/// Compare and return the minimum of two values.
 #[inline]
 pub fn min<T: TotalOrd>(v1: T, v2: T) -> T {
     if v1 < v2 { v1 } else { v2 }
 }
 
+/// Compare and return the maximum of two values.
 #[inline]
 pub fn max<T: TotalOrd>(v1: T, v2: T) -> T {
     if v1 > v2 { v1 } else { v2 }
@@ -194,11 +238,11 @@ mod test {
 
     #[test]
     fn test_int_totalord() {
-        assert_eq!(5.cmp(&10), Less);
-        assert_eq!(10.cmp(&5), Greater);
-        assert_eq!(5.cmp(&5), Equal);
-        assert_eq!((-5).cmp(&12), Less);
-        assert_eq!(12.cmp(-5), Greater);
+        assert_eq!(5u.cmp(&10), Less);
+        assert_eq!(10u.cmp(&5), Greater);
+        assert_eq!(5u.cmp(&5), Equal);
+        assert_eq!((-5u).cmp(&12), Less);
+        assert_eq!(12u.cmp(-5), Greater);
     }
 
     #[test]
@@ -220,4 +264,24 @@ mod test {
             t(Greater, o, Greater);
          }
     }
+
+    #[test]
+    fn test_user_defined_eq() {
+        // Our type.
+        struct SketchyNum {
+            num : int
+        }
+
+        // Our implementation of `Eq` to support `==` and `!=`.
+        impl Eq for SketchyNum {
+            // Our custom eq allows numbers which are near eachother to be equal! :D
+            fn eq(&self, other: &SketchyNum) -> bool {
+                (self.num - other.num).abs() < 5
+            }
+        }
+
+        // Now these binary operators will work when applied!
+        assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
+        assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
+    }
 }