[std::cmp] add missing docs and provide an example

This commit is contained in:
Kevin Cantu 2014-03-16 14:26:54 -07:00
parent 7056f97093
commit 02c9c94ddd
1 changed files with 91 additions and 17 deletions

View File

@ -10,18 +10,37 @@
/*! /*!
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 This module defines both `Ord` and `Eq` traits which are used by the compiler
the common interfaces for doing comparison. Both are language items to implement comparison operators.
that the compiler uses to implement the comparison operators. Rust code Rust programs may implement `Ord` to overload the `<`, `<=`, `>`, and `>=` operators,
may implement `Ord` to overload the `<`, `<=`, `>`, and `>=` operators, and may implement `Eq` to overload the `==` and `!=` operators.
and `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
}
}
// Now these binary operators will work when applied!
assert!(SketchyNum {num: 37} == SketchyNum {num: 34});
assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
```
*/ */
#![allow(missing_doc)]
/** /**
* Trait for values that can be compared for equality and inequality. * Trait for values that can be compared for equality and inequality.
* *
@ -35,8 +54,10 @@ and `Eq` to overload the `==` and `!=` operators.
*/ */
#[lang="eq"] #[lang="eq"]
pub trait 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; fn eq(&self, other: &Self) -> bool;
/// This method tests for `!=`.
#[inline] #[inline]
fn ne(&self, other: &Self) -> bool { !self.eq(other) } fn ne(&self, other: &Self) -> bool { !self.eq(other) }
} }
@ -55,6 +76,7 @@ pub trait TotalEq: Eq {
fn assert_receiver_is_total_eq(&self) {} fn assert_receiver_is_total_eq(&self) {}
} }
/// A macro which defines an implementation of TotalEq for a given type.
macro_rules! totaleq_impl( macro_rules! totaleq_impl(
($t:ty) => { ($t:ty) => {
impl TotalEq for $t {} impl TotalEq for $t {}
@ -78,11 +100,29 @@ totaleq_impl!(uint)
totaleq_impl!(char) totaleq_impl!(char)
/// An ordering is, e.g, a result of a comparison between two values.
#[deriving(Clone, Eq, Show)] #[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 { 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; fn cmp(&self, other: &Self) -> Ordering;
} }
@ -99,6 +139,7 @@ impl Ord for Ordering {
fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) } 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( macro_rules! totalord_impl(
($t:ty) => { ($t:ty) => {
impl TotalOrd for $t { impl TotalOrd for $t {
@ -128,8 +169,11 @@ totalord_impl!(uint)
totalord_impl!(char) totalord_impl!(char)
/** /**
Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the * Combine orderings, lexically.
lexical ordering on a type `(int, int)`. *
* 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] #[inline]
pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering { pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
@ -151,11 +195,18 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
*/ */
#[lang="ord"] #[lang="ord"]
pub trait Ord: Eq { 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; fn lt(&self, other: &Self) -> bool;
/// This method tests less than or equal to (`<=`).
#[inline] #[inline]
fn le(&self, other: &Self) -> bool { !other.lt(self) } fn le(&self, other: &Self) -> bool { !other.lt(self) }
/// This method tests greater than (`>`).
#[inline] #[inline]
fn gt(&self, other: &Self) -> bool { other.lt(self) } fn gt(&self, other: &Self) -> bool { other.lt(self) }
/// This method tests greater than or equal to (`>=`).
#[inline] #[inline]
fn ge(&self, other: &Self) -> bool { !self.lt(other) } fn ge(&self, other: &Self) -> bool { !self.lt(other) }
} }
@ -165,14 +216,17 @@ pub trait Ord: Eq {
/// container types; e.g. it is often desirable to be able to use `&str` /// 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. /// values to look up entries in a container with `~str` keys.
pub trait Equiv<T> { pub trait Equiv<T> {
/// Implement this function to decide equivalent values.
fn equiv(&self, other: &T) -> bool; fn equiv(&self, other: &T) -> bool;
} }
/// Compare and return the minimum of two values.
#[inline] #[inline]
pub fn min<T: TotalOrd>(v1: T, v2: T) -> T { pub fn min<T: TotalOrd>(v1: T, v2: T) -> T {
if v1 < v2 { v1 } else { v2 } if v1 < v2 { v1 } else { v2 }
} }
/// Compare and return the maximum of two values.
#[inline] #[inline]
pub fn max<T: TotalOrd>(v1: T, v2: T) -> T { pub fn max<T: TotalOrd>(v1: T, v2: T) -> T {
if v1 > v2 { v1 } else { v2 } if v1 > v2 { v1 } else { v2 }
@ -184,11 +238,11 @@ mod test {
#[test] #[test]
fn test_int_totalord() { fn test_int_totalord() {
assert_eq!(5.cmp(&10), Less); assert_eq!(5u.cmp(&10), Less);
assert_eq!(10.cmp(&5), Greater); assert_eq!(10u.cmp(&5), Greater);
assert_eq!(5.cmp(&5), Equal); assert_eq!(5u.cmp(&5), Equal);
assert_eq!((-5).cmp(&12), Less); assert_eq!((-5u).cmp(&12), Less);
assert_eq!(12.cmp(-5), Greater); assert_eq!(12u.cmp(-5), Greater);
} }
#[test] #[test]
@ -210,4 +264,24 @@ mod test {
t(Greater, o, Greater); 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});
}
} }