From 84030fd05a6d6b0bc3d31cf638bc8c88adae7a41 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sat, 30 Aug 2014 17:11:22 -0400 Subject: [PATCH 1/2] Move info into individual modules. --- src/libcollections/priority_queue.rs | 5 +++++ src/libcollections/ringbuf.rs | 8 ++++---- src/libcollections/treemap.rs | 10 +++++++--- src/libcollections/trie.rs | 9 +++++++-- src/libcollections/vec.rs | 4 +++- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/libcollections/priority_queue.rs b/src/libcollections/priority_queue.rs index da8cf085218..68e2086d042 100644 --- a/src/libcollections/priority_queue.rs +++ b/src/libcollections/priority_queue.rs @@ -10,6 +10,11 @@ //! A priority queue implemented with a binary heap. //! +//! Insertions have `O(log n)` time complexity and checking or popping the largest element is +//! `O(1)`. Converting a vector to a priority queue can be done in-place, and has `O(n)` +//! complexity. A priority queue can also be converted to a sorted vector in-place, allowing it to +//! be used for an `O(n log n)` in-place heapsort. +//! //! # Example //! //! This is a larger example which implements [Dijkstra's algorithm][dijkstra] diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ringbuf.rs index 3665535e720..aa745ef39ee 100644 --- a/src/libcollections/ringbuf.rs +++ b/src/libcollections/ringbuf.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! A double-ended queue implemented as a circular buffer. -//! -//! `RingBuf` implements the trait `Deque`. It should be imported with -//! `use collections::Deque`. +//! This crate implements a double-ended queue with `O(1)` amortized inserts and removals from both +//! ends of the container. It also has `O(1)` indexing like a vector. The contained elements are +//! not required to be copyable, and the queue will be sendable if the contained type is sendable. +//! Its interface `Deque` is defined in `collections`. use core::prelude::*; diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 80a7c6d4bad..354edae473f 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -8,9 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! An ordered map and set implemented as self-balancing binary search -//! trees. The only requirement for the types is that the key implements -//! `Ord`. +//! Maps are collections of unique keys with corresponding values, and sets are +//! just unique keys without a corresponding value. The `Map` and `Set` traits in +//! `std::container` define the basic interface. +//! +//! This crate defines the `TreeMap` and `TreeSet` types. Their keys must implement `Ord`. +//! +//! `TreeMap`s are ordered. //! //! ## Example //! diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs index fa8bcf94de1..7d60d3a85e1 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie.rs @@ -8,8 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Ordered containers with unsigned integer keys, -//! implemented as radix tries (`TrieSet` and `TrieMap` types). +//! Maps are collections of unique keys with corresponding values, and sets are +//! just unique keys without a corresponding value. The `Map` and `Set` traits in +//! `std::container` define the basic interface. +//! +//! This crate defines `TrieMap` and `TrieSet`, which require `uint` keys. +//! +//! `TrieMap` is ordered. use core::prelude::*; diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a7005cf454d..34b3b11df00 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! An owned, growable vector. +//! A growable list type, written `Vec` but pronounced 'vector.' +//! +//! Vectors have `O(1)` indexing, push (to the end) and pop (from the end). use core::prelude::*; From 1b818020a062383c810170b18860caca553b5289 Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Mon, 8 Sep 2014 17:21:34 -0400 Subject: [PATCH 2/2] Remove container guide. This isn't really what guides are for, this information belongs in the module-level docs. Fixes #9314. --- src/doc/guide-container.md | 414 +------------------------------------ src/doc/index.md | 1 - src/libcore/iter.rs | 6 - 3 files changed, 3 insertions(+), 418 deletions(-) diff --git a/src/doc/guide-container.md b/src/doc/guide-container.md index 1733f4934c0..e9bda17f4bc 100644 --- a/src/doc/guide-container.md +++ b/src/doc/guide-container.md @@ -1,414 +1,6 @@ % The Rust Containers and Iterators Guide -# Containers +This guide has been removed, with no direct replacement. -The container traits are defined in the `std::container` module. - -## Unique vectors - -Vectors have `O(1)` indexing, push (to the end) and pop (from the end). Vectors -are the most common container in Rust, and are flexible enough to fit many use -cases. - -Vectors can also be sorted and used as efficient lookup tables with the -`bsearch()` method, if all the elements are inserted at one time and -deletions are unnecessary. - -## Maps and sets - -Maps are collections of unique keys with corresponding values, and sets are -just unique keys without a corresponding value. The `Map` and `Set` traits in -`std::container` define the basic interface. - -The standard library provides three owned map/set types: - -* `collections::HashMap` and `collections::HashSet`, requiring the keys to - implement `Eq` and `Hash` -* `collections::TrieMap` and `collections::TrieSet`, requiring the keys to be `uint` -* `collections::TreeMap` and `collections::TreeSet`, requiring the keys - to implement `Ord` - -These maps do not use managed pointers so they can be sent between tasks as -long as the key and value types are sendable. Neither the key or value type has -to be copyable. - -The `TrieMap` and `TreeMap` maps are ordered, while `HashMap` uses an arbitrary -order. - -Each `HashMap` instance has a random 128-bit key to use with a keyed hash, -making the order of a set of keys in a given hash table randomized. Rust -provides a [SipHash](https://131002.net/siphash/) implementation for any type -implementing the `Hash` trait. - -## Double-ended queues - -The `collections::ringbuf` module implements a double-ended queue with `O(1)` -amortized inserts and removals from both ends of the container. It also has -`O(1)` indexing like a vector. The contained elements are not required to be -copyable, and the queue will be sendable if the contained type is sendable. -Its interface `Deque` is defined in `collections`. - -The `extra::dlist` module implements a double-ended linked list, also -implementing the `Deque` trait, with `O(1)` removals and inserts at either end, -and `O(1)` concatenation. - -## Priority queues - -The `collections::priority_queue` module implements a queue ordered by a key. The -contained elements are not required to be copyable, and the queue will be -sendable if the contained type is sendable. - -Insertions have `O(log n)` time complexity and checking or popping the largest -element is `O(1)`. Converting a vector to a priority queue can be done -in-place, and has `O(n)` complexity. A priority queue can also be converted to -a sorted vector in-place, allowing it to be used for an `O(n log n)` in-place -heapsort. - -# Iterators - -## Iteration protocol - -The iteration protocol is defined by the `Iterator` trait in the -`std::iter` module. The minimal implementation of the trait is a `next` -method, yielding the next element from an iterator object: - -~~~ -/// An infinite stream of zeroes -struct ZeroStream; - -impl Iterator for ZeroStream { - fn next(&mut self) -> Option { - Some(0) - } -} -~~~ - -Reaching the end of the iterator is signalled by returning `None` instead of -`Some(item)`: - -~~~ -# fn main() {} -/// A stream of N zeroes -struct ZeroStream { - remaining: uint -} - -impl ZeroStream { - fn new(n: uint) -> ZeroStream { - ZeroStream { remaining: n } - } -} - -impl Iterator for ZeroStream { - fn next(&mut self) -> Option { - if self.remaining == 0 { - None - } else { - self.remaining -= 1; - Some(0) - } - } -} -~~~ - -In general, you cannot rely on the behavior of the `next()` method after it has -returned `None`. Some iterators may return `None` forever. Others may behave -differently. - -## Container iterators - -Containers implement iteration over the contained elements by returning an -iterator object. For example, for vector slices several iterators are available: - -* `iter()` for immutable references to the elements -* `mut_iter()` for mutable references to the elements -* `move_iter()` to move the elements out by-value - -A typical mutable container will implement at least `iter()`, `mut_iter()` and -`move_iter()`. If it maintains an order, the returned iterators will be -`DoubleEndedIterator`s, which are described below. - -### Freezing - -Unlike most other languages with external iterators, Rust has no *iterator -invalidation*. As long as an iterator is still in scope, the compiler will prevent -modification of the container through another handle. - -~~~ -let mut xs = [1i, 2, 3]; -{ - let _it = xs.iter(); - - // the vector is frozen for this scope, the compiler will statically - // prevent modification -} -// the vector becomes unfrozen again at the end of the scope -~~~ - -These semantics are due to most container iterators being implemented with `&` -and `&mut`. - -## Iterator adaptors - -The `Iterator` trait provides many common algorithms as default methods. For -example, the `fold` method will accumulate the items yielded by an `Iterator` -into a single value: - -~~~ -let xs = [1i, 9, 2, 3, 14, 12]; -let result = xs.iter().fold(0, |accumulator, item| accumulator - *item); -assert_eq!(result, -41); -~~~ - -Most adaptors return an adaptor object implementing the `Iterator` trait itself: - -~~~ -let xs = [1i, 9, 2, 3, 14, 12]; -let ys = [5i, 2, 1, 8]; -let sum = xs.iter().chain(ys.iter()).fold(0, |a, b| a + *b); -assert_eq!(sum, 57); -~~~ - -Some iterator adaptors may return `None` before exhausting the underlying -iterator. Additionally, if these iterator adaptors are called again after -returning `None`, they may call their underlying iterator again even if the -adaptor will continue to return `None` forever. This may not be desired if the -underlying iterator has side-effects. - -In order to provide a guarantee about behavior once `None` has been returned, an -iterator adaptor named `fuse()` is provided. This returns an iterator that will -never call its underlying iterator again once `None` has been returned: - -~~~ -let xs = [1i,2,3,4,5]; -let mut calls = 0i; - -{ - let it = xs.iter().scan((), |_, x| { - calls += 1; - if *x < 3 { Some(x) } else { None }}); - - // the iterator will only yield 1 and 2 before returning None - // If we were to call it 5 times, calls would end up as 5, despite - // only 2 values being yielded (and therefore 3 unique calls being - // made). The fuse() adaptor can fix this. - - let mut it = it.fuse(); - it.next(); - it.next(); - it.next(); - it.next(); - it.next(); -} - -assert_eq!(calls, 3); -~~~ - -## For loops - -The function `range` (or `range_inclusive`) allows to simply iterate through a given range: - -~~~ -for i in range(0i, 5) { - print!("{} ", i) // prints "0 1 2 3 4" -} - -for i in std::iter::range_inclusive(0i, 5) { // needs explicit import - print!("{} ", i) // prints "0 1 2 3 4 5" -} -~~~ - -The `for` keyword can be used as sugar for iterating through any iterator: - -~~~ -let xs = [2u, 3, 5, 7, 11, 13, 17]; - -// print out all the elements in the vector -for x in xs.iter() { - println!("{}", *x) -} - -// print out all but the first 3 elements in the vector -for x in xs.iter().skip(3) { - println!("{}", *x) -} -~~~ - -For loops are *often* used with a temporary iterator object, as above. They can -also advance the state of an iterator in a mutable location: - -~~~ -let xs = [1i, 2, 3, 4, 5]; -let ys = ["foo", "bar", "baz", "foobar"]; - -// create an iterator yielding tuples of elements from both vectors -let mut it = xs.iter().zip(ys.iter()); - -// print out the pairs of elements up to (&3, &"baz") -for (x, y) in it { - println!("{} {}", *x, *y); - - if *x == 3 { - break; - } -} - -// yield and print the last pair from the iterator -println!("last: {}", it.next()); - -// the iterator is now fully consumed -assert!(it.next().is_none()); -~~~ - -## Conversion - -Iterators offer generic conversion to containers with the `collect` adaptor: - -~~~ -let xs = [0i, 1, 1, 2, 3, 5, 8]; -let ys = xs.iter().rev().skip(1).map(|&x| x * 2).collect::>(); -assert_eq!(ys, vec![10, 6, 4, 2, 2, 0]); -~~~ - -The method requires a type hint for the container type, if the surrounding code -does not provide sufficient information. - -Containers can provide conversion from iterators through `collect` by -implementing the `FromIterator` trait. For example, the implementation for -vectors is as follows: - -~~~ {.ignore} -impl FromIterator for Vec { - fn from_iter>(mut iterator: I) -> Vec { - let (lower, _) = iterator.size_hint(); - let mut vector = Vec::with_capacity(lower); - for element in iterator { - vector.push(element); - } - vector - } -} -~~~ - -### Size hints - -The `Iterator` trait provides a `size_hint` default method, returning a lower -bound and optionally on upper bound on the length of the iterator: - -~~~ {.ignore} -fn size_hint(&self) -> (uint, Option) { (0, None) } -~~~ - -The vector implementation of `FromIterator` from above uses the lower bound -to pre-allocate enough space to hold the minimum number of elements the -iterator will yield. - -The default implementation is always correct, but it should be overridden if -the iterator can provide better information. - -The `ZeroStream` from earlier can provide an exact lower and upper bound: - -~~~ -# fn main() {} -/// A stream of N zeroes -struct ZeroStream { - remaining: uint -} - -impl ZeroStream { - fn new(n: uint) -> ZeroStream { - ZeroStream { remaining: n } - } - - fn size_hint(&self) -> (uint, Option) { - (self.remaining, Some(self.remaining)) - } -} - -impl Iterator for ZeroStream { - fn next(&mut self) -> Option { - if self.remaining == 0 { - None - } else { - self.remaining -= 1; - Some(0) - } - } -} -~~~ - -## Double-ended iterators - -The `DoubleEndedIterator` trait represents an iterator able to yield elements -from either end of a range. It inherits from the `Iterator` trait and extends -it with the `next_back` function. - -A `DoubleEndedIterator` can have its direction changed with the `rev` adaptor, -returning another `DoubleEndedIterator` with `next` and `next_back` exchanged. - -~~~ -let xs = [1i, 2, 3, 4, 5, 6]; -let mut it = xs.iter(); -println!("{}", it.next()); // prints `Some(1)` -println!("{}", it.next()); // prints `Some(2)` -println!("{}", it.next_back()); // prints `Some(6)` - -// prints `5`, `4` and `3` -for &x in it.rev() { - println!("{}", x) -} -~~~ - -The `chain`, `map`, `filter`, `filter_map` and `inspect` adaptors are -`DoubleEndedIterator` implementations if the underlying iterators are. - -~~~ -let xs = [1i, 2, 3, 4]; -let ys = [5i, 6, 7, 8]; -let mut it = xs.iter().chain(ys.iter()).map(|&x| x * 2); - -println!("{}", it.next()); // prints `Some(2)` - -// prints `16`, `14`, `12`, `10`, `8`, `6`, `4` -for x in it.rev() { - println!("{}", x); -} -~~~ - -The `reverse_` method is also available for any double-ended iterator yielding -mutable references. It can be used to reverse a container in-place. Note that -the trailing underscore is a workaround for issue #5898 and will be removed. - -~~~ -let mut ys = [1i, 2, 3, 4, 5]; -ys.mut_iter().reverse_(); -assert!(ys == [5i, 4, 3, 2, 1]); -~~~ - -## Random-access iterators - -The `RandomAccessIterator` trait represents an iterator offering random access -to the whole range. The `indexable` method retrieves the number of elements -accessible with the `idx` method. - -The `chain` adaptor is an implementation of `RandomAccessIterator` if the -underlying iterators are. - -~~~ -let xs = [1i, 2, 3, 4, 5]; -let ys = [7i, 9, 11]; -let mut it = xs.iter().chain(ys.iter()); -println!("{}", it.idx(0)); // prints `Some(1)` -println!("{}", it.idx(5)); // prints `Some(7)` -println!("{}", it.idx(7)); // prints `Some(11)` -println!("{}", it.idx(8)); // prints `None` - -// yield two elements from the beginning, and one from the end -it.next(); -it.next(); -it.next_back(); - -println!("{}", it.idx(0)); // prints `Some(3)` -println!("{}", it.idx(4)); // prints `Some(9)` -println!("{}", it.idx(6)); // prints `None` -~~~ +You may enjoy reading the [iterator](std/iter/index.html) and +[collections](std/collections/index.html) documentation. diff --git a/src/doc/index.md b/src/doc/index.md index 66f69d62e78..475c3b748db 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -57,7 +57,6 @@ a guide that can help you out: * [Strings](guide-strings.html) * [Pointers](guide-pointers.html) * [References and Lifetimes](guide-lifetimes.html) -* [Containers and Iterators](guide-container.html) * [Tasks and Communication](guide-tasks.html) * [Foreign Function Interface](guide-ffi.html) * [Writing Unsafe and Low-Level Code](guide-unsafe.html) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 89b2f9cc853..cf977a6ebe6 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -56,12 +56,6 @@ loop { This `for` loop syntax can be applied to any iterator over any type. -## Iteration protocol and more - -More detailed information about iterators can be found in the [container -guide](http://doc.rust-lang.org/guide-container.html) with -the rest of the rust manuals. - */ use clone::Clone;