add a TotalEq trait

This commit is contained in:
Daniel Micay 2013-03-27 15:20:44 -04:00
parent 91cb6687a8
commit d2b267bcb5
5 changed files with 115 additions and 24 deletions

View file

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -21,15 +21,13 @@
*/
/**
* Trait for values that can be compared for equality
* and inequality.
* Trait for values that can be compared for equality and inequality.
*
* Eventually this may be simplified to only require
* an `eq` method, with the other generated from
* a default implementation. However it should
* remain possible to implement `ne` separately, for
* compatibility with floating-point NaN semantics
* (cf. IEEE 754-2008 section 5.11).
* This trait allows partial equality, where types can be unordered instead of strictly equal or
* unequal. For example, with the built-in floating-point types `a == b` and `a != b` will both
* evaluate to false if either `a` or `b` is NaN (cf. IEEE 754-2008 section 5.11).
*
* Eventually, this will be implemented by default for types that implement `TotalEq`.
*/
#[lang="eq"]
pub trait Eq {
@ -37,11 +35,40 @@ pub trait Eq {
fn ne(&self, other: &Self) -> bool;
}
/// Trait for equality comparisons where `a == b` and `a != b` are strict inverses.
pub trait TotalEq {
fn equals(&self, other: &Self) -> bool;
}
macro_rules! totaleq_impl(
($t:ty) => {
impl TotalEq for $t {
#[inline(always)]
fn equals(&self, other: &$t) -> bool { *self == *other }
}
}
)
totaleq_impl!(bool)
totaleq_impl!(u8)
totaleq_impl!(u16)
totaleq_impl!(u32)
totaleq_impl!(u64)
totaleq_impl!(i8)
totaleq_impl!(i16)
totaleq_impl!(i32)
totaleq_impl!(i64)
totaleq_impl!(int)
totaleq_impl!(uint)
#[deriving(Eq)]
pub enum Ordering { Less, Equal, Greater }
/// Trait for types that form a total order
pub trait TotalOrd {
pub trait TotalOrd: TotalEq {
fn cmp(&self, other: &Self) -> Ordering;
}
@ -140,11 +167,17 @@ pub fn max<T:Ord>(v1: T, v2: T) -> T {
#[cfg(test)]
mod test {
#[test]
fn test_int() {
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);
}
#[test]
fn test_int_totaleq() {
fail_unless!(5.equals(&5));
fail_unless!(!2.equals(&17));
}
}

View file

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -15,7 +15,7 @@
*/
#[cfg(notest)]
use cmp::{Eq, Ord, TotalOrd, Ordering, Equal};
use prelude::*;
#[cfg(notest)]
impl Eq for () {
@ -42,3 +42,9 @@ impl TotalOrd for () {
#[inline(always)]
fn cmp(&self, _other: &()) -> Ordering { Equal }
}
#[cfg(notest)]
impl TotalEq for () {
#[inline(always)]
fn equals(&self, _other: &()) -> bool { true }
}

View file

@ -24,7 +24,7 @@
/* Reexported types and traits */
pub use clone::Clone;
pub use cmp::{Eq, Ord, TotalOrd, Ordering, Less, Equal, Greater};
pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
pub use container::{Container, Mutable, Map, Set};
pub use hash::Hash;
pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};

View file

@ -21,7 +21,7 @@
use cast;
use char;
use clone::Clone;
use cmp::{Equiv, TotalOrd, Ordering, Less, Equal, Greater};
use cmp::{Equiv, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
use libc;
use option::{None, Option, Some};
use ptr;
@ -930,6 +930,30 @@ fn eq(&self, other: &@str) -> bool {
fn ne(&self, other: &@str) -> bool { !(*self).eq(other) }
}
#[cfg(notest)]
impl<'self> TotalEq for &'self str {
#[inline(always)]
fn equals(&self, other: & &'self str) -> bool {
eq_slice((*self), (*other))
}
}
#[cfg(notest)]
impl TotalEq for ~str {
#[inline(always)]
fn equals(&self, other: &~str) -> bool {
eq_slice((*self), (*other))
}
}
#[cfg(notest)]
impl TotalEq for @str {
#[inline(always)]
fn equals(&self, other: &@str) -> bool {
eq_slice((*self), (*other))
}
}
#[cfg(notest)]
impl Ord for ~str {
#[inline(always)]

View file

@ -14,7 +14,7 @@
use container::{Container, Mutable};
use cast;
use cmp::{Eq, Equiv, Ord, TotalOrd, Ordering, Less, Equal, Greater};
use cmp::{Eq, Equiv, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
use clone::Clone;
use iter::BaseIter;
use iter;
@ -1547,7 +1547,7 @@ pub fn as_mut_buf<T,U>(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U {
// Equality
fn eq<T:Eq>(a: &[T], b: &[T]) -> bool {
fn eq<T: Eq>(a: &[T], b: &[T]) -> bool {
let (a_len, b_len) = (a.len(), b.len());
if a_len != b_len { return false; }
@ -1556,33 +1556,61 @@ fn eq<T:Eq>(a: &[T], b: &[T]) -> bool {
if a[i] != b[i] { return false; }
i += 1;
}
true
}
fn equals<T: TotalEq>(a: &[T], b: &[T]) -> bool {
let (a_len, b_len) = (a.len(), b.len());
if a_len != b_len { return false; }
let mut i = 0;
while i < a_len {
if !a[i].equals(&b[i]) { return false; }
i += 1;
}
true
}
#[cfg(notest)]
impl<'self,T:Eq> Eq for &'self [T] {
#[inline(always)]
fn eq(&self, other: & &'self [T]) -> bool { eq((*self), (*other)) }
fn eq(&self, other: & &'self [T]) -> bool { eq(*self, *other) }
#[inline(always)]
fn ne(&self, other: & &'self [T]) -> bool { !(*self).eq(other) }
fn ne(&self, other: & &'self [T]) -> bool { !self.eq(other) }
}
#[cfg(notest)]
impl<T:Eq> Eq for ~[T] {
#[inline(always)]
fn eq(&self, other: &~[T]) -> bool { eq((*self), (*other)) }
fn eq(&self, other: &~[T]) -> bool { eq(*self, *other) }
#[inline(always)]
fn ne(&self, other: &~[T]) -> bool { !(*self).eq(other) }
fn ne(&self, other: &~[T]) -> bool { !self.eq(other) }
}
#[cfg(notest)]
impl<T:Eq> Eq for @[T] {
#[inline(always)]
fn eq(&self, other: &@[T]) -> bool { eq((*self), (*other)) }
fn eq(&self, other: &@[T]) -> bool { eq(*self, *other) }
#[inline(always)]
fn ne(&self, other: &@[T]) -> bool { !(*self).eq(other) }
fn ne(&self, other: &@[T]) -> bool { !self.eq(other) }
}
#[cfg(notest)]
impl<'self,T:TotalEq> TotalEq for &'self [T] {
#[inline(always)]
fn equals(&self, other: & &'self [T]) -> bool { equals(*self, *other) }
}
#[cfg(notest)]
impl<T:TotalEq> TotalEq for ~[T] {
#[inline(always)]
fn equals(&self, other: &~[T]) -> bool { equals(*self, *other) }
}
#[cfg(notest)]
impl<T:TotalEq> TotalEq for @[T] {
#[inline(always)]
fn equals(&self, other: &@[T]) -> bool { equals(*self, *other) }
}
#[cfg(notest)]