From 1b1e4caa79077d48c1bf56bf5bfa7bfc83fdf941 Mon Sep 17 00:00:00 2001 From: Huon Wilson Date: Thu, 19 Dec 2013 23:03:11 +1100 Subject: [PATCH] std::vec: add a sugary .sort() method for plain Ord sorting. This moves the custom sorting to `.sort_by`. --- src/libextra/glob.rs | 2 +- src/libextra/priority_queue.rs | 8 ++- src/libextra/stats.rs | 6 +- src/libextra/test.rs | 5 +- src/librustc/lib.rs | 2 +- src/librustc/metadata/cstore.rs | 2 +- src/librustc/metadata/encoder.rs | 2 +- src/librustc/middle/check_match.rs | 2 +- src/librustc/middle/trans/base.rs | 2 +- src/librustdoc/html/render.rs | 2 +- src/libstd/prelude.rs | 2 +- src/libstd/vec.rs | 69 +++++++++++++++++-- src/libsyntax/attr.rs | 4 ++ src/test/bench/shootout-k-nucleotide-pipes.rs | 4 +- src/test/bench/shootout-k-nucleotide.rs | 2 +- src/test/run-pass/vector-sort-failure-safe.rs | 4 +- 16 files changed, 91 insertions(+), 27 deletions(-) diff --git a/src/libextra/glob.rs b/src/libextra/glob.rs index 75795d139915..78651b818fa5 100644 --- a/src/libextra/glob.rs +++ b/src/libextra/glob.rs @@ -148,7 +148,7 @@ impl Iterator for GlobIterator { fn list_dir_sorted(path: &Path) -> ~[Path] { match io::result(|| fs::readdir(path)) { Ok(mut children) => { - children.sort(|p1, p2| p2.filename() <= p1.filename()); + children.sort_by(|p1, p2| p2.filename() <= p1.filename()); children } Err(..) => ~[] diff --git a/src/libextra/priority_queue.rs b/src/libextra/priority_queue.rs index d2cace5e6f4c..3c1743cfe34c 100644 --- a/src/libextra/priority_queue.rs +++ b/src/libextra/priority_queue.rs @@ -231,7 +231,11 @@ mod tests { fn test_top_and_pop() { let data = ~[2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]; let mut sorted = data.clone(); +<<<<<<< HEAD sorted.sort(|x, y| x.le(y)); +======= + sorted.sort(); +>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting. let mut heap = PriorityQueue::from_vec(data); while !heap.is_empty() { assert_eq!(heap.top(), sorted.last()); @@ -314,8 +318,8 @@ mod tests { fn check_to_vec(mut data: ~[int]) { let heap = PriorityQueue::from_vec(data.clone()); let mut v = heap.clone().to_vec(); - v.sort(|x, y| x.le(y)); - data.sort(|x, y| x.le(y)); + v.sort(); + data.sort(); assert_eq!(v, data); assert_eq!(heap.to_sorted_vec(), data); diff --git a/src/libextra/stats.rs b/src/libextra/stats.rs index e4ef5723dd39..ba8f7d4f23f1 100644 --- a/src/libextra/stats.rs +++ b/src/libextra/stats.rs @@ -239,13 +239,13 @@ impl<'a> Stats for &'a [f64] { fn percentile(self, pct: f64) -> f64 { let mut tmp = self.to_owned(); - tmp.sort(|a,b| a <= b); + tmp.sort(); percentile_of_sorted(tmp, pct) } fn quartiles(self) -> (f64,f64,f64) { let mut tmp = self.to_owned(); - tmp.sort(|a,b| a <= b); + tmp.sort(); let a = percentile_of_sorted(tmp, 25.0); let b = percentile_of_sorted(tmp, 50.0); let c = percentile_of_sorted(tmp, 75.0); @@ -290,7 +290,7 @@ fn percentile_of_sorted(sorted_samples: &[f64], /// See: http://en.wikipedia.org/wiki/Winsorising pub fn winsorize(samples: &mut [f64], pct: f64) { let mut tmp = samples.to_owned(); - tmp.sort(|a,b| a <= b); + tmp.sort(); let lo = percentile_of_sorted(tmp, pct); let hi = percentile_of_sorted(tmp, 100.0-pct); for samp in samples.mut_iter() { diff --git a/src/libextra/test.rs b/src/libextra/test.rs index af22aad7b5e4..dd29a4d8d479 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -37,7 +37,6 @@ use std::to_str::ToStr; use std::f64; use std::os; - // The name of a test. By convention this follows the rules for rust // paths; i.e. it should be a series of identifiers separated by double // colons. This way if some test runner wants to arrange the tests @@ -487,7 +486,7 @@ impl ConsoleTestState { for f in self.failures.iter() { failures.push(f.name.to_str()); } - failures.sort(|a,b| a <= b); + failures.sort(); for name in failures.iter() { self.write_plain(format!(" {}\n", name.to_str())); } @@ -841,7 +840,7 @@ pub fn filter_tests( fn lteq(t1: &TestDescAndFn, t2: &TestDescAndFn) -> bool { t1.desc.name.to_str() <= t2.desc.name.to_str() } - filtered.sort(lteq); + filtered.sort_by(lteq); // Shard the remaining tests, if sharding requested. match opts.test_shard { diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 6647866cd48c..a74497208c01 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -162,7 +162,7 @@ Available lint options: let mut lint_dict = lint_dict.move_iter() .map(|(k, v)| (v, k)) .collect::<~[(lint::LintSpec, &'static str)]>(); - lint_dict.sort(|a,b| a <= b); + lint_dict.sort(); let mut max_key = 0; for &(_, name) in lint_dict.iter() { diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 9f0f5af6c4ef..6eb280df8ee5 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -191,7 +191,7 @@ pub fn get_dep_hashes(cstore: &CStore) -> ~[@str] { }); } - result.sort(|a, b| (a.name, a.vers, a.hash) <= (b.name, b.vers, b.hash)); + result.sort(); debug!("sorted:"); for x in result.iter() { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 8f64df095697..5e709f0296cc 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1531,7 +1531,7 @@ fn encode_crate_deps(ecx: &EncodeContext, }); // Sort by cnum - deps.sort(|kv1, kv2| kv1.cnum <= kv2.cnum); + deps.sort_by(|kv1, kv2| kv1.cnum <= kv2.cnum); // Sanity-check the crate numbers let mut expected_cnum = 1; diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 47549986f447..4d4cda82055b 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -464,7 +464,7 @@ fn missing_ctor(cx: &MatchCheckCtxt, // Sort them by length such that for patterns of the same length, // those with a destructured slice come first. - vec_pat_lens.sort(|&(len1, slice1), &(len2, slice2)| { + vec_pat_lens.sort_by(|&(len1, slice1), &(len2, slice2)| { if len1 == len2 { slice1 > slice2 } else { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 3c8e64672047..831c3ccce9d4 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -3163,7 +3163,7 @@ pub fn trans_crate(sess: session::Session, println!("n_closures: {}", ccx.stats.n_closures); println("fn stats:"); - ccx.stats.fn_stats.sort(|&(_, _, insns_a), &(_, _, insns_b)| insns_a >= insns_b); + ccx.stats.fn_stats.sort_by(|&(_, _, insns_a), &(_, _, insns_b)| insns_a >= insns_b); for tuple in ccx.stats.fn_stats.iter() { match *tuple { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 441661c793b4..b474bbca865b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -935,7 +935,7 @@ fn item_module(w: &mut Writer, cx: &Context, } debug!("{:?}", indices); - indices.sort(|&i1, &i2| le(&items[i1], &items[i2], i1, i2)); + indices.sort_by(|&i1, &i2| le(&items[i1], &items[i2], i1, i2)); debug!("{:?}", indices); let mut curty = ""; diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 47004ea173f3..91aa3470ff47 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -79,7 +79,7 @@ pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4}; pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8}; pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12}; pub use vec::{ImmutableEqVector, ImmutableTotalOrdVector, ImmutableCopyableVector}; -pub use vec::{OwnedVector, OwnedCopyableVector,OwnedEqVector, MutableVector}; +pub use vec::{OwnedVector, OwnedCopyableVector,OwnedEqVector, MutableVector, MutableOrdVector}; pub use vec::{Vector, VectorVector, CopyableVector, ImmutableVector}; // Reexported runtime types diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 7cdf155e6142..58392774fa01 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -2181,7 +2181,7 @@ pub trait MutableVector<'a, T> { /// v.sort(|a, b| *b <= *a); /// assert_eq!(v, [5, 4, 3, 2, 1]); /// ``` - fn sort(self, less_eq: |&T, &T| -> bool); + fn sort_by(self, less_eq: |&T, &T| -> bool); /** * Consumes `src` and moves as many elements as it can into `self` @@ -2328,7 +2328,11 @@ impl<'a,T> MutableVector<'a, T> for &'a mut [T] { } #[inline] +<<<<<<< HEAD fn sort(self, less_eq: |&T, &T| -> bool) { +======= + fn sort_by>(self, less_eq: Sort) { +>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting. merge_sort(self, less_eq) } @@ -2385,6 +2389,32 @@ impl<'a, T:Clone> MutableCloneableVector for &'a mut [T] { } } +/// Methods for mutable vectors with orderable elements, such as +/// in-place sorting. +pub trait MutableOrdVector { + /// Sort the vector, in place. + /// + /// This is equivalent to `self.sort_by(std::vec::SortForward)`. + /// + /// # Example + /// + /// ```rust + /// use std::vec; + /// + /// let mut v = [-5, 4, 1, -3, 2]; + /// + /// v.sort(); + /// assert_eq!(v, [-5, -3, 1, 2, 4]); + /// ``` + fn sort(self); +} +impl<'a, T: Ord> MutableOrdVector for &'a mut [T] { + #[inline] + fn sort(self) { + self.sort_by(SortForward) + } +} + /** * Constructs a vector from an unsafe pointer to a buffer * @@ -3474,16 +3504,39 @@ mod tests { let mut v = task_rng().gen_vec::(len); v.sort(|a,b| a <= b); +<<<<<<< HEAD assert!(v.windows(2).all(|w| w[0] <= w[1])); +======= + let mut v1 = v.clone(); + let mut v2 = v.clone(); + v.sort(); + assert!(v.windows(2).all(|w| w[0] <= w[1])); + + v1.sort_by(vec::SortForward); + assert!(v1.windows(2).all(|w| w[0] <= w[1])); + + v1.sort_by(vec::SortReverse); + assert!(v1.windows(2).all(|w| w[0] >= w[1])); + + v2.sort_by(|a: &uint, b: &uint| a <= b); + assert!(v2.windows(2).all(|w| w[0] <= w[1])); +>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting. } } // shouldn't fail/crash let mut v: [uint, .. 0] = []; +<<<<<<< HEAD v.sort(|a,b| a <= b); let mut v = [0xDEADBEEF]; v.sort(|a,b| a <= b); +======= + v.sort_by(SortForward); + + let mut v = [0xDEADBEEF]; + v.sort_by(SortForward); +>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting. assert_eq!(v, [0xDEADBEEF]); } @@ -3506,7 +3559,11 @@ mod tests { // only sort on the first element, so an unstable sort // may mix up the counts. +<<<<<<< HEAD v.sort(|&(a,_), &(b,_)| a <= b); +======= + v.sort_by(|&(a,_): &(uint, uint), &(b,_): &(uint, uint)| a <= b); +>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting. // this comparison includes the count (the second item // of the tuple), so elements with equal first items @@ -4341,7 +4398,7 @@ mod bench { use extra::test::BenchHarness; use iter::range; use vec; - use vec::VectorVector; + use vec::{VectorVector, MutableOrdVector}; use option::*; use ptr; use rand::{weak_rng, task_rng, Rng}; @@ -4551,7 +4608,7 @@ mod bench { let mut rng = weak_rng(); bh.iter(|| { let mut v: ~[f64] = rng.gen_vec(5); - v.sort(|a,b| *a <= *b); + v.sort(); }); bh.bytes = 5 * mem::size_of::() as u64; } @@ -4561,7 +4618,7 @@ mod bench { let mut rng = weak_rng(); bh.iter(|| { let mut v: ~[f64] = rng.gen_vec(100); - v.sort(|a,b| *a <= *b); + v.sort(); }); bh.bytes = 100 * mem::size_of::() as u64; } @@ -4571,7 +4628,7 @@ mod bench { let mut rng = weak_rng(); bh.iter(|| { let mut v: ~[f64] = rng.gen_vec(10000); - v.sort(|a,b| *a <= *b); + v.sort(); }); bh.bytes = 10000 * mem::size_of::() as u64; } @@ -4580,7 +4637,7 @@ mod bench { fn sort_sorted(bh: &mut BenchHarness) { let mut v = vec::from_fn(10000, |i| i); bh.iter(|| { - v.sort(|a,b| *a <= *b); + v.sort(); }); bh.bytes = (v.len() * mem::size_of_val(&v[0])) as u64; } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 9b616781d4f5..4564542f9293 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -203,7 +203,11 @@ pub fn sort_meta_items(items: &[@MetaItem]) -> ~[@MetaItem] { .map(|&mi| (mi.name(), mi)) .collect::<~[(@str, @MetaItem)]>(); +<<<<<<< HEAD v.sort(|&(a, _), &(b, _)| a <= b); +======= + v.sort_by(|&(a, _): &(@str, @MetaItem), &(b, _): &(@str, @MetaItem)| a <= b); +>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting. // There doesn't seem to be a more optimal way to do this v.move_iter().map(|(_, m)| { diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index f430817025e3..ca04f3d97048 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -54,8 +54,8 @@ fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str { // sort by key, then by value fn sortKV(mut orig: ~[(TT,UU)]) -> ~[(TT,UU)] { - orig.sort(le_by_key); - orig.sort(le_by_val); + orig.sort_by(le_by_key); + orig.sort_by(le_by_val); origin } diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 71da98677f12..067ef873fd3d 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -266,7 +266,7 @@ fn print_frequencies(frequencies: &Table, frame: i32) { for frequencies.each |entry| { vector.push((entry.code, entry.count)); } - vector.sort(|a,b| a <= b); + vector.sort(); let mut total_count = 0; for vector.each |&(_, count)| { diff --git a/src/test/run-pass/vector-sort-failure-safe.rs b/src/test/run-pass/vector-sort-failure-safe.rs index bae101bf58a4..ca82fb0422e7 100644 --- a/src/test/run-pass/vector-sort-failure-safe.rs +++ b/src/test/run-pass/vector-sort-failure-safe.rs @@ -48,7 +48,7 @@ pub fn main() { // work out the total number of comparisons required to sort // this array... let mut count = 0; - main.clone().sort(|a, b| { count += 1; a <= b }); + main.clone().sort_by(|a, b| { count += 1; a <= b }); // ... and then fail on each and every single one. for fail_countdown in range(0, count) { @@ -63,7 +63,7 @@ pub fn main() { std::task::try(proc() { let mut v = v; let mut fail_countdown = fail_countdown; - v.sort(|a, b| { + v.sort_by(|a, b| { if fail_countdown == 0 { fail!() }