Skip to content

Commit 811e045

Browse files
committed
auto merge of #7426 : thestinger/rust/zero-size-noncopyable, r=catamorphism
4885918 r=huonw 42a63fc r=thestinger 7ec5a08 r=catamorphism fb1e5f1 r=thestinger 659cd55 r=cmr
2 parents 887ae82 + 3fbea16 commit 811e045

File tree

14 files changed

+302
-195
lines changed

14 files changed

+302
-195
lines changed

RELEASES.txt

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ Version 0.7 (July 2013)
101101
dynamic borrowcheck failures for debugging.
102102
* rustdoc has a nicer stylesheet.
103103
* Various improvements to rustdoc.
104+
* Improvements to rustpkg (see the detailed release notes)
104105

105106
* Other
106107
* More and improved library documentation.

doc/rustpkg.md

+10
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,22 @@ When building a package that is in a `git` repository,
9595
When building a package that is not under version control,
9696
or that has no tags, `rustpkg` assumes the intended version is 0.1.
9797

98+
# Dependencies
99+
100+
rustpkg infers dependencies from `extern mod` directives.
101+
Thus, there should be no need to pass a `-L` flag to rustpkg to tell it where to find a library.
102+
(In the future, it will also be possible to write an `extern mod` directive referring to a remote package.)
103+
98104
# Custom build scripts
99105

100106
A file called `pkg.rs` at the root level in a workspace is called a *package script*.
101107
If a package script exists, rustpkg executes it to build the package
102108
rather than inferring crates as described previously.
103109

110+
Inside `pkg.rs`, it's possible to call back into rustpkg to finish up the build.
111+
`rustpkg::api` contains functions to build, install, or clean libraries and executables
112+
in the way rustpkg normally would without custom build logic.
113+
104114
# Command reference
105115

106116
## build

doc/tutorial-container.md

+207
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
% Containers and iterators
2+
3+
# Containers
4+
5+
The container traits are defined in the `std::container` module.
6+
7+
## Unique and managed vectors
8+
9+
Vectors have `O(1)` indexing and removal from the end, along with `O(1)`
10+
amortized insertion. Vectors are the most common container in Rust, and are
11+
flexible enough to fit many use cases.
12+
13+
Vectors can also be sorted and used as efficient lookup tables with the
14+
`std::vec::bsearch` function, if all the elements are inserted at one time and
15+
deletions are unnecessary.
16+
17+
## Maps and sets
18+
19+
Maps are collections of unique keys with corresponding values, and sets are
20+
just unique keys without a corresponding value. The `Map` and `Set` traits in
21+
`std::container` define the basic interface.
22+
23+
The standard library provides three owned map/set types:
24+
25+
* `std::hashmap::HashMap` and `std::hashmap::HashSet`, requiring the keys to
26+
implement `Eq` and `Hash`
27+
* `std::trie::TrieMap` and `std::trie::TrieSet`, requiring the keys to be `uint`
28+
* `extra::treemap::TreeMap` and `extra::treemap::TreeSet`, requiring the keys
29+
to implement `TotalOrd`
30+
31+
These maps do not use managed pointers so they can be sent between tasks as
32+
long as the key and value types are sendable. Neither the key or value type has
33+
to be copyable.
34+
35+
The `TrieMap` and `TreeMap` maps are ordered, while `HashMap` uses an arbitrary
36+
order.
37+
38+
Each `HashMap` instance has a random 128-bit key to use with a keyed hash,
39+
making the order of a set of keys in a given hash table randomized. Rust
40+
provides a [SipHash](https://131002.net/siphash/) implementation for any type
41+
implementing the `IterBytes` trait.
42+
43+
## Double-ended queues
44+
45+
The `extra::deque` module implements a double-ended queue with `O(1)` amortized
46+
inserts and removals from both ends of the container. It also has `O(1)`
47+
indexing like a vector. The contained elements are not required to be copyable,
48+
and the queue will be sendable if the contained type is sendable.
49+
50+
## Priority queues
51+
52+
The `extra::priority_queue` module implements a queue ordered by a key. The
53+
contained elements are not required to be copyable, and the queue will be
54+
sendable if the contained type is sendable.
55+
56+
Insertions have `O(log n)` time complexity and checking or popping the largest
57+
element is `O(1)`. Converting a vector to a priority queue can be done
58+
in-place, and has `O(n)` complexity. A priority queue can also be converted to
59+
a sorted vector in-place, allowing it to be used for an `O(n log n)` in-place
60+
heapsort.
61+
62+
# Iterators
63+
64+
## Iteration protocol
65+
66+
The iteration protocol is defined by the `Iterator` trait in the
67+
`std::iterator` module. The minimal implementation of the trait is a `next`
68+
method, yielding the next element from an iterator object:
69+
70+
~~~
71+
/// An infinite stream of zeroes
72+
struct ZeroStream;
73+
74+
impl Iterator<int> for ZeroStream {
75+
fn next(&mut self) -> Option<int> {
76+
Some(0)
77+
}
78+
}
79+
~~~~
80+
81+
Reaching the end of the iterator is signalled by returning `None` instead of
82+
`Some(item)`:
83+
84+
~~~
85+
/// A stream of N zeroes
86+
struct ZeroStream {
87+
priv remaining: uint
88+
}
89+
90+
impl ZeroStream {
91+
fn new(n: uint) -> ZeroStream {
92+
ZeroStream { remaining: n }
93+
}
94+
}
95+
96+
impl Iterator<int> for ZeroStream {
97+
fn next(&mut self) -> Option<int> {
98+
if self.remaining == 0 {
99+
None
100+
} else {
101+
self.remaining -= 1;
102+
Some(0)
103+
}
104+
}
105+
}
106+
~~~
107+
108+
## Container iterators
109+
110+
Containers implement iteration over the contained elements by returning an
111+
iterator object. For example, vectors have four iterators available:
112+
113+
* `vector.iter()`, for immutable references to the elements
114+
* `vector.mut_iter()`, for mutable references to the elements
115+
* `vector.rev_iter()`, for immutable references to the elements in reverse order
116+
* `vector.mut_rev_iter()`, for mutable references to the elements in reverse order
117+
118+
### Freezing
119+
120+
Unlike most other languages with external iterators, Rust has no *iterator
121+
invalidation*. As long an iterator is still in scope, the compiler will prevent
122+
modification of the container through another handle.
123+
124+
~~~
125+
let mut xs = [1, 2, 3];
126+
{
127+
let _it = xs.iter();
128+
129+
// the vector is frozen for this scope, the compiler will statically
130+
// prevent modification
131+
}
132+
// the vector becomes unfrozen again at the end of the scope
133+
~~~
134+
135+
These semantics are due to most container iterators being implemented with `&`
136+
and `&mut`.
137+
138+
## Iterator adaptors
139+
140+
The `IteratorUtil` trait implements common algorithms as methods extending
141+
every `Iterator` implementation. For example, the `fold` method will accumulate
142+
the items yielded by an `Iterator` into a single value:
143+
144+
~~~
145+
let xs = [1, 9, 2, 3, 14, 12];
146+
let result = xs.iter().fold(0, |accumulator, item| accumulator - *item);
147+
assert_eq!(result, -41);
148+
~~~
149+
150+
Some adaptors return an adaptor object implementing the `Iterator` trait itself:
151+
152+
~~~
153+
let xs = [1, 9, 2, 3, 14, 12];
154+
let ys = [5, 2, 1, 8];
155+
let sum = xs.iter().chain_(ys.iter()).fold(0, |a, b| a + *b);
156+
assert_eq!(sum, 57);
157+
~~~
158+
159+
Note that some adaptors like the `chain_` method above use a trailing
160+
underscore to work around an issue with method resolve. The underscores will be
161+
dropped when they become unnecessary.
162+
163+
## For loops
164+
165+
The `for` loop syntax is currently in transition, and will switch from the old
166+
closure-based iteration protocol to iterator objects. For now, the `advance`
167+
adaptor is required as a compatibility shim to use iterators with for loops.
168+
169+
~~~
170+
let xs = [2, 3, 5, 7, 11, 13, 17];
171+
172+
// print out all the elements in the vector
173+
for xs.iter().advance |x| {
174+
println(x.to_str())
175+
}
176+
177+
// print out all but the first 3 elements in the vector
178+
for xs.iter().skip(3).advance |x| {
179+
println(x.to_str())
180+
}
181+
~~~
182+
183+
For loops are *often* used with a temporary iterator object, as above. They can
184+
also advance the state of an iterator in a mutable location:
185+
186+
~~~
187+
let xs = [1, 2, 3, 4, 5];
188+
let ys = ["foo", "bar", "baz", "foobar"];
189+
190+
// create an iterator yielding tuples of elements from both vectors
191+
let mut it = xs.iter().zip(ys.iter());
192+
193+
// print out the pairs of elements up to (&3, &"baz")
194+
for it.advance |(x, y)| {
195+
println(fmt!("%d %s", *x, *y));
196+
197+
if *x == 3 {
198+
break;
199+
}
200+
}
201+
202+
// yield and print the last pair from the iterator
203+
println(fmt!("last: %?", it.next()));
204+
205+
// the iterator is now fully consumed
206+
assert!(it.next().is_none());
207+
~~~

doc/tutorial.md

+1-126
Original file line numberDiff line numberDiff line change
@@ -1607,132 +1607,6 @@ do spawn {
16071607
If you want to see the output of `debug!` statements, you will need to turn on `debug!` logging.
16081608
To enable `debug!` logging, set the RUST_LOG environment variable to the name of your crate, which, for a file named `foo.rs`, will be `foo` (e.g., with bash, `export RUST_LOG=foo`).
16091609

1610-
## For loops
1611-
1612-
> ***Note:*** The closure-based protocol used `for` loop is on the way out. The `for` loop will
1613-
> use iterator objects in the future instead.
1614-
1615-
The most common way to express iteration in Rust is with a `for`
1616-
loop. Like `do`, `for` is a nice syntax for describing control flow
1617-
with closures. Additionally, within a `for` loop, `break`, `loop`,
1618-
and `return` work just as they do with `while` and `loop`.
1619-
1620-
Consider again our `each` function, this time improved to return
1621-
immediately when the iteratee returns `false`:
1622-
1623-
~~~~
1624-
fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
1625-
let mut n = 0;
1626-
while n < v.len() {
1627-
if !op(&v[n]) {
1628-
return false;
1629-
}
1630-
n += 1;
1631-
}
1632-
return true;
1633-
}
1634-
~~~~
1635-
1636-
And using this function to iterate over a vector:
1637-
1638-
~~~~
1639-
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
1640-
# let mut n = 0;
1641-
# while n < v.len() {
1642-
# if !op(&v[n]) {
1643-
# return false;
1644-
# }
1645-
# n += 1;
1646-
# }
1647-
# return true;
1648-
# }
1649-
each([2, 4, 8, 5, 16], |n| {
1650-
if *n % 2 != 0 {
1651-
println("found odd number!");
1652-
false
1653-
} else { true }
1654-
});
1655-
~~~~
1656-
1657-
With `for`, functions like `each` can be treated more
1658-
like built-in looping structures. When calling `each`
1659-
in a `for` loop, instead of returning `false` to break
1660-
out of the loop, you just write `break`. To skip ahead
1661-
to the next iteration, write `loop`.
1662-
1663-
~~~~
1664-
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
1665-
# let mut n = 0;
1666-
# while n < v.len() {
1667-
# if !op(&v[n]) {
1668-
# return false;
1669-
# }
1670-
# n += 1;
1671-
# }
1672-
# return true;
1673-
# }
1674-
for each([2, 4, 8, 5, 16]) |n| {
1675-
if *n % 2 != 0 {
1676-
println("found odd number!");
1677-
break;
1678-
}
1679-
}
1680-
~~~~
1681-
1682-
As an added bonus, you can use the `return` keyword, which is not
1683-
normally allowed in closures, in a block that appears as the body of a
1684-
`for` loop: the meaning of `return` in such a block is to return from
1685-
the enclosing function, not just the loop body.
1686-
1687-
~~~~
1688-
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
1689-
# let mut n = 0;
1690-
# while n < v.len() {
1691-
# if !op(&v[n]) {
1692-
# return false;
1693-
# }
1694-
# n += 1;
1695-
# }
1696-
# return true;
1697-
# }
1698-
fn contains(v: &[int], elt: int) -> bool {
1699-
for each(v) |x| {
1700-
if (*x == elt) { return true; }
1701-
}
1702-
false
1703-
}
1704-
~~~~
1705-
1706-
Notice that, because `each` passes each value by borrowed pointer,
1707-
the iteratee needs to dereference it before using it.
1708-
In these situations it can be convenient to lean on Rust's
1709-
argument patterns to bind `x` to the actual value, not the pointer.
1710-
1711-
~~~~
1712-
# fn each(v: &[int], op: &fn(v: &int) -> bool) -> bool {
1713-
# let mut n = 0;
1714-
# while n < v.len() {
1715-
# if !op(&v[n]) {
1716-
# return false;
1717-
# }
1718-
# n += 1;
1719-
# }
1720-
# return true;
1721-
# }
1722-
# fn contains(v: &[int], elt: int) -> bool {
1723-
for each(v) |&x| {
1724-
if (x == elt) { return true; }
1725-
}
1726-
# false
1727-
# }
1728-
~~~~
1729-
1730-
`for` syntax only works with stack closures.
1731-
1732-
> ***Note:*** This is, essentially, a special loop protocol:
1733-
> the keywords `break`, `loop`, and `return` work, in varying degree,
1734-
> with `while`, `loop`, `do`, and `for` constructs.
1735-
17361610
# Methods
17371611

17381612
Methods are like functions except that they always begin with a special argument,
@@ -2653,6 +2527,7 @@ tutorials on individual topics.
26532527
* [Tasks and communication][tasks]
26542528
* [Macros][macros]
26552529
* [The foreign function interface][ffi]
2530+
* [Containers and iterators](tutorial-container.html)
26562531

26572532
There is further documentation on the [wiki].
26582533

0 commit comments

Comments
 (0)