Skip to content

Commit 03405f8

Browse files
committed
Merge pull request #12 from liigo/master
update/add the latest official docs/rfcs/blogs
2 parents 3da3f98 + 88b5011 commit 03405f8

18 files changed

+1787
-165
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
Cargo: Rust's community crate host
2+
==================================
3+
Nov 20, 2014 • Alex Crichton
4+
5+
Today it is my pleasure to announce that [crates.io](https://crates.io) is online and ready for action. The site is a central location to discover/download Rust crates, and Cargo is ready to start publishing to it today. For the next few months, we are asking that intrepid early adopters [help us](http://doc.crates.io/crates-io.html) get the registry battle-tested.
6+
7+
Until Rust itself is stable early next year, registry dependencies will need to be updated often. Production users may want to continue using git dependencies until then.
8+
9+
# What is Cargo?
10+
Cargo is a package manager [for Rust](http://www.rust-lang.org), [in Rust](https://github.com/rust-lang/cargo). Managing dependencies is a fundamentally difficult problem, but fortunately over the last decade there’s been a lot of progress in the design of package managers. Designed by Carl Lerche and Yehuda Katz, Cargo follows the tradition of successes like [Bundler](http://bundler.io) and [NPM](https://www.npmjs.org):
11+
12+
- Cargo leverages crates.io to foster a thriving community of crates that can easily interoperate with one another and last for years to come.
13+
14+
- Cargo releases developers from the worry of managing dependencies and ensures that all collaborators are building the same code.
15+
16+
- Cargo lets your dependencies say how they should be built, and manages the entire build process for you.
17+
18+
# A Community on Cargo
19+
20+
To get a feel for how Cargo achieves its goals, let’s take a look at some of its core mechanics.
21+
22+
## Declaring Dependencies
23+
24+
Cargo makes depending on third-party code as easy as depending on the standard library. When using Cargo, each crate will have an associated [manifest](http://doc.crates.io/manifest.html) to describe itself and its dependencies. Adding a new dependency is now as simple as adding one line to the manifest, and this ease has allowed Cargo in just a few short months to enable a large and growing network of Rust projects and libraries which were simply infeasible before.
25+
26+
Cargo alone, however, is not quite the entire solution. Discovering dependencies is still difficult, and ensuring that these dependencies are available for years to come is also not guaranteed.
27+
28+
## crates.io
29+
30+
To pair with Cargo, the central crates.io site serves as a single location for publishing and discovering libraries. This repository serves as permanent storage for releases of crates over time to ensure that projects can always build with the exact same versions years later. Up until now, users of Cargo have largely just downloaded dependencies directly from the source GitHub repository, but the primary source will now be shifting to crates.io.
31+
32+
Other programming language communities have been quite successful with this form of central repository. For example [rubygems.org](http://rubygems.org) is your one-stop-shop for [Bundler](http://bundler.io) dependencies and [npmjs.org](https://www.npmjs.org) has had over 600 million downloads in just this month alone! We intend for crates.io to serve a similar role for Rust as a critical piece of infrastructure for [Rust’s long-term stability story at 1.0](http://blog.rust-lang.org/2014/10/30/Stability.html).
33+
34+
# Versioning and Reproducible Builds
35+
36+
Over the past few years, the concept of [Semantic Versioning](http://semver.org) has gained traction as a way for library developers to easily and clearly communicate with users when they make breaking changes. The core idea of semantic versioning is simple: each new release is categorized as a minor or major release, and only major releases can introduce breakage. Cargo allows you to specify version ranges for your dependencies, with the default meaning of “compatible with”.
37+
38+
When specifying a version range, applications often end up requesting multiple versions of a single crate, and Cargo solves this by selecting the highest version of each major version (“stable code”) requested. This highly encourages using stable distributions while still allowing duplicates of unstable code (pre-1.0 and git for example).
39+
40+
Once the set of dependencies and their versions have been calculated, Cargo generates a [Cargo.lock](http://doc.crates.io/guide.html#cargo.toml-vs-cargo.lock) to encode this information. This “lock file” is then distributed to collaborators of applications to ensure that the crates being built remain the same from one build to the next, across times, machines, and environments.
41+
42+
# Building Code
43+
44+
Up to this point we’ve seen how Cargo facilitates discovery and reuse of community projects while managing what versions to use. Now Cargo just has to deal with the problem of actually compiling all this code!
45+
46+
With a deep understanding of the Rust code that it is building, Cargo is able to provide some nice standard features as well as some Rust-specific features:
47+
48+
- By default, Cargo builds as many crates in parallel as possible. This not only applies to upstream dependencies being built in parallel, but also items for the local crate such as test suites, binaries, and unit tests.
49+
50+
- Cargo supports unit testing out of the box both for crates themselves and in the form of integration tests. This even includes example programs to ensure they don’t bitrot.
51+
52+
- Cargo generates documentation for all crates in a dependency graph, and it can even run [Rust’s documentation tests](http://doc.rust-lang.org/rustdoc.html#testing-the-documentation) to ensure examples in documentation stay up to date.
53+
54+
- Cargo can run a [build script](http://doc.crates.io/build-script.html) before any crate is compiled to perform tasks such as code generation, compiling native dependencies, or detecting native dependencies on the local system.
55+
56+
- Cargo supports cross compilation out of the box. Cross compiling is done by simply specifying a `--target` options and Cargo will manage tasks such as compiling plugins and other build dependencies for the right platform.
57+
58+
# What else is in store?
59+
60+
The launch of crates.io is a key step in moving the Cargo ecosystem forward, but the story does not end here. Usage of crates.io is architected assuming a stable compiler, which should be [coming soon](http://blog.rust-lang.org/2014/09/15/Rust-1.0.html)! There are also a number of extensions to crates.io such as a hosted documentation service or a CI build infrastructure hook which could be built out using the crates.io APIs.
61+
62+
This is just the beginning for crates.io, and I’m excited to start finding all Rust crates from one location. I can’t wait to see what the registry looks like at 1.0, and I can only fathom what it will look like after 1.0!

rust-zh-translating/source/docs/complement-design-faq.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ code should need to run is a stack.
9595
`match` being exhaustive has some useful properties. First, if every
9696
possibility is covered by the `match`, adding further variants to the `enum`
9797
in the future will prompt a compilation failure, rather than runtime panic.
98-
Second, it makes cost explicit. In general, only safe way to have a
98+
Second, it makes cost explicit. In general, the only safe way to have a
9999
non-exhaustive match would be to panic the task if nothing is matched, though
100100
it could fall through if the type of the `match` expression is `()`. This sort
101101
of hidden cost and special casing is against the language's philosophy. It's
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
% Error Handling in Rust
2+
3+
> The best-laid plans of mice and men
4+
> Often go awry
5+
>
6+
> "Tae a Moose", Robert Burns
7+
8+
Sometimes, things just go wrong. It's important to have a plan for when the
9+
inevitable happens. Rust has rich support for handling errors that may (let's
10+
be honest: will) occur in your programs.
11+
12+
There are two main kinds of errors that can occur in your programs: failures,
13+
and panics. Let's talk about the difference between the two, and then discuss
14+
how to handle each. Then, we'll discuss upgrading failures to panics.
15+
16+
# Failure vs. Panic
17+
18+
Rust uses two terms to differentiate between two forms of error: failure, and
19+
panic. A **failure** is an error that can be recovered from in some way. A
20+
**panic** is an error that cannot be recovered from.
21+
22+
What do we mean by 'recover'? Well, in most cases, the possibility of an error
23+
is expected. For example, consider the `from_str` function:
24+
25+
```{rust,ignore}
26+
from_str("5");
27+
```
28+
29+
This function takes a string argument and converts it into another type. But
30+
because it's a string, you can't be sure that the conversion actually works.
31+
For example, what should this convert to?
32+
33+
```{rust,ignore}
34+
from_str("hello5world");
35+
```
36+
37+
This won't work. So we know that this function will only work properly for some
38+
inputs. It's expected behavior. We call this kind of error 'failure.'
39+
40+
On the other hand, sometimes, there are errors that are unexpected, or which
41+
we cannot recover from. A classic example is an `assert!`:
42+
43+
```{rust,ignore}
44+
assert!(x == 5);
45+
```
46+
47+
We use `assert!` to declare that something is true. If it's not true, something
48+
is very wrong. Wrong enough that we can't continue with things in the current
49+
state. Another example is using the `unreachable!()` macro
50+
51+
```{rust,ignore}
52+
enum Event {
53+
NewRelease,
54+
}
55+
56+
fn probability(_: &Event) -> f64 {
57+
// real implementation would be more complex, of course
58+
0.95
59+
}
60+
61+
fn descriptive_probability(event: Event) -> &'static str {
62+
match probability(&event) {
63+
1.00 => "certain",
64+
0.00 => "impossible",
65+
0.00 ... 0.25 => "very unlikely",
66+
0.25 ... 0.50 => "unlikely",
67+
0.50 ... 0.75 => "likely",
68+
0.75 ... 1.00 => "very likely",
69+
}
70+
}
71+
72+
fn main() {
73+
std::io::println(descriptive_probability(NewRelease));
74+
}
75+
```
76+
77+
This will give us an error:
78+
79+
```{notrust,ignore}
80+
error: non-exhaustive patterns: `_` not covered [E0004]
81+
```
82+
83+
While we know that we've covered all possible cases, Rust can't tell. It
84+
doesn't know that probability is between 0.0 and 1.0. So we add another case:
85+
86+
```rust
87+
use Event::NewRelease;
88+
89+
enum Event {
90+
NewRelease,
91+
}
92+
93+
fn probability(_: &Event) -> f64 {
94+
// real implementation would be more complex, of course
95+
0.95
96+
}
97+
98+
fn descriptive_probability(event: Event) -> &'static str {
99+
match probability(&event) {
100+
1.00 => "certain",
101+
0.00 => "impossible",
102+
0.00 ... 0.25 => "very unlikely",
103+
0.25 ... 0.50 => "unlikely",
104+
0.50 ... 0.75 => "likely",
105+
0.75 ... 1.00 => "very likely",
106+
_ => unreachable!()
107+
}
108+
}
109+
110+
fn main() {
111+
println!("{}", descriptive_probability(NewRelease));
112+
}
113+
```
114+
115+
We shouldn't ever hit the `_` case, so we use the `unreachable!()` macro to
116+
indicate this. `unreachable!()` gives a different kind of error than `Result`.
117+
Rust calls these sorts of errors 'panics.'
118+
119+
# Handling errors with `Option` and `Result`
120+
121+
The simplest way to indicate that a function may fail is to use the `Option<T>`
122+
type. Remember our `from_str()` example? Here's its type signature:
123+
124+
```{rust,ignore}
125+
pub fn from_str<A: FromStr>(s: &str) -> Option<A>
126+
```
127+
128+
`from_str()` returns an `Option<A>`. If the conversion succeeds, it will return
129+
`Some(value)`, and if it fails, it will return `None`.
130+
131+
This is appropriate for the simplest of cases, but doesn't give us a lot of
132+
information in the failure case. What if we wanted to know _why_ the conversion
133+
failed? For this, we can use the `Result<T, E>` type. It looks like this:
134+
135+
```rust
136+
enum Result<T, E> {
137+
Ok(T),
138+
Err(E)
139+
}
140+
```
141+
142+
This enum is provided by Rust itself, so you don't need to define it to use it
143+
in your code. The `Ok(T)` variant represents a success, and the `Err(E)` variant
144+
represents a failure. Returning a `Result` instead of an `Option` is recommended
145+
for all but the most trivial of situations.
146+
147+
Here's an example of using `Result`:
148+
149+
```rust
150+
#[deriving(Show)]
151+
enum Version { Version1, Version2 }
152+
153+
#[deriving(Show)]
154+
enum ParseError { InvalidHeaderLength, InvalidVersion }
155+
156+
fn parse_version(header: &[u8]) -> Result<Version, ParseError> {
157+
if header.len() < 1 {
158+
return Err(ParseError::InvalidHeaderLength);
159+
}
160+
match header[0] {
161+
1 => Ok(Version::Version1),
162+
2 => Ok(Version::Version2),
163+
_ => Err(ParseError::InvalidVersion)
164+
}
165+
}
166+
167+
let version = parse_version(&[1, 2, 3, 4]);
168+
match version {
169+
Ok(v) => {
170+
println!("working with version: {}", v);
171+
}
172+
Err(e) => {
173+
println!("error parsing header: {}", e);
174+
}
175+
}
176+
```
177+
178+
This function makes use of an enum, `ParseError`, to enumerate the various
179+
errors that can occur.
180+
181+
# Non-recoverable errors with `panic!`
182+
183+
In the case of an error that is unexpected and not recoverable, the `panic!`
184+
macro will induce a panic. This will crash the current task, and give an error:
185+
186+
```{rust,ignore}
187+
panic!("boom");
188+
```
189+
190+
gives
191+
192+
```{notrust,ignore}
193+
task '<main>' panicked at 'boom', hello.rs:2
194+
```
195+
196+
when you run it.
197+
198+
Because these kinds of situations are relatively rare, use panics sparingly.
199+
200+
# Upgrading failures to panics
201+
202+
In certain circumstances, even though a function may fail, we may want to treat
203+
it as a panic instead. For example, `io::stdin().read_line()` returns an
204+
`IoResult<String>`, a form of `Result`, when there is an error reading the
205+
line. This allows us to handle and possibly recover from this sort of error.
206+
207+
If we don't want to handle this error, and would rather just abort the program,
208+
we can use the `unwrap()` method:
209+
210+
```{rust,ignore}
211+
io::stdin().read_line().unwrap();
212+
```
213+
214+
`unwrap()` will `panic!` if the `Option` is `None`. This basically says "Give
215+
me the value, and if something goes wrong, just crash." This is less reliable
216+
than matching the error and attempting to recover, but is also significantly
217+
shorter. Sometimes, just crashing is appropriate.
218+
219+
There's another way of doing this that's a bit nicer than `unwrap()`:
220+
221+
```{rust,ignore}
222+
let input = io::stdin().read_line()
223+
.ok()
224+
.expect("Failed to read line");
225+
```
226+
`ok()` converts the `IoResult` into an `Option`, and `expect()` does the same
227+
thing as `unwrap()`, but takes a message. This message is passed along to the
228+
underlying `panic!`, providing a better error message if the code errors.

rust-zh-translating/source/docs/guide-lifetimes.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ expensive. So we'd like to define a function that takes the points just as
5151
a reference.
5252

5353
~~~
54+
# use std::num::Float;
5455
# struct Point {x: f64, y: f64}
5556
# fn sqrt(f: f64) -> f64 { 0.0 }
5657
fn compute_distance(p1: &Point, p2: &Point) -> f64 {
@@ -307,8 +308,8 @@ copying.
307308
# }
308309
fn compute_area(shape: &Shape) -> f64 {
309310
match *shape {
310-
Circle(_, radius) => std::f64::consts::PI * radius * radius,
311-
Rectangle(_, ref size) => size.w * size.h
311+
Shape::Circle(_, radius) => std::f64::consts::PI * radius * radius,
312+
Shape::Rectangle(_, ref size) => size.w * size.h
312313
}
313314
}
314315
~~~
@@ -477,14 +478,14 @@ example:
477478
# a: &'r T, b: &'r T) -> &'r T {
478479
# if compute_area(shape) > threshold {a} else {b}
479480
# }
480-
// -+ r
481-
fn select_based_on_unit_circle<'r, T>( // |-+ B
482-
threshold: f64, a: &'r T, b: &'r T) -> &'r T { // | |
483-
// | |
484-
let shape = Circle(Point {x: 0., y: 0.}, 1.); // | |
485-
select(&shape, threshold, a, b) // | |
486-
} // |-+
487-
// -+
481+
// -+ r
482+
fn select_based_on_unit_circle<'r, T>( // |-+ B
483+
threshold: f64, a: &'r T, b: &'r T) -> &'r T { // | |
484+
// | |
485+
let shape = Shape::Circle(Point {x: 0., y: 0.}, 1.); // | |
486+
select(&shape, threshold, a, b) // | |
487+
} // |-+
488+
// -+
488489
~~~
489490

490491
In this call to `select()`, the lifetime of the first parameter shape

0 commit comments

Comments
 (0)