Intpocalypse, book edition.

Fix all usage of int/uint/i/u in the book.
This commit is contained in:
Steve Klabnik 2015-01-13 10:40:18 -05:00
parent 078bd498b9
commit 899ffcf62a
13 changed files with 187 additions and 185 deletions

View File

@ -116,11 +116,11 @@ pub fn compress(src: &[u8]) -> Vec<u8> {
let psrc = src.as_ptr();
let mut dstlen = snappy_max_compressed_length(srclen);
let mut dst = Vec::with_capacity(dstlen as uint);
let mut dst = Vec::with_capacity(dstlen as usize);
let pdst = dst.as_mut_ptr();
snappy_compress(psrc, srclen, pdst, &mut dstlen);
dst.set_len(dstlen as uint);
dst.set_len(dstlen as usize);
dst
}
}
@ -148,11 +148,11 @@ pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> {
let mut dstlen: size_t = 0;
snappy_uncompressed_length(psrc, srclen, &mut dstlen);
let mut dst = Vec::with_capacity(dstlen as uint);
let mut dst = Vec::with_capacity(dstlen as usize);
let pdst = dst.as_mut_ptr();
if snappy_uncompress(psrc, srclen, pdst, &mut dstlen) == 0 {
dst.set_len(dstlen as uint);
dst.set_len(dstlen as usize);
Some(dst)
} else {
None // SNAPPY_INVALID_INPUT

View File

@ -5,7 +5,7 @@ multiple types of arguments. For example, remember our `OptionalInt` type?
```{rust}
enum OptionalInt {
Value(int),
Value(i32),
Missing,
}
```
@ -40,26 +40,26 @@ we substitute that type for the same type used in the generic. Here's an
example of using `Option<T>`, with some extra type annotations:
```{rust}
let x: Option<int> = Some(5i);
let x: Option<i32> = Some(5);
```
In the type declaration, we say `Option<int>`. Note how similar this looks to
`Option<T>`. So, in this particular `Option`, `T` has the value of `int`. On
the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5i`.
Since that's an `int`, the two sides match, and Rust is happy. If they didn't
In the type declaration, we say `Option<i32>`. Note how similar this looks to
`Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On
the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5`.
Since that's an `i32`, the two sides match, and Rust is happy. If they didn't
match, we'd get an error:
```{rust,ignore}
let x: Option<f64> = Some(5i);
// error: mismatched types: expected `core::option::Option<f64>`
// but found `core::option::Option<int>` (expected f64 but found int)
let x: Option<f64> = Some(5);
// error: mismatched types: expected `core::option::Option<f64>`,
// found `core::option::Option<_>` (expected f64 but found integral variable)
```
That doesn't mean we can't make `Option<T>`s that hold an `f64`! They just have to
match up:
```{rust}
let x: Option<int> = Some(5i);
let x: Option<i32> = Some(5);
let y: Option<f64> = Some(5.0f64);
```

View File

@ -5,7 +5,7 @@ Let's talk about loops.
Remember Rust's `for` loop? Here's an example:
```{rust}
for x in range(0i, 10i) {
for x in range(0, 10) {
println!("{}", x);
}
```
@ -17,7 +17,7 @@ call the `.next()` method on repeatedly, and it gives us a sequence of things.
Like this:
```{rust}
let mut range = range(0i, 10i);
let mut range = range(0, 10);
loop {
match range.next() {
@ -32,8 +32,8 @@ loop {
We make a mutable binding to the return value of `range`, which is our iterator.
We then `loop`, with an inner `match`. This `match` is used on the result of
`range.next()`, which gives us a reference to the next value of the iterator.
`next` returns an `Option<int>`, in this case, which will be `Some(int)` when
we have a value and `None` once we run out. If we get `Some(int)`, we print it
`next` returns an `Option<i32>`, in this case, which will be `Some(i32)` when
we have a value and `None` once we run out. If we get `Some(i32)`, we print it
out, and if we get `None`, we `break` out of the loop.
This code sample is basically the same as our `for` loop version. The `for`
@ -50,9 +50,9 @@ primitive. For example, if you needed to iterate over the contents of
a vector, you may be tempted to write this:
```{rust}
let nums = vec![1i, 2i, 3i];
let nums = vec![1, 2, 3];
for i in range(0u, nums.len()) {
for i in range(0, nums.len()) {
println!("{}", nums[i]);
}
```
@ -62,7 +62,7 @@ vectors returns an iterator which iterates through a reference to each element
of the vector in turn. So write this:
```{rust}
let nums = vec![1i, 2i, 3i];
let nums = vec![1, 2, 3];
for num in nums.iter() {
println!("{}", num);
@ -79,12 +79,12 @@ very common with iterators: we can ignore unnecessary bounds checks, but still
know that we're safe.
There's another detail here that's not 100% clear because of how `println!`
works. `num` is actually of type `&int`. That is, it's a reference to an `int`,
not an `int` itself. `println!` handles the dereferencing for us, so we don't
works. `num` is actually of type `&i32`. That is, it's a reference to an `i32`,
not an `i32` itself. `println!` handles the dereferencing for us, so we don't
see it. This code works fine too:
```{rust}
let nums = vec![1i, 2i, 3i];
let nums = vec![1, 2, 3];
for num in nums.iter() {
println!("{}", *num);
@ -118,7 +118,7 @@ The most common consumer is `collect()`. This code doesn't quite compile,
but it shows the intention:
```{rust,ignore}
let one_to_one_hundred = range(1i, 101i).collect();
let one_to_one_hundred = range(1, 101).collect();
```
As you can see, we call `collect()` on our iterator. `collect()` takes
@ -128,7 +128,7 @@ type of things you want to collect, and so you need to let it know.
Here's the version that does compile:
```{rust}
let one_to_one_hundred = range(1i, 101i).collect::<Vec<int>>();
let one_to_one_hundred = range(1, 101).collect::<Vec<i32>>();
```
If you remember, the `::<>` syntax allows us to give a type hint,
@ -138,7 +138,7 @@ and so we tell it that we want a vector of integers.
is one:
```{rust}
let greater_than_forty_two = range(0i, 100i)
let greater_than_forty_two = range(0, 100)
.find(|x| *x > 42);
match greater_than_forty_two {
@ -155,8 +155,8 @@ element, `find` returns an `Option` rather than the element itself.
Another important consumer is `fold`. Here's what it looks like:
```{rust}
let sum = range(1i, 4i)
.fold(0i, |sum, x| sum + x);
let sum = range(1, 4)
.fold(0, |sum, x| sum + x);
```
`fold()` is a consumer that looks like this:
@ -172,24 +172,24 @@ in this iterator:
| base | accumulator | element | closure result |
|------|-------------|---------|----------------|
| 0i | 0i | 1i | 1i |
| 0i | 1i | 2i | 3i |
| 0i | 3i | 3i | 6i |
| 0 | 0 | 1 | 1 |
| 0 | 1 | 2 | 3 |
| 0 | 3 | 3 | 6 |
We called `fold()` with these arguments:
```{rust}
# range(1i, 4i)
.fold(0i, |sum, x| sum + x);
# range(1, 4)
.fold(0, |sum, x| sum + x);
```
So, `0i` is our base, `sum` is our accumulator, and `x` is our element. On the
first iteration, we set `sum` to `0i`, and `x` is the first element of `nums`,
`1i`. We then add `sum` and `x`, which gives us `0i + 1i = 1i`. On the second
So, `0` is our base, `sum` is our accumulator, and `x` is our element. On the
first iteration, we set `sum` to `0`, and `x` is the first element of `nums`,
`1`. We then add `sum` and `x`, which gives us `0 + 1 = 1`. On the second
iteration, that value becomes our accumulator, `sum`, and the element is
the second element of the array, `2i`. `1i + 2i = 3i`, and so that becomes
the second element of the array, `2`. `1 + 2 = 3`, and so that becomes
the value of the accumulator for the last iteration. On that iteration,
`x` is the last element, `3i`, and `3i + 3i = 6i`, which is our final
`x` is the last element, `3`, and `3 + 3 = 6`, which is our final
result for our sum. `1 + 2 + 3 = 6`, and that's the result we got.
Whew. `fold` can be a bit strange the first few times you see it, but once it
@ -210,14 +210,14 @@ This code, for example, does not actually generate the numbers
`1-100`, and just creates a value that represents the sequence:
```{rust}
let nums = range(1i, 100i);
let nums = range(1, 100);
```
Since we didn't do anything with the range, it didn't generate the sequence.
Let's add the consumer:
```{rust}
let nums = range(1i, 100i).collect::<Vec<int>>();
let nums = range(1, 100).collect::<Vec<i32>>();
```
Now, `collect()` will require that `range()` give it some numbers, and so
@ -228,7 +228,7 @@ which you've used before. `iter()` can turn a vector into a simple iterator
that gives you each element in turn:
```{rust}
let nums = [1i, 2i, 3i];
let nums = [1, 2, 3];
for num in nums.iter() {
println!("{}", num);
@ -239,12 +239,12 @@ These two basic iterators should serve you well. There are some more
advanced iterators, including ones that are infinite. Like `count`:
```{rust}
std::iter::count(1i, 5i);
std::iter::count(1, 5);
```
This iterator counts up from one, adding five each time. It will give
you a new integer every time, forever (well, technically, until it reaches the
maximum number representable by an `int`). But since iterators are lazy,
maximum number representable by an `i32`). But since iterators are lazy,
that's okay! You probably don't want to use `collect()` on it, though...
That's enough about iterators. Iterator adapters are the last concept
@ -256,7 +256,7 @@ we need to talk about with regards to iterators. Let's get to it!
a new iterator. The simplest one is called `map`:
```{rust,ignore}
range(1i, 100i).map(|x| x + 1i);
range(1, 100).map(|x| x + 1);
```
`map` is called upon another iterator, and produces a new iterator where each
@ -267,7 +267,7 @@ compile the example, you'll get a warning:
```{notrust,ignore}
warning: unused result which must be used: iterator adaptors are lazy and
do nothing unless consumed, #[warn(unused_must_use)] on by default
range(1i, 100i).map(|x| x + 1i);
range(1, 100).map(|x| x + 1);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
@ -275,7 +275,7 @@ Laziness strikes again! That closure will never execute. This example
doesn't print any numbers:
```{rust,ignore}
range(1i, 100i).map(|x| println!("{}", x));
range(1, 100).map(|x| println!("{}", x));
```
If you are trying to execute a closure on an iterator for its side effects,
@ -287,7 +287,7 @@ 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) {
for i in std::iter::count(1, 5).take(5) {
println!("{}", i);
}
```
@ -307,7 +307,7 @@ returns `true` or `false`. The new iterator `filter()` produces
only the elements that that closure returns `true` for:
```{rust}
for i in range(1i, 100i).filter(|&x| x % 2 == 0) {
for i in range(1, 100).filter(|&x| x % 2 == 0) {
println!("{}", i);
}
```
@ -322,11 +322,11 @@ You can chain all three things together: start with an iterator, adapt it
a few times, and then consume the result. Check it out:
```{rust}
range(1i, 1000i)
range(1, 1000)
.filter(|&x| x % 2 == 0)
.filter(|&x| x % 3 == 0)
.take(5)
.collect::<Vec<int>>();
.collect::<Vec<i32>>();
```
This will give you a vector containing `6`, `12`, `18`, `24`, and `30`.

View File

@ -54,7 +54,7 @@ The other kind of looping construct in Rust is the `while` loop. It looks like
this:
```{rust}
let mut x = 5u32; // mut x: u32
let mut x = 5; // mut x: u32
let mut done = false; // mut done: bool
while !done {
@ -91,7 +91,7 @@ can do with safety and code generation, so you should always prefer
Let's take a look at that `while` loop we had earlier:
```{rust}
let mut x = 5u32;
let mut x = 5;
let mut done = false;
while !done {
@ -108,7 +108,7 @@ modifying iteration: `break` and `continue`.
In this case, we can write the loop in a better way with `break`:
```{rust}
let mut x = 5u32;
let mut x = 5;
loop {
x += x - 3;

View File

@ -11,8 +11,8 @@ which both pattern-match on their input and both return early in one case,
doing nothing otherwise:
~~~~
# enum T { SpecialA(uint), SpecialB(uint) }
# fn f() -> uint {
# enum T { SpecialA(u32), SpecialB(u32) }
# fn f() -> u32 {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
match input_1 {
@ -24,7 +24,7 @@ match input_2 {
T::SpecialB(x) => { return x; }
_ => {}
}
# return 0u;
# return 0;
# }
~~~~
@ -37,8 +37,8 @@ lightweight custom syntax extensions, themselves defined using the
the pattern in the above code:
~~~~
# enum T { SpecialA(uint), SpecialB(uint) }
# fn f() -> uint {
# enum T { SpecialA(u32), SpecialB(u32) }
# fn f() -> u32 {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
macro_rules! early_return {
@ -165,8 +165,8 @@ separator token (a comma-separated list could be written `$(...),*`), and `+`
instead of `*` to mean "at least one".
~~~~
# enum T { SpecialA(uint),SpecialB(uint),SpecialC(uint),SpecialD(uint)}
# fn f() -> uint {
# enum T { SpecialA(u32), SpecialB(u32), SpecialC(u32), SpecialD(u32) }
# fn f() -> u32 {
# let input_1 = T::SpecialA(0);
# let input_2 = T::SpecialA(0);
macro_rules! early_return {
@ -226,10 +226,10 @@ solves the problem.
Now consider code like the following:
~~~~
# enum T1 { Good1(T2, uint), Bad1}
# enum T1 { Good1(T2, u32), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(uint), Bad2}
# fn f(x: T1) -> uint {
# enum T3 { Good2(u32), Bad2}
# fn f(x: T1) -> u32 {
match x {
T1::Good1(g1, val) => {
match g1.body {
@ -273,10 +273,10 @@ macro_rules! biased_match {
)
}
# enum T1 { Good1(T2, uint), Bad1}
# enum T1 { Good1(T2, u32), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(uint), Bad2}
# fn f(x: T1) -> uint {
# enum T3 { Good2(u32), Bad2}
# fn f(x: T1) -> u32 {
biased_match!((x) -> (T1::Good1(g1, val)) else { return 0 };
binds g1, val );
biased_match!((g1.body) -> (T3::Good2(result) )
@ -383,10 +383,10 @@ macro_rules! biased_match {
}
# enum T1 { Good1(T2, uint), Bad1}
# enum T1 { Good1(T2, u32), Bad1}
# struct T2 { body: T3 }
# enum T3 { Good2(uint), Bad2}
# fn f(x: T1) -> uint {
# enum T3 { Good2(u32), Bad2}
# fn f(x: T1) -> u32 {
biased_match!(
(x) -> (T1::Good1(g1, val)) else { return 0 };
(g1.body) -> (T3::Good2(result) ) else { panic!("Didn't get Good2") };
@ -528,7 +528,7 @@ A further difficulty occurs when a macro is used in multiple crates. Say that
`mylib` defines
```rust
pub fn increment(x: uint) -> uint {
pub fn increment(x: u32) -> u32 {
x + 1
}

View File

@ -418,7 +418,7 @@ struct Wheel {
fn main() {
let car = Car { name: "DeLorean".to_string() };
for _ in range(0u, 4) {
for _ in range(0, 4) {
Wheel { size: 360, owner: car };
}
}
@ -456,7 +456,7 @@ fn main() {
let car_owner = Rc::new(car);
for _ in range(0u, 4) {
for _ in range(0, 4) {
Wheel { size: 360, owner: car_owner.clone() };
}
}

View File

@ -8,7 +8,7 @@ A quick refresher: you can match against literals directly, and `_` acts as an
*any* case:
```{rust}
let x = 1i;
let x = 1;
match x {
1 => println!("one"),
@ -21,7 +21,7 @@ match x {
You can match multiple patterns with `|`:
```{rust}
let x = 1i;
let x = 1;
match x {
1 | 2 => println!("one or two"),
@ -33,7 +33,7 @@ match x {
You can match a range of values with `...`:
```{rust}
let x = 1i;
let x = 1;
match x {
1 ... 5 => println!("one through five"),
@ -47,7 +47,7 @@ If you're matching multiple things, via a `|` or a `...`, you can bind
the value to a name with `@`:
```{rust}
let x = 1i;
let x = 1;
match x {
e @ 1 ... 5 => println!("got a range element {}", e),
@ -60,11 +60,11 @@ ignore the value and type in the variant:
```{rust}
enum OptionalInt {
Value(int),
Value(i32),
Missing,
}
let x = OptionalInt::Value(5i);
let x = OptionalInt::Value(5);
match x {
OptionalInt::Value(..) => println!("Got an int!"),
@ -76,11 +76,11 @@ You can introduce *match guards* with `if`:
```{rust}
enum OptionalInt {
Value(int),
Value(i32),
Missing,
}
let x = OptionalInt::Value(5i);
let x = OptionalInt::Value(5);
match x {
OptionalInt::Value(i) if i > 5 => println!("Got an int bigger than five!"),
@ -93,33 +93,33 @@ If you're matching on a pointer, you can use the same syntax as you declared it
with. First, `&`:
```{rust}
let x = &5i;
let x = &5;
match x {
&val => println!("Got a value: {}", val),
}
```
Here, the `val` inside the `match` has type `int`. In other words, the left-hand
side of the pattern destructures the value. If we have `&5i`, then in `&val`, `val`
would be `5i`.
Here, the `val` inside the `match` has type `i32`. In other words, the left-hand
side of the pattern destructures the value. If we have `&5`, then in `&val`, `val`
would be `5`.
If you want to get a reference, use the `ref` keyword:
```{rust}
let x = 5i;
let x = 5;
match x {
ref r => println!("Got a reference to {}", r),
}
```
Here, the `r` inside the `match` has the type `&int`. In other words, the `ref`
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
keyword _creates_ a reference, for use in the pattern. If you need a mutable
reference, `ref mut` will work in the same way:
```{rust}
let mut x = 5i;
let mut x = 5;
match x {
ref mut mr => println!("Got a mutable reference to {}", mr),
@ -131,11 +131,11 @@ If you have a struct, you can destructure it inside of a pattern:
```{rust}
# #![allow(non_shorthand_field_patterns)]
struct Point {
x: int,
y: int,
x: i32,
y: i32,
}
let origin = Point { x: 0i, y: 0i };
let origin = Point { x: 0, y: 0 };
match origin {
Point { x: x, y: y } => println!("({},{})", x, y),
@ -147,11 +147,11 @@ If we only care about some of the values, we don't have to give them all names:
```{rust}
# #![allow(non_shorthand_field_patterns)]
struct Point {
x: int,
y: int,
x: i32,
y: i32,
}
let origin = Point { x: 0i, y: 0i };
let origin = Point { x: 0, y: 0 };
match origin {
Point { x: x, .. } => println!("x is {}", x),
@ -163,11 +163,11 @@ You can do this kind of match on any member, not just the first:
```{rust}
# #![allow(non_shorthand_field_patterns)]
struct Point {
x: int,
y: int,
x: i32,
y: i32,
}
let origin = Point { x: 0i, y: 0i };
let origin = Point { x: 0, y: 0 };
match origin {
Point { y: y, .. } => println!("y is {}", y),

View File

@ -68,7 +68,7 @@ use rustc::plugin::Registry;
fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
-> Box<MacResult + 'static> {
static NUMERALS: &'static [(&'static str, uint)] = &[
static NUMERALS: &'static [(&'static str, u32)] = &[
("M", 1000), ("CM", 900), ("D", 500), ("CD", 400),
("C", 100), ("XC", 90), ("L", 50), ("XL", 40),
("X", 10), ("IX", 9), ("V", 5), ("IV", 4),
@ -83,7 +83,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
};
let mut text = text.as_slice();
let mut total = 0u;
let mut total = 0;
while !text.is_empty() {
match NUMERALS.iter().find(|&&(rn, _)| text.starts_with(rn)) {
Some(&(rn, val)) => {
@ -118,7 +118,7 @@ fn main() {
}
```
The advantages over a simple `fn(&str) -> uint` are:
The advantages over a simple `fn(&str) -> u32` are:
* The (arbitrarily complex) conversion is done at compile time.
* Input validation is also performed at compile time.

View File

@ -28,9 +28,10 @@ question](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-
as the rest of this guide assumes you know the difference.) Like this:
```{rust}
let x = 5i;
let y = 8i;
let x = 5;
let y = 8;
```
| location | value |
|----------|-------|
| 0xd3e030 | 5 |
@ -46,10 +47,11 @@ Let's introduce a pointer. In some languages, there is just one type of
*reference*, which is the simplest kind of pointer.
```{rust}
let x = 5i;
let y = 8i;
let x = 5;
let y = 8;
let z = &y;
```
|location | value |
|-------- |----------|
|0xd3e030 | 5 |
@ -58,12 +60,12 @@ let z = &y;
See the difference? Rather than contain a value, the value of a pointer is a
location in memory. In this case, the location of `y`. `x` and `y` have the
type `int`, but `z` has the type `&int`. We can print this location using the
type `i32`, but `z` has the type `&i32`. We can print this location using the
`{:p}` format string:
```{rust}
let x = 5i;
let y = 8i;
let x = 5;
let y = 8;
let z = &y;
println!("{:p}", z);
@ -71,12 +73,12 @@ println!("{:p}", z);
This would print `0xd3e028`, with our fictional memory addresses.
Because `int` and `&int` are different types, we can't, for example, add them
Because `i32` and `&i32` are different types, we can't, for example, add them
together:
```{rust,ignore}
let x = 5i;
let y = 8i;
let x = 5;
let y = 8;
let z = &y;
println!("{}", x + z);
@ -85,7 +87,7 @@ println!("{}", x + z);
This gives us an error:
```text
hello.rs:6:24: 6:25 error: mismatched types: expected `int` but found `&int` (expected int but found &-ptr)
hello.rs:6:24: 6:25 error: mismatched types: expected `i32` but found `&i32` (expected i32 but found &-ptr)
hello.rs:6 println!("{}", x + z);
^
```
@ -95,8 +97,8 @@ pointer means accessing the value at the location stored in the pointer. This
will work:
```{rust}
let x = 5i;
let y = 8i;
let x = 5;
let y = 8;
let z = &y;
println!("{}", x + *z);
@ -153,7 +155,7 @@ So what do pointers have to do with this? Well, since pointers point to a
location in memory...
```text
func foo(&int x) {
func foo(&i32 x) {
*x = 5
}
@ -252,7 +254,7 @@ The most basic type of pointer that Rust has is called a *reference*. Rust
references look like this:
```{rust}
let x = 5i;
let x = 5;
let y = &x;
println!("{}", *y);
@ -269,18 +271,18 @@ referent, because `println!` will automatically dereference it for us.
Here's a function that takes a reference:
```{rust}
fn succ(x: &int) -> int { *x + 1 }
fn succ(x: &i32) -> i32 { *x + 1 }
```
You can also use `&` as an operator to create a reference, so we can
call this function in two different ways:
```{rust}
fn succ(x: &int) -> int { *x + 1 }
fn succ(x: &i32) -> i32 { *x + 1 }
fn main() {
let x = 5i;
let x = 5;
let y = &x;
println!("{}", succ(y));
@ -294,13 +296,13 @@ Of course, if this were real code, we wouldn't bother with the reference, and
just write:
```{rust}
fn succ(x: int) -> int { x + 1 }
fn succ(x: i32) -> i32 { x + 1 }
```
References are immutable by default:
```{rust,ignore}
let x = 5i;
let x = 5;
let y = &x;
*y = 5; // error: cannot assign to immutable dereference of `&`-pointer `*y`
@ -310,21 +312,21 @@ They can be made mutable with `mut`, but only if its referent is also mutable.
This works:
```{rust}
let mut x = 5i;
let mut x = 5;
let y = &mut x;
```
This does not:
```{rust,ignore}
let x = 5i;
let x = 5;
let y = &mut x; // error: cannot borrow immutable local variable `x` as mutable
```
Immutable pointers are allowed to alias:
```{rust}
let x = 5i;
let x = 5;
let y = &x;
let z = &x;
```
@ -332,7 +334,7 @@ let z = &x;
Mutable ones, however, are not:
```{rust,ignore}
let mut x = 5i;
let mut x = 5;
let y = &mut x;
let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time
```
@ -359,7 +361,7 @@ duration a *lifetime*. Let's try a more complex example:
```{rust}
fn main() {
let x = &mut 5i;
let x = &mut 5;
if *x < 10 {
let y = &x;
@ -380,7 +382,7 @@ mutated, and therefore, lets us pass. This wouldn't work:
```{rust,ignore}
fn main() {
let x = &mut 5i;
let x = &mut 5;
if *x < 10 {
let y = &x;
@ -425,13 +427,13 @@ References just borrow ownership, which is more polite if you don't need the
ownership. In other words, prefer:
```{rust}
fn succ(x: &int) -> int { *x + 1 }
fn succ(x: &i32) -> i32 { *x + 1 }
```
to
```{rust}
fn succ(x: Box<int>) -> int { *x + 1 }
fn succ(x: Box<i32>) -> i32 { *x + 1 }
```
As a corollary to that rule, references allow you to accept a wide variety of
@ -439,7 +441,7 @@ other pointers, and so are useful so that you don't have to write a number
of variants per pointer. In other words, prefer:
```{rust}
fn succ(x: &int) -> int { *x + 1 }
fn succ(x: &i32) -> i32 { *x + 1 }
```
to
@ -447,9 +449,9 @@ to
```{rust}
use std::rc::Rc;
fn box_succ(x: Box<int>) -> int { *x + 1 }
fn box_succ(x: Box<i32>) -> i32 { *x + 1 }
fn rc_succ(x: Rc<int>) -> int { *x + 1 }
fn rc_succ(x: Rc<i32>) -> i32 { *x + 1 }
```
Note that the caller of your function will have to modify their calls slightly:
@ -457,11 +459,11 @@ Note that the caller of your function will have to modify their calls slightly:
```{rust}
use std::rc::Rc;
fn succ(x: &int) -> int { *x + 1 }
fn succ(x: &i32) -> i32 { *x + 1 }
let ref_x = &5i;
let box_x = Box::new(5i);
let rc_x = Rc::new(5i);
let ref_x = &5;
let box_x = Box::new(5);
let rc_x = Rc::new(5);
succ(ref_x);
succ(&*box_x);
@ -477,7 +479,7 @@ those contents.
heap allocation in Rust. Creating a box looks like this:
```{rust}
let x = Box::new(5i);
let x = Box::new(5);
```
Boxes are heap allocated and they are deallocated automatically by Rust when
@ -485,7 +487,7 @@ they go out of scope:
```{rust}
{
let x = Box::new(5i);
let x = Box::new(5);
// stuff happens
@ -505,7 +507,7 @@ boxes, though. As a rough approximation, you can treat this Rust code:
```{rust}
{
let x = Box::new(5i);
let x = Box::new(5);
// stuff happens
}
@ -544,12 +546,12 @@ for more detail on how lifetimes work.
Using boxes and references together is very common. For example:
```{rust}
fn add_one(x: &int) -> int {
fn add_one(x: &i32) -> i32 {
*x + 1
}
fn main() {
let x = Box::new(5i);
let x = Box::new(5);
println!("{}", add_one(&*x));
}
@ -561,12 +563,12 @@ function, and since it's only reading the value, allows it.
We can borrow `x` multiple times, as long as it's not simultaneous:
```{rust}
fn add_one(x: &int) -> int {
fn add_one(x: &i32) -> i32 {
*x + 1
}
fn main() {
let x = Box::new(5i);
let x = Box::new(5);
println!("{}", add_one(&*x));
println!("{}", add_one(&*x));
@ -577,12 +579,12 @@ fn main() {
Or as long as it's not a mutable borrow. This will error:
```{rust,ignore}
fn add_one(x: &mut int) -> int {
fn add_one(x: &mut i32) -> i32 {
*x + 1
}
fn main() {
let x = Box::new(5i);
let x = Box::new(5);
println!("{}", add_one(&*x)); // error: cannot borrow immutable dereference
// of `&`-pointer as mutable
@ -610,7 +612,7 @@ enum List<T> {
}
fn main() {
let list: List<int> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
println!("{:?}", list);
}
```
@ -659,10 +661,10 @@ so as to avoid copying a large data structure. For example:
```{rust}
struct BigStruct {
one: int,
two: int,
one: i32,
two: i32,
// etc
one_hundred: int,
one_hundred: i32,
}
fn foo(x: Box<BigStruct>) -> Box<BigStruct> {
@ -687,10 +689,10 @@ This is an antipattern in Rust. Instead, write this:
```{rust}
struct BigStruct {
one: int,
two: int,
one: i32,
two: i32,
// etc
one_hundred: int,
one_hundred: i32,
}
fn foo(x: Box<BigStruct>) -> BigStruct {

View File

@ -512,7 +512,7 @@ use test::Bencher;
#[bench]
fn bench_xor_1000_ints(b: &mut Bencher) {
b.iter(|| {
range(0u, 1000).fold(0, |old, new| old ^ new);
range(0, 1000).fold(0, |old, new| old ^ new);
});
}
```
@ -537,7 +537,7 @@ computation entirely. This could be done for the example above by adjusting the
# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
b.iter(|| {
// note lack of `;` (could also use an explicit `return`).
range(0u, 1000).fold(0, |old, new| old ^ new)
range(0, 1000).fold(0, |old, new| old ^ new)
});
```

View File

@ -224,7 +224,7 @@ use std::sync::Future;
# fn main() {
# fn make_a_sandwich() {};
fn fib(n: u64) -> u64 {
// lengthy computation returning an uint
// lengthy computation returning an 64
12586269025
}
@ -249,7 +249,7 @@ computations. The workload will be distributed on the available cores.
# #![allow(deprecated)]
# use std::num::Float;
# use std::sync::Future;
fn partial_sum(start: uint) -> f64 {
fn partial_sum(start: u64) -> f64 {
let mut local_sum = 0f64;
for num in range(start*100000, (start+1)*100000) {
local_sum += (num as f64 + 1.0).powf(-2.0);
@ -289,7 +289,7 @@ use std::num::Float;
use std::rand;
use std::sync::Arc;
fn pnorm(nums: &[f64], p: uint) -> f64 {
fn pnorm(nums: &[f64], p: u64) -> f64 {
nums.iter().fold(0.0, |a, b| a + b.powf(p as f64)).powf(1.0 / (p as f64))
}
@ -297,7 +297,7 @@ fn main() {
let numbers = Vec::from_fn(1000000, |_| rand::random::<f64>());
let numbers_arc = Arc::new(numbers);
for num in range(1u, 10) {
for num in range(1, 10) {
let thread_numbers = numbers_arc.clone();
spawn(move || {
@ -328,7 +328,7 @@ if it were local.
```{rust,ignore}
# use std::rand;
# use std::sync::Arc;
# fn pnorm(nums: &[f64], p: uint) -> f64 { 4.0 }
# fn pnorm(nums: &[f64], p: u64) -> f64 { 4.0 }
# fn main() {
# let numbers=Vec::from_fn(1000000, |_| rand::random::<f64>());
# let numbers_arc = Arc::new(numbers);
@ -357,16 +357,16 @@ each other if they panic. The simplest way of handling a panic is with the
`try` function, which is similar to `spawn`, but immediately blocks and waits
for the child thread to finish. `try` returns a value of type
`Result<T, Box<Any + Send>>`. `Result` is an `enum` type with two variants:
`Ok` and `Err`. In this case, because the type arguments to `Result` are `int`
`Ok` and `Err`. In this case, because the type arguments to `Result` are `i32`
and `()`, callers can pattern-match on a result to check whether it's an `Ok`
result with an `int` field (representing a successful result) or an `Err` result
result with an `i32` field (representing a successful result) or an `Err` result
(representing termination with an error).
```{rust,ignore}
# use std::thread::Thread;
# fn some_condition() -> bool { false }
# fn calculate_result() -> int { 0 }
let result: Result<int, Box<std::any::Any + Send>> = Thread::spawn(move || {
# fn calculate_result() -> i32 { 0 }
let result: Result<i32, Box<std::any::Any + Send>> = Thread::spawn(move || {
if some_condition() {
calculate_result()
} else {

View File

@ -145,7 +145,7 @@ As you can see, `print_area` is now generic, but also ensures that we
have passed in the correct types. If we pass in an incorrect type:
```{rust,ignore}
print_area(5i);
print_area(5);
```
We get a compile-time error:
@ -156,14 +156,14 @@ error: failed to find an implementation of trait main::HasArea for int
So far, we've only added trait implementations to structs, but you can
implement a trait for any type. So technically, we _could_ implement
`HasArea` for `int`:
`HasArea` for `i32`:
```{rust}
trait HasArea {
fn area(&self) -> f64;
}
impl HasArea for int {
impl HasArea for i32 {
fn area(&self) -> f64 {
println!("this is silly");
@ -171,7 +171,7 @@ impl HasArea for int {
}
}
5i.area();
5.area();
```
It is considered poor style to implement methods on such primitive types, even
@ -264,8 +264,8 @@ it won't affect you, unless you `use` that trait.
There's one more restriction on implementing traits. Either the trait or the
type you're writing the `impl` for must be inside your crate. So, we could
implement the `HasArea` type for `int`, because `HasArea` is in our crate. But
if we tried to implement `Float`, a trait provided by Rust, for `int`, we could
implement the `HasArea` type for `i32`, because `HasArea` is in our crate. But
if we tried to implement `Float`, a trait provided by Rust, for `i32`, we could
not, because both the trait and the type aren't in our crate.
One last thing about traits: generic functions with a trait bound use

View File

@ -95,7 +95,7 @@ offered by the Rust language and libraries. For example, they
use-after-free;
- are considered sendable (if their contents is considered sendable),
so the compiler offers no assistance with ensuring their use is
thread-safe; for example, one can concurrently access a `*mut int`
thread-safe; for example, one can concurrently access a `*mut i32`
from two threads without synchronization.
- lack any form of lifetimes, unlike `&`, and so the compiler cannot
reason about dangling pointers; and
@ -265,12 +265,12 @@ impl<T: Send> Drop for Unique<T> {
// A comparison between the built-in `Box` and this reimplementation
fn main() {
{
let mut x = Box::new(5i);
let mut x = Box::new(5);
*x = 10;
} // `x` is freed here
{
let mut y = Unique::new(5i);
let mut y = Unique::new(5);
*y.borrow_mut() = 10;
} // `y` is freed here
}
@ -367,7 +367,7 @@ expressions must be mutable lvalues:
```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn add(a: int, b: int) -> int {
fn add(a: i32, b: i32) -> i32 {
let mut c = 0;
unsafe {
asm!("add $2, $0"
@ -378,7 +378,7 @@ fn add(a: int, b: int) -> int {
c
}
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
# fn add(a: int, b: int) -> int { a + b }
# fn add(a: i32, b: i32) -> i32 { a + b }
fn main() {
assert_eq!(add(3, 14159), 14162)
@ -454,7 +454,7 @@ extern crate libc;
// Entry point for this program
#[start]
fn start(_argc: int, _argv: *const *const u8) -> int {
fn start(_argc: isize, _argv: *const *const u8) -> isize {
0
}
@ -480,7 +480,7 @@ compiler's name mangling too:
extern crate libc;
#[no_mangle] // ensure that this symbol is called `main` in the output
pub extern fn main(argc: int, argv: *const *const u8) -> int {
pub extern fn main(argc: i32, argv: *const *const u8) -> i32 {
0
}
@ -552,8 +552,8 @@ pub extern fn dot_product(a: *const u32, a_len: u32,
// cannot tell the pointers are valid.
let (a_slice, b_slice): (&[u32], &[u32]) = unsafe {
mem::transmute((
Slice { data: a, len: a_len as uint },
Slice { data: b, len: b_len as uint },
Slice { data: a, len: a_len as usize },
Slice { data: b, len: b_len as usize },
))
};
@ -568,13 +568,13 @@ pub extern fn dot_product(a: *const u32, a_len: u32,
#[lang = "panic_fmt"]
extern fn panic_fmt(args: &core::fmt::Arguments,
file: &str,
line: uint) -> ! {
line: u32) -> ! {
loop {}
}
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
# #[start] fn start(argc: int, argv: *const *const u8) -> int { 0 }
# #[start] fn start(argc: isize, argv: *const *const u8) -> isize { 0 }
# fn main() {}
```
@ -628,7 +628,7 @@ via a declaration like
extern "rust-intrinsic" {
fn transmute<T, U>(x: T) -> U;
fn offset<T>(dst: *const T, offset: int) -> *const T;
fn offset<T>(dst: *const T, offset: isize) -> *const T;
}
```
@ -665,24 +665,24 @@ extern {
pub struct Box<T>(*mut T);
#[lang="exchange_malloc"]
unsafe fn allocate(size: uint, _align: uint) -> *mut u8 {
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
let p = libc::malloc(size as libc::size_t) as *mut u8;
// malloc failed
if p as uint == 0 {
if p as usize == 0 {
abort();
}
p
}
#[lang="exchange_free"]
unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
libc::free(ptr as *mut libc::c_void)
}
#[start]
fn main(argc: int, argv: *const *const u8) -> int {
let x = box 1i;
fn main(argc: isize, argv: *const *const u8) -> isize {
let x = box 1;
0
}