let y = Missing;
match x {
- Value(n) => println!("x is {:d}", n),
+ Value(n) => println!("x is {}", n),
Missing => println!("x is missing!"),
}
match y {
- Value(n) => println!("y is {:d}", n),
+ Value(n) => println!("y is {}", n),
Missing => println!("y is missing!"),
}
}
```{rust}
for x in range(0i, 10i) {
- println!("{:d}", x);
+ println!("{}", x);
}
```
for x in range(0i, 10i) {
if x % 2 == 0 { continue; }
- println!("{:d}", x);
+ println!("{}", x);
}
```
let y = Missing;
match x {
- Value(n) => println!("x is {:d}", n),
+ Value(n) => println!("x is {}", n),
Missing => println!("x is missing!"),
}
match y {
- Value(n) => println!("y is {:d}", n),
+ Value(n) => println!("y is {}", n),
Missing => println!("y is missing!"),
}
}
```{rust}
fn main() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
```
```
fn main() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
mod hello {
fn print_hello() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
}
```
mod hello {
fn print_hello() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
}
```
mod hello {
pub fn print_hello() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
}
```
```{notrust,ignore}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
-/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: code is never used: `main`, #[warn(dead_code)] on by default
+/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: function is never used: `main`, #[warn(dead_code)] on by default
/home/you/projects/testing/src/main.rs:1 fn main() {
-/home/you/projects/testing/src/main.rs:2 println!("Hello, world");
+/home/you/projects/testing/src/main.rs:2 println!("Hello, world!")
/home/you/projects/testing/src/main.rs:3 }
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-
+ Running target/lib-654ce120f310a3a5
running 1 test
test foo ... FAILED
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
-task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:242
+task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
```
Lots of output! Let's break this down:
`tests`, as well as the tests you put inside of your crate.
```{notrust,ignore}
-/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: code is never used: `main`, #[warn(dead_code)] on by default
+/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: function is never used: `main`, #[warn(dead_code)] on by default
/home/you/projects/testing/src/main.rs:1 fn main() {
-/home/you/projects/testing/src/main.rs:2 println!("Hello, world");
+/home/you/projects/testing/src/main.rs:2 println!("Hello, world!")
/home/you/projects/testing/src/main.rs:3 }
```
output.
```{notrust,ignore}
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-```
+ Running target/lib-654ce120f310a3a5
-Wait a minute, zero tests? Didn't we define one? Yup. This output is from
-attempting to run the tests in our crate, of which we don't have any.
-You'll note that Rust reports on several kinds of tests: passed, failed,
-ignored, and measured. The 'measured' tests refer to benchmark tests, which
-we'll cover soon enough!
-
-```{notrust,ignore}
running 1 test
test foo ... FAILED
```
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
-task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:242
+task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
```
After all the tests run, Rust will show us any output from our failed tests.
```{notrust,ignore}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
-/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: code is never used: `main`, #[warn(dead_code)] on by default
-/home/you/projects/testing/src/main.rs:1 fn main() {
-/home/you/projects/testing/src/main.rs:2 println!("Hello, world");
-/home/you/projects/testing/src/main.rs:3 }
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-
+ Running target/lib-654ce120f310a3a5
running 1 test
test foo ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
-Nice! Our test passes, as we expected. Let's get rid of that warning for our `main`
-function. Change your `src/main.rs` to look like this:
+Nice! Our test passes, as we expected. Note how we didn't get the
+`main` warning this time? This is because `src/main.rs` didn't
+need recompiling, but we'll get that warning again if we
+change (and recompile) that file. Let's get rid of that
+warning; change your `src/main.rs` to look like this:
```{rust}
#[cfg(not(test))]
fn main() {
- println!("Hello, world");
+ println!("Hello, world!")
}
```
include `main` when it's _not_ true. So we use `not` to negate things:
`cfg(not(test))` will only compile our code when the `cfg(test)` is false.
-With this attribute, we won't get the warning:
+With this attribute we won't get the warning (even
+though `src/main.rs` gets recompiled this time):
```{notrust,ignore}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-
+ Running target/lib-654ce120f310a3a5
running 1 test
test foo ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
Nice. Okay, let's write a real test now. Change your `tests/lib.rs`
#[cfg(not(test))]
fn main() {
- println!("Hello, world");
+ println!("Hello, world!")
}
```
```{ignore,notrust}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
+ Running target/lib-654ce120f310a3a5
+
+running 1 test
+test math_checks_out ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+ Running target/testing-8a94b31f7fd2e8fe
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+ Doc-tests testing
-running 1 test
-test math_checks_out ... ok
+running 0 tests
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
Great! One test passed. We've got an integration test showing that our public
```{ignore,notrust}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
+ Running target/lib-654ce120f310a3a5
+
+running 1 test
+test math_checks_out ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+ Running target/testing-8a94b31f7fd2e8fe
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+ Doc-tests testing
-running 1 test
-test math_checks_out ... ok
+running 0 tests
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
If we tried to write a test for these two new functions, it wouldn't
```{ignore,notrust}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
+ Running target/lib-654ce120f310a3a5
+
+running 1 test
+test math_checks_out ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-8a94b31f7fd2e8fe
running 2 tests
test test::test_times_four ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
+ Doc-tests testing
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-
-
-running 1 test
-test math_checks_out ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
```
Cool! We now have two tests of our internal functions. You'll note that there
## Boxes
-All of our references so far have been to variables we've created on the stack.
-In Rust, the simplest way to allocate heap variables is using a *box*. To
-create a box, use the `box` keyword:
+Most of the types we've seen so far have a fixed size or number of components.
+The compiler needs this fact to lay out values in memory. However, some data
+structures, such as a linked list, do not have a fixed size. You might think to
+implement a linked list with an enum that's either a `Node` or the end of the
+list (`Nil`), like this:
+
+```{rust,ignore}
+enum List { // error: illegal recursive enum type
+ Node(u32, List),
+ Nil
+}
+```
+
+But the compiler complains that the type is recursive, that is, it could be
+arbitrarily large. To remedy this, Rust provides a fixed-size container called
+a **box** that can hold any type. You can box up any value with the `box`
+keyword. Our boxed List gets the type `Box<List>` (more on the notation when we
+get to generics):
```{rust}
-let x = box 5i;
+enum List {
+ Node(u32, Box<List>),
+ Nil
+}
+
+fn main() {
+ let list = Node(0, box Node(1, box Nil));
+}
```
-This allocates an integer `5` on the heap, and creates a binding `x` that
-refers to it. The great thing about boxed pointers is that we don't have to
-manually free this allocation! If we write
+A box dynamically allocates memory to hold its contents. The great thing about
+Rust is that that memory is *automatically*, *efficiently*, and *predictably*
+deallocated when you're done with the box.
+
+A box is a pointer type, and you access what's inside using the `*` operator,
+just like regular references. This (rather silly) example dynamically allocates
+an integer `5` and makes `x` a pointer to it:
```{rust}
{
let x = box 5i;
- // do stuff
+ println!("{}", *x); // Prints 5
}
```
-then Rust will automatically free `x` at the end of the block. This isn't
-because Rust has a garbage collector -- it doesn't. Instead, when `x` goes out
-of scope, Rust `free`s `x`. This Rust code will do the same thing as the
-following C code:
+The great thing about boxes is that we don't have to manually free this
+allocation! Instead, when `x` reaches the end of its lifetime -- in this case,
+when it goes out of scope at the end of the block -- Rust `free`s `x`. This
+isn't because Rust has a garbage collector (it doesn't). Instead, by tracking
+the ownership and lifetime of a variable (with a little help from you, the
+programmer), the compiler knows precisely when it is no longer used.
+
+The Rust code above will do the same thing as the following C code:
```{c,ignore}
{
int *x = (int *)malloc(sizeof(int));
- // do stuff
+ if (!x) abort();
+ *x = 5;
+ printf("%d\n", *x);
free(x);
}
```
-This means we get the benefits of manual memory management, but the compiler
-ensures that we don't do something wrong. We can't forget to `free` our memory.
+We get the benefits of manual memory management, while ensuring we don't
+introduce any bugs. We can't forget to `free` our memory.
Boxes are the sole owner of their contents, so you cannot take a mutable
reference to them and then use the original box:
*x;
```
-## Rc and Arc
-
-Sometimes, you need to allocate something on the heap, but give out multiple
-references to the memory. Rust's `Rc<T>` (pronounced 'arr cee tee') and
-`Arc<T>` types (again, the `T` is for generics, we'll learn more later) provide
-you with this ability. **Rc** stands for 'reference counted,' and **Arc** for
-'atomically reference counted.' This is how Rust keeps track of the multiple
-owners: every time we make a new reference to the `Rc<T>`, we add one to its
-internal 'reference count.' Every time a reference goes out of scope, we
-subtract one from the count. When the count is zero, the `Rc<T>` can be safely
-deallocated. `Arc<T>` is almost identical to `Rc<T>`, except for one thing: The
-'atomically' in 'Arc' means that increasing and decreasing the count uses a
-thread-safe mechanism to do so. Why two types? `Rc<T>` is faster, so if you're
-not in a multi-threaded scenario, you can have that advantage. Since we haven't
-talked about threading yet in Rust, we'll show you `Rc<T>` for the rest of this
-section.
+Boxes are simple and efficient pointers to dynamically allocated values with a
+single owner. They are useful for tree-like structures where the lifetime of a
+child depends solely on the lifetime of its (single) parent. If you need a
+value that must persist as long as any of several referrers, read on.
-To create an `Rc<T>`, use `Rc::new()`:
+## Rc and Arc
-```{rust}
-use std::rc::Rc;
+Sometimes, you need a variable that is referenced from multiple places
+(immutably!), lasting as long as any of those places, and disappearing when it
+is no longer referenced. For instance, in a graph-like data structure, a node
+might be referenced from all of its neighbors. In this case, it is not possible
+for the compiler to determine ahead of time when the value can be freed -- it
+needs a little run-time support.
-let x = Rc::new(5i);
-```
+Rust's **Rc** type provides shared ownership of a dynamically allocated value
+that is automatically freed at the end of its last owner's lifetime. (`Rc`
+stands for 'reference counted,' referring to the way these library types are
+implemented.) This provides more flexibility than single-owner boxes, but has
+some runtime overhead.
-To create a second reference, use the `.clone()` method:
+To create an `Rc` value, use `Rc::new()`. To create a second owner, use the
+`.clone()` method:
```{rust}
use std::rc::Rc;
let x = Rc::new(5i);
let y = x.clone();
+
+println!("{} {}", *x, *y); // Prints 5 5
```
-The `Rc<T>` will live as long as any of its references are alive. After they
-all go out of scope, the memory will be `free`d.
+The `Rc` will live as long as any of its owners are alive. After that, the
+memory will be `free`d.
+
+**Arc** is an 'atomically reference counted' value, identical to `Rc` except
+that ownership can be safely shared among multiple threads. Why two types?
+`Arc` has more overhead, so if you're not in a multi-threaded scenario, you
+don't have to pay the price.
-If you use `Rc<T>` or `Arc<T>`, you have to be careful about introducing
-cycles. If you have two `Rc<T>`s that point to each other, the reference counts
-will never drop to zero, and you'll have a memory leak. To learn more, check
-out [the section on `Rc<T>` and `Arc<T>` in the pointers
-guide](guide-pointers.html#rc-and-arc).
+If you use `Rc` or `Arc`, you have to be careful about introducing cycles. If
+you have two `Rc`s that point to each other, they will happily keep each other
+alive forever, creating a memory leak. To learn more, check out [the section on
+`Rc` and `Arc` in the pointers guide](guide-pointers.html#rc-and-arc).
# Patterns
# Closures
-So far, we've made lots of functions in Rust. But we've given them all names.
-Rust also allows us to create anonymous functions too. Rust's anonymous
+So far, we've made lots of functions in Rust, but we've given them all names.
+Rust also allows us to create anonymous functions. Rust's anonymous
functions are called **closure**s. By themselves, closures aren't all that
interesting, but when you combine them with functions that take closures as
arguments, really powerful things are possible.
default to returning unit (`()`).
There's one big difference between a closure and named functions, and it's in
-the name: a closure "closes over its environment." What's that mean? It means
+the name: a closure "closes over its environment." What does that mean? It means
this:
```{rust}
The `||` syntax means this is an anonymous closure that takes no arguments.
Without it, we'd just have a block of code in `{}`s.
-In other words, a closure has access to variables in the scope that it's
-defined. The closure borrows any variables that it uses. This will error:
+In other words, a closure has access to variables in the scope where it's
+defined. The closure borrows any variables it uses, so this will error:
```{rust,ignore}
fn main() {
println!("{}", p()); // prints 25
```
-Procs have a big difference from closures: they may only be called once. This
+There is a big difference between procs and closures: procs may only be called once. This
will error when we try to compile:
```{rust,ignore}
If you do the math, `(5 * 5) + (5 * 5) == 50`, so that's the output we get.
Play around with this concept until you're comfortable with it. Rust's standard
-library uses lots of closures, where appropriate, so you'll be using
+library uses lots of closures where appropriate, so you'll be using
this technique a lot.
-If we didn't want to give `square` a name, we could also just define it inline.
+If we didn't want to give `square` a name, we could just define it inline.
This example is the same as the previous one:
```{rust}
}
```
-Doing this is not particularly common, but every once in a while, it's useful.
+Doing this is not particularly common, but it's useful every once in a while.
That's all you need to get the hang of closures! Closures are a little bit
-strange at first, but once you're used to using them, you'll miss them in any
-language that doesn't have them. Passing functions to other functions is
-incredibly powerful. Next, let's look at one of those things: iterators.
+strange at first, but once you're used to them, you'll miss them
+in other languages. Passing functions to other functions is
+incredibly powerful, as you will see in the following chapter about iterators.
# Iterators
```{rust}
for x in range(0i, 10i) {
- println!("{:d}", x);
+ println!("{}", x);
}
```
```{rust}
let greater_than_forty_two = range(0i, 100i)
- .find(|x| *x >= 42);
+ .find(|x| *x > 42);
match greater_than_forty_two {
Some(_) => println!("We got some numbers!"),
`map` is called upon another iterator, and produces a new iterator where each
element reference has the closure it's been given as an argument called on it.
-So this would give us the numbers from `2-101`. Well, almost! If you
+So this would give us the numbers from `2-100`. Well, almost! If you
compile the example, you'll get a warning:
```{notrust,ignore}
If you are trying to execute a closure on an iterator for its side effects,
just use `for` instead.
-There are tons of interesting iterator adapters. `take(n)` will get the
-first `n` items out of an iterator, and return them as a list. Let's
-try it out with our infinite iterator from before, `count()`:
+There are tons of interesting iterator adapters. `take(n)` will return an
+iterator over the next `n` elements of the original iterator, note that this
+has no side effect on the original iterator. Let's try it out with our infinite
+iterator from before, `count()`:
```{rust}
for i in std::iter::count(1i, 5i).take(5) {
## Success and failure
-Tasks don't always succeed, they can also fail. A task that wishes to fail
-can call the `fail!` macro, passing a message:
+Tasks don't always succeed, they can also panic. A task that wishes to panic
+can call the `panic!` macro, passing a message:
```{rust}
spawn(proc() {
- fail!("Nope.");
+ panic!("Nope.");
});
```
-If a task fails, it is not possible for it to recover. However, it can
-notify other tasks that it has failed. We can do this with `task::try`:
+If a task panics, it is not possible for it to recover. However, it can
+notify other tasks that it has panicked. We can do this with `task::try`:
```{rust}
use std::task;
if rand::random() {
println!("OK");
} else {
- fail!("oops!");
+ panic!("oops!");
}
});
```
-This task will randomly fail or succeed. `task::try` returns a `Result`
+This task will randomly panic or succeed. `task::try` returns a `Result`
type, so we can handle the response like any other computation that may
-fail.
+panic.
# Macros
The first is when interfacing with C code, and the second is when building
certain kinds of abstractions.
-Rust has support for FFI (which you can read about in the [FFI
-Guide](guide-ffi.html)), but can't guarantee that the C code will be safe.
-Therefore, Rust marks such functions with the `unsafe`
+Rust has support for [FFI](http://en.wikipedia.org/wiki/Foreign_function_interface)
+(which you can read about in the [FFI Guide](guide-ffi.html)), but can't guarantee
+that the C code will be safe. Therefore, Rust marks such functions with the `unsafe`
keyword, which indicates that the function may not behave properly.
Second, if you'd like to create some sort of shared-memory data structure, Rust