diff --git a/src/doc/guide.md b/src/doc/guide.md index 838d54f81c4..f45cb36c719 100644 --- a/src/doc/guide.md +++ b/src/doc/guide.md @@ -384,7 +384,7 @@ The first thing we'll learn about are 'variable bindings.' They look like this: ```{rust} fn main() { - let x = 5i; + let x = 5; } ``` @@ -399,15 +399,13 @@ hand side of a `let` expression is a full pattern, not just a variable name. This means we can do things like: ```{rust} -let (x, y) = (1i, 2i); +let (x, y) = (1, 2); ``` After this expression is evaluated, `x` will be one, and `y` will be two. Patterns are really powerful, but this is about all we can do with them so far. So let's just keep this in the back of our minds as we go forward. -By the way, in these examples, `i` indicates that the number is an integer. - Rust is a statically typed language, which means that we specify our types up front. So why does our first example compile? Well, Rust has this thing called "type inference." If it can figure out what the type of something is, Rust @@ -416,18 +414,18 @@ doesn't require you to actually type it out. We can add the type if we want to, though. Types come after a colon (`:`): ```{rust} -let x: int = 5; +let x: i32 = 5; ``` If I asked you to read this out loud to the rest of the class, you'd say "`x` -is a binding with the type `int` and the value `five`." +is a binding with the type `i32` and the value `five`." In future examples, we may annotate the type in a comment. The examples will look like this: ```{rust} fn main() { - let x = 5i; // x: int + let x = 5; // x: i32 } ``` @@ -438,23 +436,23 @@ include them to help you understand what the types that Rust infers are. By default, bindings are **immutable**. This code will not compile: ```{ignore} -let x = 5i; -x = 10i; +let x = 5; +x = 10; ``` It will give you this error: ```text error: re-assignment of immutable variable `x` - x = 10i; + x = 10; ^~~~~~~ ``` If you want a binding to be mutable, you can use `mut`: ```{rust} -let mut x = 5i; // mut x: int -x = 10i; +let mut x = 5; // mut x: i32 +x = 10; ``` There is no single reason that bindings are immutable by default, but we can @@ -488,14 +486,14 @@ src/main.rs:2 let x; Giving it a type will compile, though: ```{rust} -let x: int; +let x: i32; ``` Let's try it out. Change your `src/main.rs` file to look like this: ```{rust} fn main() { - let x: int; + let x: i32; println!("Hello world!"); } @@ -507,7 +505,7 @@ but it will still print "Hello, world!": ```text Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world) src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default -src/main.rs:2 let x: int; +src/main.rs:2 let x: i32; ^ ``` @@ -517,7 +515,7 @@ do that. Change your program to look like this: ```{rust,ignore} fn main() { - let x: int; + let x: i32; println!("The value of x is: {}", x); } @@ -568,9 +566,9 @@ multiple paths can be taken. In the case of `if`, there is one choice that leads down two paths: ```rust -let x = 5i; +let x = 5; -if x == 5i { +if x == 5 { println!("x is five!"); } ``` @@ -582,9 +580,9 @@ the block is executed. If it's `false`, then it is not. If you want something to happen in the `false` case, use an `else`: ```{rust} -let x = 5i; +let x = 5; -if x == 5i { +if x == 5 { println!("x is five!"); } else { println!("x is not five :("); @@ -595,21 +593,21 @@ This is all pretty standard. However, you can also do this: ```{rust} -let x = 5i; +let x = 5; -let y = if x == 5i { - 10i +let y = if x == 5 { + 10 } else { - 15i -}; // y: int + 15 +}; // y: i32 ``` Which we can (and probably should) write like this: ```{rust} -let x = 5i; +let x = 5; -let y = if x == 5i { 10i } else { 15i }; // y: int +let y = if x == 5 { 10 } else { 15 }; // y: i32 ``` This reveals two interesting things about Rust: it is an expression-based @@ -641,15 +639,15 @@ In Rust, however, using `let` to introduce a binding is _not_ an expression. The following will produce a compile-time error: ```{ignore} -let x = (let y = 5i); // expected identifier, found keyword `let` +let x = (let y = 5); // expected identifier, found keyword `let` ``` The compiler is telling us here that it was expecting to see the beginning of an expression, and a `let` can only begin a statement, not an expression. -Note that assigning to an already-bound variable (e.g. `y = 5i`) is still an +Note that assigning to an already-bound variable (e.g. `y = 5`) is still an expression, although its value is not particularly useful. Unlike C, where an -assignment evaluates to the assigned value (e.g. `5i` in the previous example), +assignment evaluates to the assigned value (e.g. `5` in the previous example), in Rust the value of an assignment is the unit type `()` (which we'll cover later). The second kind of statement in Rust is the **expression statement**. Its @@ -664,9 +662,9 @@ What is this exception that makes us say 'almost?' You saw it already, in this code: ```{rust} -let x = 5i; +let x = 5; -let y: int = if x == 5i { 10i } else { 15i }; +let y: i32 = if x == 5 { 10 } else { 15 }; ``` Note that I've added the type annotation to `y`, to specify explicitly that I @@ -675,20 +673,20 @@ want `y` to be an integer. This is not the same as this, which won't compile: ```{ignore} -let x = 5i; +let x = 5; -let y: int = if x == 5i { 10i; } else { 15i; }; +let y: i32 = if x == 5 { 10; } else { 15; }; ``` Note the semicolons after the 10 and 15. Rust will give us the following error: ```text -error: mismatched types: expected `int` but found `()` (expected int but found ()) +error: mismatched types: expected `i32` but found `()` (expected i32 but found ()) ``` We expected an integer, but we got `()`. `()` is pronounced 'unit', and is a special type in Rust's type system. In Rust, `()` is _not_ a valid value for a -variable of type `int`. It's only a valid value for variables of the type `()`, +variable of type `i32`. It's only a valid value for variables of the type `()`, which aren't very useful. Remember how we said statements don't return a value? Well, that's the purpose of unit in this case. The semicolon turns any expression into a statement by throwing away its value and returning unit @@ -719,7 +717,7 @@ fn foo() { So, what about taking arguments? Here's a function that prints a number: ```{rust} -fn print_number(x: int) { +fn print_number(x: i32) { println!("x is: {}", x); } ``` @@ -731,7 +729,7 @@ fn main() { print_number(5); } -fn print_number(x: int) { +fn print_number(x: i32) { println!("x is: {}", x); } ``` @@ -746,7 +744,7 @@ fn main() { print_sum(5, 6); } -fn print_sum(x: int, y: int) { +fn print_sum(x: i32, y: i32) { println!("sum is: {}", x + y); } ``` @@ -779,7 +777,7 @@ sweet spot between full inference and no inference. What about returning a value? Here's a function that adds one to an integer: ```{rust} -fn add_one(x: int) -> int { +fn add_one(x: i32) -> i32 { x + 1 } ``` @@ -790,7 +788,7 @@ Rust functions return exactly one value, and you declare the type after an You'll note the lack of a semicolon here. If we added it in: ```{ignore} -fn add_one(x: int) -> int { +fn add_one(x: i32) -> i32 { x + 1; } ``` @@ -799,7 +797,7 @@ We would get an error: ```text error: not all control paths return a value -fn add_one(x: int) -> int { +fn add_one(x: i32) -> i32 { x + 1; } @@ -809,7 +807,7 @@ help: consider removing this semicolon: ``` Remember our earlier discussions about semicolons and `()`? Our function claims -to return an `int`, but with a semicolon, it would return `()` instead. Rust +to return an `i32`, but with a semicolon, it would return `()` instead. Rust realizes this probably isn't what we want, and suggests removing the semicolon. This is very much like our `if` statement before: the result of the block @@ -823,7 +821,7 @@ semicolon in a return position would cause a bug. But what about early returns? Rust does have a keyword for that, `return`: ```{rust} -fn foo(x: int) -> int { +fn foo(x: i32) -> i32 { if x < 5 { return x; } x + 1 @@ -834,7 +832,7 @@ Using a `return` as the last line of a function works, but is considered poor style: ```{rust} -fn foo(x: int) -> int { +fn foo(x: i32) -> i32 { if x < 5 { return x; } return x + 1; @@ -857,7 +855,7 @@ and **doc comment**s. ```{rust} // Line comments are anything after '//' and extend to the end of the line. -let x = 5i; // this is also a line comment. +let x = 5; // this is also a line comment. // If you have a long explanation for something, you can put line comments next // to each other. Put a space between the // and your comment so that it's @@ -904,19 +902,19 @@ The first compound data type we're going to talk about are called **tuple**s. Tuples are an ordered list of a fixed size. Like this: ```rust -let x = (1i, "hello"); +let x = (1, "hello"); ``` The parentheses and commas form this two-length tuple. Here's the same code, but with the type annotated: ```rust -let x: (int, &str) = (1, "hello"); +let x: (i32, &str) = (1, "hello"); ``` As you can see, the type of a tuple looks just like the tuple, but with each position having a type name rather than the value. Careful readers will also -note that tuples are heterogeneous: we have an `int` and a `&str` in this tuple. +note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple. You haven't seen `&str` as a type before, and we'll discuss the details of strings later. In systems programming languages, strings are a bit more complex than in other languages. For now, just read `&str` as "a string slice," and @@ -926,7 +924,7 @@ You can access the fields in a tuple through a **destructuring let**. Here's an example: ```rust -let (x, y, z) = (1i, 2i, 3i); +let (x, y, z) = (1, 2, 3); println!("x is {}", x); ``` @@ -944,8 +942,8 @@ destructuring. You can assign one tuple into another, if they have the same arity and contained types. ```rust -let mut x = (1i, 2i); // x: (int, int) -let y = (2i, 3i); // y: (int, int) +let mut x = (1, 2); // x: (i32, i32) +let y = (2, 3); // y: (i32, i32) x = y; ``` @@ -954,8 +952,8 @@ You can also check for equality with `==`. Again, this will only compile if the tuples have the same type. ```rust -let x = (1i, 2i, 3i); -let y = (2i, 2i, 4i); +let x = (1, 2, 3); +let y = (2, 2, 4); if x == y { println!("yes"); @@ -969,10 +967,10 @@ This will print `no`, because some of the values aren't equal. One other use of tuples is to return multiple values from a function: ```rust -fn next_two(x: int) -> (int, int) { (x + 1i, x + 2i) } +fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) } fn main() { - let (x, y) = next_two(5i); + let (x, y) = next_two(5); println!("x, y = {}, {}", x, y); } ``` @@ -992,12 +990,12 @@ difference: structs give each element that they contain a name, called a ```rust struct Point { - x: int, - y: int, + x: i32, + y: i32, } fn main() { - let origin = Point { x: 0i, y: 0i }; // origin: Point + let origin = Point { x: 0, y: 0 }; // origin: Point println!("The origin is at ({}, {})", origin.x, origin.y); } @@ -1019,12 +1017,12 @@ Use `mut` to make them mutable: ```{rust} struct Point { - x: int, - y: int, + x: i32, + y: i32, } fn main() { - let mut point = Point { x: 0i, y: 0i }; + let mut point = Point { x: 0, y: 0 }; point.x = 5; @@ -1042,15 +1040,15 @@ don't: ```{rust} -struct Color(int, int, int); -struct Point(int, int, int); +struct Color(i32, i32, i32); +struct Point(i32, i32, i32); ``` These two will not be equal, even if they have the same values: ```{rust} -# struct Color(int, int, int); -# struct Point(int, int, int); +# struct Color(i32, i32, i32); +# struct Point(i32, i32, i32); let black = Color(0, 0, 0); let origin = Point(0, 0, 0); ``` @@ -1060,15 +1058,15 @@ It is almost always better to use a struct than a tuple struct. We would write ```{rust} struct Color { - red: int, - blue: int, - green: int, + red: i32, + blue: i32, + green: i32, } struct Point { - x: int, - y: int, - z: int, + x: i32, + y: i32, + z: i32, } ``` @@ -1080,7 +1078,7 @@ tuple struct with only one element. We call this a 'newtype,' because it lets you create a new type that's a synonym for another one: ```{rust} -struct Inches(int); +struct Inches(i32); let length = Inches(10); @@ -1117,15 +1115,15 @@ Here's an example of how to use `Ordering`: ```{rust} use std::cmp::Ordering; -fn cmp(a: int, b: int) -> Ordering { +fn cmp(a: i32, b: i32) -> Ordering { if a < b { Ordering::Less } else if a > b { Ordering::Greater } else { Ordering::Equal } } fn main() { - let x = 5i; - let y = 10i; + let x = 5; + let y = 10; let ordering = cmp(x, y); // ordering: Ordering @@ -1163,21 +1161,21 @@ This enum has two variants, one of which has a value: ```{rust} enum OptionalInt { - Value(int), + Value(i32), Missing, } ``` -This enum represents an `int` that we may or may not have. In the `Missing` +This enum represents an `i32` that we may or may not have. In the `Missing` case, we have no value, but in the `Value` case, we do. This enum is specific -to `int`s, though. We can make it usable by any type, but we haven't quite +to `i32`s, though. We can make it usable by any type, but we haven't quite gotten there yet! You can also have any number of values in an enum: ```{rust} enum OptionalColor { - Color(int, int, int), + Color(i32, i32, i32), Missing, } ``` @@ -1256,7 +1254,7 @@ Rust has a keyword, `match`, that allows you to replace complicated `if`/`else` groupings with something more powerful. Check it out: ```{rust} -let x = 5i; +let x = 5; match x { 1 => println!("one"), @@ -1283,7 +1281,7 @@ error: non-exhaustive patterns: `_` not covered In other words, Rust is trying to tell us we forgot a value. Because `x` is an integer, Rust knows that it can have a number of different values – for example, -`6i`. Without the `_`, however, there is no arm that could match, and so Rust refuses +`6`. Without the `_`, however, there is no arm that could match, and so Rust refuses to compile. `_` acts like a 'catch-all arm'. If none of the other arms match, the arm with `_` will, and since we have this catch-all arm, we now have an arm for every possible value of `x`, and so our program will compile successfully. @@ -1294,15 +1292,15 @@ section on enums? ```{rust} use std::cmp::Ordering; -fn cmp(a: int, b: int) -> Ordering { +fn cmp(a: i32, b: i32) -> Ordering { if a < b { Ordering::Less } else if a > b { Ordering::Greater } else { Ordering::Equal } } fn main() { - let x = 5i; - let y = 10i; + let x = 5; + let y = 10; let ordering = cmp(x, y); @@ -1321,15 +1319,15 @@ We can re-write this as a `match`: ```{rust} use std::cmp::Ordering; -fn cmp(a: int, b: int) -> Ordering { +fn cmp(a: i32, b: i32) -> Ordering { if a < b { Ordering::Less } else if a > b { Ordering::Greater } else { Ordering::Equal } } fn main() { - let x = 5i; - let y = 10i; + let x = 5; + let y = 10; match cmp(x, y) { Ordering::Less => println!("less"), @@ -1350,7 +1348,7 @@ make sure to cover all of our bases. ```{rust} enum OptionalInt { - Value(int), + Value(i32), Missing, } @@ -1372,7 +1370,7 @@ fn main() { That is how you can get and use the values contained in `enum`s. It can also allow us to handle errors or unexpected computations; for example, a -function that is not guaranteed to be able to compute a result (an `int` here) +function that is not guaranteed to be able to compute a result (an `i32` here) could return an `OptionalInt`, and we would handle that value with a `match`. As you can see, `enum` and `match` used together are quite useful! @@ -1383,15 +1381,15 @@ also implement the previous line like this: ```{rust} use std::cmp::Ordering; -fn cmp(a: int, b: int) -> Ordering { +fn cmp(a: i32, b: i32) -> Ordering { if a < b { Ordering::Less } else if a > b { Ordering::Greater } else { Ordering::Equal } } fn main() { - let x = 5i; - let y = 10i; + let x = 5; + let y = 10; println!("{}", match cmp(x, y) { Ordering::Less => "less", @@ -1423,8 +1421,8 @@ for (x = 0; x < 10; x++) { Instead, it looks like this: ```{rust} -for x in range(0i, 10i) { - println!("{}", x); // x: int +for x in range(0, 10) { + println!("{}", x); // x: i32 } ``` @@ -1528,7 +1526,7 @@ We now loop forever with `loop` and use `break` to break out early. iteration. This will only print the odd numbers: ```{rust} -for x in range(0i, 10i) { +for x in range(0, 10) { if x % 2 == 0 { continue; } println!("{}", x); @@ -1624,15 +1622,15 @@ things. The most basic is the **array**, a fixed-size list of elements of the same type. By default, arrays are immutable. ```{rust} -let a = [1i, 2i, 3i]; // a: [int; 3] -let mut m = [1i, 2i, 3i]; // mut m: [int; 3] +let a = [1, 2, 3]; // a: [i32; 3] +let mut m = [1, 2, 3]; // mut m: [i32; 3] ``` There's a shorthand for initializing each element of an array to the same -value. In this example, each element of `a` will be initialized to `0i`: +value. In this example, each element of `a` will be initialized to `0`: ```{rust} -let a = [0i; 20]; // a: [int; 20] +let a = [0; 20]; // a: [i32; 20] ``` Arrays have type `[T; N]`. We'll talk about this `T` notation later, when we @@ -1643,7 +1641,7 @@ You can get the number of elements in an array `a` with `a.len()`, and use number in order: ```{rust} -let a = [1i, 2, 3]; // Only the first item needs a type suffix +let a = [1, 2, 3]; println!("a has {} elements", a.len()); for e in a.iter() { @@ -1672,7 +1670,7 @@ later). Vectors are to arrays what `String` is to `&str`. You can create them with the `vec!` macro: ```{rust} -let v = vec![1i, 2, 3]; // v: Vec +let v = vec![1, 2, 3]; // v: Vec ``` (Notice that unlike the `println!` macro we've used in the past, we use square @@ -1683,7 +1681,7 @@ You can get the length of, iterate over, and subscript vectors just like arrays. In addition, (mutable) vectors can grow automatically: ```{rust} -let mut nums = vec![1i, 2, 3]; // mut nums: Vec +let mut nums = vec![1, 2, 3]; // mut nums: Vec nums.push(4); @@ -1700,7 +1698,7 @@ Slices have a length, can be mutable or not, and in many ways behave like arrays: ```{rust} -let a = [0i, 1, 2, 3, 4]; +let a = [0, 1, 2, 3, 4]; let middle = a.slice(1, 4); // A slice of a: just the elements [1,2,3] for e in middle.iter() { @@ -1792,7 +1790,7 @@ Do you remember this code? ```{rust} enum OptionalInt { - Value(int), + Value(i32), Missing, } @@ -1824,7 +1822,7 @@ where there's no standard input. Because of this, `read_line` returns a type very similar to our `OptionalInt`: an `IoResult`. We haven't talked about `IoResult` yet because it is the **generic** form of our `OptionalInt`. Until then, you can think of it as being the same thing, just for any type – -not just `int`s. +not just `i32`s. Rust provides a method on these `IoResult`s called `ok()`, which does the same thing as our `match` statement but assumes that we have a valid value. @@ -2006,7 +2004,7 @@ use std::rand; fn main() { println!("Guess the number!"); - let secret_number = (rand::random() % 100i) + 1i; // secret_number: int + let secret_number = (rand::random() % 100) + 1; // secret_number: i32 println!("The secret number is: {}", secret_number); @@ -2038,7 +2036,7 @@ Let's try to compile this using `cargo build`: $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) src/main.rs:7:26: 7:34 error: the type of this value must be known in this context -src/main.rs:7 let secret_number = (rand::random() % 100i) + 1i; +src/main.rs:7 let secret_number = (rand::random() % 100) + 1; ^~~~~~~~ error: aborting due to previous error ``` @@ -2047,15 +2045,15 @@ It didn't work! Rust says "the type of this value must be known in this context." What's up with that? Well, as it turns out, `rand::random()` can generate many kinds of random values, not just integers. And in this case, Rust isn't sure what kind of value `random()` should generate. So we have to help -it. With number literals, we just add an `i` onto the end to tell Rust they're +it. With number literals, we can just add an `i32` onto the end to tell Rust they're integers, but that does not work with functions. There's a different syntax, and it looks like this: ```{rust,ignore} -rand::random::(); +rand::random::(); ``` -This says "please give me a random `int` value." We can change our code to use +This says "please give me a random `i32` value." We can change our code to use this hint: ```{rust,no_run} @@ -2065,7 +2063,7 @@ use std::rand; fn main() { println!("Guess the number!"); - let secret_number = (rand::random::() % 100i) + 1i; + let secret_number = (rand::random::() % 100) + 1; println!("The secret number is: {}", secret_number); @@ -2182,7 +2180,7 @@ fn main() { } } -fn cmp(a: int, b: int) -> Ordering { +fn cmp(a: i32, b: i32) -> Ordering { if a < b { Ordering::Less } else if a > b { Ordering::Greater } else { Ordering::Equal } @@ -2194,10 +2192,10 @@ If we try to compile, we'll get some errors: ```bash $ cargo build Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game) -src/main.rs:20:15: 20:20 error: mismatched types: expected `int` but found `collections::string::String` (expected int but found struct collections::string::String) +src/main.rs:20:15: 20:20 error: mismatched types: expected `i32` but found `collections::string::String` (expected i32 but found struct collections::string::String) src/main.rs:20 match cmp(input, secret_number) { ^~~~~ -src/main.rs:20:22: 20:35 error: mismatched types: expected `int` but found `uint` (expected int but found uint) +src/main.rs:20:22: 20:35 error: mismatched types: expected `i32` but found `uint` (expected i32 but found uint) src/main.rs:20 match cmp(input, secret_number) { ^~~~~~~~~~~~~ error: aborting due to 2 previous errors @@ -2906,7 +2904,7 @@ Here's a very basic test: ```{rust} #[test] fn is_one_equal_to_one() { - assert_eq!(1i, 1i); + assert_eq!(1, 1); } ``` @@ -3207,9 +3205,9 @@ to look like this: ```{rust,ignore} #[test] fn math_checks_out() { - let result = add_three_times_four(5i); + let result = add_three_times_four(5); - assert_eq!(32i, result); + assert_eq!(32, result); } ``` @@ -3219,7 +3217,7 @@ And try to run the test: $ cargo test Compiling testing v0.0.1 (file:///home/you/projects/testing) /home/you/projects/testing/tests/lib.rs:3:18: 3:38 error: unresolved name `add_three_times_four`. -/home/you/projects/testing/tests/lib.rs:3 let result = add_three_times_four(5i); +/home/you/projects/testing/tests/lib.rs:3 let result = add_three_times_four(5); ^~~~~~~~~~~~~~~~~~~~ error: aborting due to previous error Build failed, waiting for other jobs to finish... @@ -3240,7 +3238,7 @@ and put this in it: ```{rust} # fn main() {} -pub fn add_three_times_four(x: int) -> int { +pub fn add_three_times_four(x: i32) -> i32 { (x + 3) * 4 } ``` @@ -3267,9 +3265,9 @@ use testing::add_three_times_four; #[test] fn math_checks_out() { - let result = add_three_times_four(5i); + let result = add_three_times_four(5); - assert_eq!(32i, result); + assert_eq!(32, result); } ``` @@ -3313,13 +3311,13 @@ some unit tests to test those. Change your `src/lib.rs` to look like this: ```{rust,ignore} -pub fn add_three_times_four(x: int) -> int { +pub fn add_three_times_four(x: i32) -> i32 { times_four(add_three(x)) } -fn add_three(x: int) -> int { x + 3 } +fn add_three(x: i32) -> i32 { x + 3 } -fn times_four(x: int) -> int { x * 4 } +fn times_four(x: i32) -> i32 { x * 4 } ``` If you run `cargo test`, you should get the same output: @@ -3363,16 +3361,16 @@ use testing::add_three; #[test] fn math_checks_out() { - let result = add_three_times_four(5i); + let result = add_three_times_four(5); - assert_eq!(32i, result); + assert_eq!(32, result); } #[test] fn test_add_three() { - let result = add_three(5i); + let result = add_three(5); - assert_eq!(8i, result); + assert_eq!(8, result); } ``` @@ -3389,13 +3387,13 @@ Right. It's private. So external, integration tests won't work. We need a unit test. Open up your `src/lib.rs` and add this: ```{rust,ignore} -pub fn add_three_times_four(x: int) -> int { +pub fn add_three_times_four(x: i32) -> i32 { times_four(add_three(x)) } -fn add_three(x: int) -> int { x + 3 } +fn add_three(x: i32) -> i32 { x + 3 } -fn times_four(x: int) -> int { x * 4 } +fn times_four(x: i32) -> i32 { x * 4 } #[cfg(test)] mod test { @@ -3404,16 +3402,16 @@ mod test { #[test] fn test_add_three() { - let result = add_three(5i); + let result = add_three(5); - assert_eq!(8i, result); + assert_eq!(8, result); } #[test] fn test_times_four() { - let result = times_four(5i); + let result = times_four(5); - assert_eq!(20i, result); + assert_eq!(20, result); } } ``` @@ -3495,7 +3493,7 @@ References are created using the ampersand (`&`). Here's a simple reference: ```{rust} -let x = 5i; +let x = 5; let y = &x; ``` @@ -3503,10 +3501,10 @@ let y = &x; rather than the reference itself) `y`, we use the asterisk (`*`): ```{rust} -let x = 5i; +let x = 5; let y = &x; -assert_eq!(5i, *y); +assert_eq!(5, *y); ``` Like any `let` binding, references are immutable by default. @@ -3514,7 +3512,7 @@ Like any `let` binding, references are immutable by default. You can declare that functions take a reference: ```{rust} -fn add_one(x: &int) -> int { *x + 1 } +fn add_one(x: &i32) -> i32 { *x + 1 } fn main() { assert_eq!(6, add_one(&5)); @@ -3529,7 +3527,7 @@ Because references are immutable, you can have multiple references that **alias** (point to the same place): ```{rust} -let x = 5i; +let x = 5; let y = &x; let z = &x; ``` @@ -3537,14 +3535,14 @@ let z = &x; We can make a mutable reference by using `&mut` instead of `&`: ```{rust} -let mut x = 5i; +let mut x = 5; let y = &mut x; ``` Note that `x` must also be mutable. If it isn't, like this: ```{rust,ignore} -let x = 5i; +let x = 5; let y = &mut x; ``` @@ -3570,7 +3568,7 @@ Rust will also prevent us from creating two mutable references that alias. This won't work: ```{rust,ignore} -let mut x = 5i; +let mut x = 5; let y = &mut x; let z = &mut x; ``` @@ -3586,7 +3584,7 @@ note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent ^ note: previous borrow ends here fn main() { - let mut x = 5i; + let mut x = 5; let y = &mut x; let z = &mut x; } @@ -3667,7 +3665,7 @@ all of Rust. Let's see this syntax in action: ```{rust} { - let x = 5i; // x is the owner of this integer, which is memory on the stack. + let x = 5; // x is the owner of this integer, which is memory on the stack. // other code here... @@ -3675,11 +3673,11 @@ all of Rust. Let's see this syntax in action: /// this function borrows an integer. It's given back automatically when the /// function returns. -fn foo(x: &int) -> &int { x } +fn foo(x: &i32) -> &i32 { x } { // x is the owner of the integer, which is memory on the stack. - let x = 5i; + let x = 5; // privilege 2: you may lend that resource to as many borrowers as you like let y = &x; @@ -3692,7 +3690,7 @@ fn foo(x: &int) -> &int { x } { // x is the owner of this integer, which is memory on the stack. - let mut x = 5i; + let mut x = 5; // privilege 3: you may lend that resource to a single borrower, mutably let y = &mut x; @@ -3718,7 +3716,7 @@ violation of the restrictions placed on owners who lend something out mutably. The code: ```{rust,ignore} -let mut x = 5i; +let mut x = 5; let y = &mut x; let z = &mut x; ``` @@ -3734,7 +3732,7 @@ note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent ^ note: previous borrow ends here fn main() { - let mut x = 5i; + let mut x = 5; let y = &mut x; let z = &mut x; } @@ -3767,7 +3765,7 @@ we can't change `x` until the borrow is over. ```text note: previous borrow ends here fn main() { - let mut x = 5i; + let mut x = 5; let y = &mut x; let z = &mut x; } @@ -3828,7 +3826,7 @@ an integer `5` and makes `x` a pointer to it: ```{rust} { - let x = box 5i; + let x = box 5; println!("{}", *x); // Prints 5 } ``` @@ -3844,7 +3842,7 @@ The Rust code above will do the same thing as the following C code: ```{c,ignore} { - int *x = (int *)malloc(sizeof(int)); + i32 *x = (i32 *)malloc(sizeof(i32)); if (!x) abort(); *x = 5; printf("%d\n", *x); @@ -3859,7 +3857,7 @@ Boxes are the sole owner of their contents, so you cannot take a mutable reference to them and then use the original box: ```{rust,ignore} -let mut x = box 5i; +let mut x = box 5; let y = &mut x; *x; // you might expect 5, but this is actually an error @@ -3880,7 +3878,7 @@ As long as `y` is borrowing the contents, we cannot use `x`. After `y` is done borrowing the value, we can use it again. This works fine: ```{rust} -let mut x = box 5i; +let mut x = box 5; { let y = &mut x; @@ -3915,7 +3913,7 @@ To create an `Rc` value, use `Rc::new()`. To create a second owner, use the ```{rust} use std::rc::Rc; -let x = Rc::new(5i); +let x = Rc::new(5); let y = x.clone(); println!("{} {}", *x, *y); // Prints 5 5 @@ -3944,7 +3942,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"), @@ -3957,7 +3955,7 @@ match x { You can match multiple patterns with `|`: ```{rust} -let x = 1i; +let x = 1; match x { 1 | 2 => println!("one or two"), @@ -3969,7 +3967,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"), @@ -3983,7 +3981,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), @@ -3996,14 +3994,14 @@ 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!"), + OptionalInt::Value(..) => println!("Got an i32!"), OptionalInt::Missing => println!("No such luck."), } ``` @@ -4012,15 +4010,15 @@ 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!"), - OptionalInt::Value(..) => println!("Got an int!"), + OptionalInt::Value(i) if i > 5 => println!("Got an i32 bigger than five!"), + OptionalInt::Value(..) => println!("Got an i32!"), OptionalInt::Missing => println!("No such luck."), } ``` @@ -4029,33 +4027,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), @@ -4067,11 +4065,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), @@ -4083,11 +4081,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), @@ -4099,11 +4097,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), @@ -4233,9 +4231,9 @@ arguments, really powerful things are possible. Let's make a closure: ```{rust} -let add_one = |x| { 1i + x }; +let add_one = |x| { 1 + x }; -println!("The sum of 5 plus 1 is {}.", add_one(5i)); +println!("The sum of 5 plus 1 is {}.", add_one(5)); ``` We create a closure using the `|...| { ... }` syntax, and then we create a @@ -4245,8 +4243,8 @@ binding name and two parentheses, just like we would for a named function. Let's compare syntax. The two are pretty close: ```{rust} -let add_one = |x: int| -> int { 1i + x }; -fn add_one (x: int) -> int { 1i + x } +let add_one = |x: i32| -> i32 { 1 + x }; +fn add_one (x: i32) -> i32 { 1 + x } ``` As you may have noticed, closures infer their argument and return types, so you @@ -4259,7 +4257,7 @@ this: ```{rust} fn main() { - let x = 5i; + let x = 5; let printer = || { println!("x is: {}", x); }; @@ -4275,11 +4273,11 @@ defined. The closure borrows any variables it uses, so this will error: ```{rust,ignore} fn main() { - let mut x = 5i; + let mut x = 5; let printer = || { println!("x is: {}", x); }; - x = 6i; // error: cannot assign to `x` because it is borrowed + x = 6; // error: cannot assign to `x` because it is borrowed } ``` @@ -4299,67 +4297,67 @@ now. We'll talk about them more in the "Threads" section of the guide. Closures are most useful as an argument to another function. Here's an example: ```{rust} -fn twice(x: int, f: |int| -> int) -> int { +fn twice(x: i32, f: |i32| -> i32) -> i32 { f(x) + f(x) } fn main() { - let square = |x: int| { x * x }; + let square = |x: i32| { x * x }; - twice(5i, square); // evaluates to 50 + twice(5, square); // evaluates to 50 } ``` Let's break the example down, starting with `main`: ```{rust} -let square = |x: int| { x * x }; +let square = |x: i32| { x * x }; ``` We've seen this before. We make a closure that takes an integer, and returns its square. ```{rust} -# fn twice(x: int, f: |int| -> int) -> int { f(x) + f(x) } -# let square = |x: int| { x * x }; -twice(5i, square); // evaluates to 50 +# fn twice(x: i32, f: |i32| -> i32) -> i32 { f(x) + f(x) } +# let square = |x: i32| { x * x }; +twice(5, square); // evaluates to 50 ``` This line is more interesting. Here, we call our function, `twice`, and we pass it two arguments: an integer, `5`, and our closure, `square`. This is just like passing any other two variable bindings to a function, but if you've never worked with closures before, it can seem a little complex. Just think: "I'm -passing two variables: one is an int, and one is a function." +passing two variables: one is an i32, and one is a function." Next, let's look at how `twice` is defined: ```{rust,ignore} -fn twice(x: int, f: |int| -> int) -> int { +fn twice(x: i32, f: |i32| -> i32) -> i32 { ``` `twice` takes two arguments, `x` and `f`. That's why we called it with two -arguments. `x` is an `int`, we've done that a ton of times. `f` is a function, -though, and that function takes an `int` and returns an `int`. Notice -how the `|int| -> int` syntax looks a lot like our definition of `square` +arguments. `x` is an `i32`, we've done that a ton of times. `f` is a function, +though, and that function takes an `i32` and returns an `i32`. Notice +how the `|i32| -> i32` syntax looks a lot like our definition of `square` above, if we added the return type in: ```{rust} -let square = |x: int| -> int { x * x }; -// |int| -> int +let square = |x: i32| -> i32 { x * x }; +// |i32| -> i32 ``` -This function takes an `int` and returns an `int`. +This function takes an `i32` and returns an `i32`. This is the most complicated function signature we've seen yet! Give it a read a few times until you can see how it works. It takes a teeny bit of practice, and then it's easy. -Finally, `twice` returns an `int` as well. +Finally, `twice` returns an `i32` as well. Okay, let's look at the body of `twice`: ```{rust} -fn twice(x: int, f: |int| -> int) -> int { +fn twice(x: i32, f: |i32| -> i32) -> i32 { f(x) + f(x) } ``` @@ -4377,12 +4375,12 @@ 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} -fn twice(x: int, f: |int| -> int) -> int { +fn twice(x: i32, f: |i32| -> i32) -> i32 { f(x) + f(x) } fn main() { - twice(5i, |x: int| { x * x }); // evaluates to 50 + twice(5, |x: i32| { x * x }); // evaluates to 50 } ``` @@ -4390,14 +4388,14 @@ A named function's name can be used wherever you'd use a closure. Another way of writing the previous example: ```{rust} -fn twice(x: int, f: |int| -> int) -> int { +fn twice(x: i32, f: |i32| -> i32) -> i32 { f(x) + f(x) } -fn square(x: int) -> int { x * x } +fn square(x: i32) -> i32 { x * x } fn main() { - twice(5i, square); // evaluates to 50 + twice(5, square); // evaluates to 50 } ``` @@ -4415,7 +4413,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); } ``` @@ -4427,7 +4425,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() { @@ -4442,8 +4440,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`, 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`, 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` @@ -4460,7 +4458,7 @@ 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()) { println!("{}", nums[i]); @@ -4472,7 +4470,7 @@ vectors returns an iterator that 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); @@ -4489,12 +4487,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); @@ -4528,7 +4526,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 @@ -4538,7 +4536,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::>(); +let one_to_one_hundred = range(1, 101).collect::>(); ``` If you remember, the `::<>` syntax allows us to give a type hint, @@ -4548,7 +4546,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 { @@ -4565,8 +4563,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: @@ -4582,24 +4580,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 @@ -4620,14 +4618,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::>(); +let nums = range(1, 100).collect::>(); ``` Now, `collect()` will require that `range()` give it some numbers, and so @@ -4638,7 +4636,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); @@ -4649,12 +4647,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 @@ -4666,7 +4664,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 @@ -4677,7 +4675,7 @@ compile the example, you'll get a warning: ```text 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); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` @@ -4685,7 +4683,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, @@ -4697,7 +4695,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); } ``` @@ -4717,7 +4715,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); } ``` @@ -4732,11 +4730,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::>(); + .collect::>(); ``` This will give you a vector containing `6`, `12`, `18`, `24`, and `30`. @@ -4755,7 +4753,7 @@ multiple types of arguments. For example, remember our `OptionalInt` type? ```{rust} enum OptionalInt { - Value(int), + Value(i32), Missing, } ``` @@ -4788,30 +4786,30 @@ The `` part, which you've seen a few times before, indicates that this is a generic data type. `T` is called a **type parameter**. When we create instances of `Option`, we need to provide a concrete type in place of the type parameter. For example, if we wanted something like our `OptionalInt`, we would -need to instantiate an `Option`. Inside the declaration of our enum, +need to instantiate an `Option`. Inside the declaration of our enum, wherever we see a `T`, we replace it with the type specified (or inferred by the the compiler). ```{rust} -let x: Option = Some(5i); +let x: Option = Some(5); ``` -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 match, we'd get an +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 = Some(5i); +let x: Option = Some(5); // error: mismatched types: expected `core::option::Option`, -// found `core::option::Option` (expected f64, found int) +// found `core::option::Option` (expected f64, found i32) ``` That doesn't mean we can't make `Option`s that hold an `f64`! They just have to match up: ```{rust} -let x: Option = Some(5i); +let x: Option = Some(5); let y: Option = Some(5.0f64); ``` @@ -5084,25 +5082,25 @@ 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: ```text -error: failed to find an implementation of trait main::HasArea for int +error: failed to find an implementation of trait main::HasArea for i32 ``` 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"); @@ -5110,7 +5108,7 @@ impl HasArea for int { } } -5i.area(); +5.area(); ``` It is considered poor style to implement methods on such primitive types, even @@ -5166,7 +5164,7 @@ fn main() { ``` Requiring us to `use` traits whose methods we want means that even if someone -does something bad like add methods to `int`, it won't affect us, unless you +does something bad like add methods to `i32`, it won't affect us, unless you `use` that trait. The second condition allows us to `impl` built-in `trait`s for types we define, @@ -5174,9 +5172,9 @@ or allows us to `impl` our own `trait`s for built-in types, but restricts us from mixing and matching third party or built-in `impl`s with third party or built-in types. -We could `impl` the `HasArea` trait for `int`, because `HasArea` is in our +We could `impl` the `HasArea` trait for `i32`, because `HasArea` is in our crate. But if we tried to implement `Float`, a standard library `trait`, for -`int`, we could not, because neither the `trait` nor the `type` are in our +`i32`, we could not, because neither the `trait` nor the `type` are in our crate. ## Monomorphization @@ -5259,7 +5257,7 @@ touches. This implies that those variables are not usable from the parent thread after the child thread is spawned: ```{rust,ignore} -let mut x = vec![1i, 2i, 3i]; +let mut x = vec![1, 2, 3]; spawn(move || { println!("The value of x[0] is: {}", x[0]); @@ -5333,7 +5331,7 @@ use std::sync::Future; let mut delayed_value = Future::spawn(move || { // just return anything for examples' sake - 12345i + 12345 }); println!("value = {}", delayed_value.get()); ``` @@ -5401,7 +5399,7 @@ a function, but it would be worse. Why? Well, what macros allow you to do is write code that generates more code. So when we call `println!` like this: ```{rust} -let x = 5i; +let x = 5; println!("x is: {}", x); ``` @@ -5421,7 +5419,7 @@ called `print.rs`: ```{rust} fn main() { - let x = 5i; + let x = 5; println!("x is: {}", x); } ``` @@ -5439,7 +5437,7 @@ extern crate "native" as rt; #[prelude_import] use std::prelude::*; fn main() { - let x = 5i; + let x = 5; match (&x,) { (__arg0,) => { #[inline] @@ -5457,7 +5455,7 @@ fn main() { } ``` -Whew! This isn't too terrible. You can see that we still `let x = 5i`, +Whew! This isn't too terrible. You can see that we still `let x = 5`, but then things get a little bit hairy. Three more bindings get set: a static format string, an argument vector, and the arguments. We then invoke the `println_args` function with the generated arguments.