mirror of
https://github.com/rust-lang-cn/book-cn.git
synced 2025-02-02 23:38:41 +08:00
Change to not have parens in function names in prose
Unless we're quoting a line of code that actually does call the function. But when we're talking about the definition, don't include the parens.
This commit is contained in:
parent
468e5cc202
commit
6d617aba2a
@ -88,7 +88,7 @@ requires these around all function bodies. It's considered good style to put
|
|||||||
the opening curly brace on the same line as the function declaration, with one
|
the opening curly brace on the same line as the function declaration, with one
|
||||||
space in between.
|
space in between.
|
||||||
|
|
||||||
Inside the `main()` function:
|
Inside the `main` function:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
println!("Hello, world!");
|
println!("Hello, world!");
|
||||||
@ -98,15 +98,15 @@ This line does all of the work in this little program: it prints text to the
|
|||||||
screen. There are a number of details that are important here. The first is
|
screen. There are a number of details that are important here. The first is
|
||||||
that it’s indented with four spaces, not a tab.
|
that it’s indented with four spaces, not a tab.
|
||||||
|
|
||||||
The second important part is `println!()`. This is calling a Rust *macro*,
|
The second important part is `println!`. This is calling a Rust *macro*,
|
||||||
which is how metaprogramming is done in Rust. If it were calling a function
|
which is how metaprogramming is done in Rust. If it were calling a function
|
||||||
instead, it would look like this: `println()` (without the `!`). We'll discuss
|
instead, it would look like this: `println` (without the `!`). We'll discuss
|
||||||
Rust macros in more detail in Chapter XX, but for now you just need to know
|
Rust macros in more detail in Chapter XX, but for now you just need to know
|
||||||
that when you see a `!` that means that you’re calling a macro instead of a
|
that when you see a `!` that means that you’re calling a macro instead of a
|
||||||
normal function.
|
normal function.
|
||||||
|
|
||||||
Next is `"Hello, world!"` which is a *string*. We pass this string as an
|
Next is `"Hello, world!"` which is a *string*. We pass this string as an
|
||||||
argument to `println!()`, which prints the string to the screen. Easy enough!
|
argument to `println!`, which prints the string to the screen. Easy enough!
|
||||||
|
|
||||||
The line ends with a semicolon (`;`). The `;` indicates that this expression is
|
The line ends with a semicolon (`;`). The `;` indicates that this expression is
|
||||||
over, and the next one is ready to begin. Most lines of Rust code end with a
|
over, and the next one is ready to begin. Most lines of Rust code end with a
|
||||||
|
@ -117,7 +117,7 @@ the functionality to accept user input.
|
|||||||
fn main() {
|
fn main() {
|
||||||
```
|
```
|
||||||
|
|
||||||
As you’ve seen in Chapter 1, the `main()` function is the entry point into the
|
As you’ve seen in Chapter 1, the `main` function is the entry point into the
|
||||||
program. The `fn` syntax declares a new function, the `()`s indicate that
|
program. The `fn` syntax declares a new function, the `()`s indicate that
|
||||||
there are no arguments, and `{` starts the body of the function.
|
there are no arguments, and `{` starts the body of the function.
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ println!("Guess the number!");
|
|||||||
println!("Please input your guess.");
|
println!("Please input your guess.");
|
||||||
```
|
```
|
||||||
|
|
||||||
As we learned in Chapter 1, `println!()` is a macro that prints a string to the
|
As we learned in Chapter 1, `println!` is a macro that prints a string to the
|
||||||
screen. This is just a prompt stating what the game is and requesting input from
|
screen. This is just a prompt stating what the game is and requesting input from
|
||||||
the user.
|
the user.
|
||||||
|
|
||||||
@ -164,19 +164,19 @@ let mut bar = 5; // mutable
|
|||||||
|
|
||||||
So now we know that `let mut guess` will introduce a mutable binding named
|
So now we know that `let mut guess` will introduce a mutable binding named
|
||||||
`guess`, but we have to look at the other side of the `=` for the value it’s
|
`guess`, but we have to look at the other side of the `=` for the value it’s
|
||||||
bound to: `String::new()`. `String` is a string type, provided by the standard
|
bound to: `String::new`. `String` is a string type, provided by the standard
|
||||||
library. A [`String`][string]<!-- ignore --> is a growable, UTF-8 encoded bit
|
library. A [`String`][string]<!-- ignore --> is a growable, UTF-8 encoded bit
|
||||||
of text.
|
of text.
|
||||||
|
|
||||||
[string]: ../std/string/struct.String.html
|
[string]: ../std/string/struct.String.html
|
||||||
|
|
||||||
The `::` syntax in the `::new()` line indicates that `new()` is an *associated
|
The `::` syntax in the `::new` line indicates that `new` is an *associated
|
||||||
function* of a particular type. An associated function is a function that is
|
function* of a particular type. An associated function is a function that is
|
||||||
associated with a type, in this case `String`, rather than a particular
|
associated with a type, in this case `String`, rather than a particular
|
||||||
instance of a `String`. Some languages call this a *static method*.
|
instance of a `String`. Some languages call this a *static method*.
|
||||||
|
|
||||||
This `new()` function creates a new, empty `String`.
|
This `new` function creates a new, empty `String`.
|
||||||
You’ll find a `new()` function on many types, as it’s a common name for making
|
You’ll find a `new` function on many types, as it’s a common name for making
|
||||||
a new value of some kind.
|
a new value of some kind.
|
||||||
|
|
||||||
So to summarize, the `let mut guess = String::new();` line has created a
|
So to summarize, the `let mut guess = String::new();` line has created a
|
||||||
@ -201,13 +201,13 @@ terminal.
|
|||||||
[iostdin]: ../std/io/struct.Stdin.html
|
[iostdin]: ../std/io/struct.Stdin.html
|
||||||
|
|
||||||
The next part, `.read_line(&mut guess)`, calls the
|
The next part, `.read_line(&mut guess)`, calls the
|
||||||
[`read_line()`][read_line]<!-- ignore --> method on the standard input handle
|
[`read_line`][read_line]<!-- ignore --> method on the standard input handle
|
||||||
to get input from the user. We’re also passing one argument to `read_line()`:
|
to get input from the user. We’re also passing one argument to `read_line`:
|
||||||
`&mut guess`.
|
`&mut guess`.
|
||||||
|
|
||||||
[read_line]: ../std/io/struct.Stdin.html#method.read_line
|
[read_line]: ../std/io/struct.Stdin.html#method.read_line
|
||||||
|
|
||||||
The job of `read_line()` is to take whatever the user types into standard input
|
The job of `read_line` is to take whatever the user types into standard input
|
||||||
and place that into a string, so it takes that string as an argument. The
|
and place that into a string, so it takes that string as an argument. The
|
||||||
string argument needs to be mutable so that the method can change the string's
|
string argument needs to be mutable so that the method can change the string's
|
||||||
content by adding the user input.
|
content by adding the user input.
|
||||||
@ -243,7 +243,7 @@ calls. Now let's see what this line does.
|
|||||||
|
|
||||||
### Handling Potential Failure with the `Result` Type
|
### Handling Potential Failure with the `Result` Type
|
||||||
|
|
||||||
We mentioned that `read_line()` puts what the user types into the string we
|
We mentioned that `read_line` puts what the user types into the string we
|
||||||
pass it, but it also returns a value: in this case, an
|
pass it, but it also returns a value: in this case, an
|
||||||
[`io::Result`][ioresult]<!-- ignore -->. Rust has a number of types named
|
[`io::Result`][ioresult]<!-- ignore -->. Rust has a number of types named
|
||||||
`Result` in its standard library: a generic [`Result`][result]<!-- ignore -->,
|
`Result` in its standard library: a generic [`Result`][result]<!-- ignore -->,
|
||||||
@ -266,19 +266,19 @@ or why the operation failed.
|
|||||||
|
|
||||||
The purpose of these `Result` types is to encode error handling information.
|
The purpose of these `Result` types is to encode error handling information.
|
||||||
Values of the `Result` type, like any type, have methods defined on them. In
|
Values of the `Result` type, like any type, have methods defined on them. In
|
||||||
this case, `io::Result` has an [`expect()` method][expect]<!-- ignore --> that
|
this case, `io::Result` has an [`expect` method][expect]<!-- ignore --> that
|
||||||
we can call. If this instance of `io::Result` is an `Err` value, `expect()`
|
we can call. If this instance of `io::Result` is an `Err` value, `expect`
|
||||||
will cause our program to crash and display the message that we passed as an
|
will cause our program to crash and display the message that we passed as an
|
||||||
argument to `expect()`. In this case, if the `read_line()` method returns an
|
argument to `expect`. In this case, if the `read_line` method returns an
|
||||||
`Err`, it would likely be the result of an error coming from the underlying
|
`Err`, it would likely be the result of an error coming from the underlying
|
||||||
operating system. If this instance of `io::Result` is an `Ok` value, `expect()`
|
operating system. If this instance of `io::Result` is an `Ok` value, `expect`
|
||||||
will take the return value that `Ok` is holding and return just that value to
|
will take the return value that `Ok` is holding and return just that value to
|
||||||
us so that we can use it. In this case, that value will be what the user
|
us so that we can use it. In this case, that value will be what the user
|
||||||
entered into standard input.
|
entered into standard input.
|
||||||
|
|
||||||
[expect]: ../std/result/enum.Result.html#method.expect
|
[expect]: ../std/result/enum.Result.html#method.expect
|
||||||
|
|
||||||
If we don't call `expect()`, our program will compile, but we’ll get a warning:
|
If we don't call `expect`, our program will compile, but we’ll get a warning:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ cargo build
|
$ cargo build
|
||||||
@ -292,10 +292,10 @@ src/main.rs:10 io::stdin().read_line(&mut guess);
|
|||||||
Rust warns that we haven’t used the `Result` value, telling us that we
|
Rust warns that we haven’t used the `Result` value, telling us that we
|
||||||
haven’t handled a possible error. The right way to suppress the warning is to
|
haven’t handled a possible error. The right way to suppress the warning is to
|
||||||
actually write error handling, but if we just want to crash the program when a
|
actually write error handling, but if we just want to crash the program when a
|
||||||
problem occurs, we can use `expect()`. We’ll save recovering from errors for a
|
problem occurs, we can use `expect`. We’ll save recovering from errors for a
|
||||||
future project.
|
future project.
|
||||||
|
|
||||||
### Printing Values with `println!()` Placeholders
|
### Printing Values with `println!` Placeholders
|
||||||
|
|
||||||
There’s only one line of this first example left, aside from the closing curly
|
There’s only one line of this first example left, aside from the closing curly
|
||||||
brace:
|
brace:
|
||||||
@ -308,7 +308,7 @@ This prints out the string we saved our input in. The `{}`s are a placeholder:
|
|||||||
think of `{}` as little crab pincers, holding a value in place. You can print
|
think of `{}` as little crab pincers, holding a value in place. You can print
|
||||||
more than one value this way: the first `{}` holds the first value listed after
|
more than one value this way: the first `{}` holds the first value listed after
|
||||||
the format string, the second set holds the second value, and so on. Printing
|
the format string, the second set holds the second value, and so on. Printing
|
||||||
out multiple values in one call to `println!()` would then look like this:
|
out multiple values in one call to `println!` would then look like this:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let x = 5;
|
let x = 5;
|
||||||
@ -538,12 +538,12 @@ let secret_number = rand::thread_rng().gen_range(1, 101);
|
|||||||
println!("The secret number is: {}", secret_number);
|
println!("The secret number is: {}", secret_number);
|
||||||
```
|
```
|
||||||
|
|
||||||
The `rand::thread_rng()` function will give us the particular random number
|
The `rand::thread_rng` function will give us the particular random number
|
||||||
generator that we're going to use: one that is local to our current thread of
|
generator that we're going to use: one that is local to our current thread of
|
||||||
execution and seeded by the operating system. Next, we call the `gen_range()`
|
execution and seeded by the operating system. Next, we call the `gen_range`
|
||||||
method on our random number generator. This method is defined by the `Rng`
|
method on our random number generator. This method is defined by the `Rng`
|
||||||
trait that we brought into scope with the `use rand::Rng` statement above. The
|
trait that we brought into scope with the `use rand::Rng` statement above. The
|
||||||
`gen_range()` method takes two numbers as arguments and generates a random
|
`gen_range` method takes two numbers as arguments and generates a random
|
||||||
number between them. It's inclusive on the lower bound but exclusive on the
|
number between them. It's inclusive on the lower bound but exclusive on the
|
||||||
upper bound, so we need `1` and `101` to ask for a number ranging from one to a
|
upper bound, so we need `1` and `101` to ask for a number ranging from one to a
|
||||||
hundred.
|
hundred.
|
||||||
@ -638,12 +638,12 @@ match guess.cmp(&secret_number) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The `cmp()` method compares two values, and can be called on anything that can
|
The `cmp` method compares two values, and can be called on anything that can
|
||||||
be compared. It takes a reference to whatever you want to compare with, so here
|
be compared. It takes a reference to whatever you want to compare with, so here
|
||||||
it's comparing our `guess` to our `secret_number`. `cmp()` returns a variant of
|
it's comparing our `guess` to our `secret_number`. `cmp` returns a variant of
|
||||||
the `Ordering` enum we imported with the `use` statement earlier. We use a
|
the `Ordering` enum we imported with the `use` statement earlier. We use a
|
||||||
[`match`][match]<!-- ignore --> statement to decide what to do next based on
|
[`match`][match]<!-- ignore --> statement to decide what to do next based on
|
||||||
which variant of `Ordering` we got back from our call to `cmp()` with the values
|
which variant of `Ordering` we got back from our call to `cmp` with the values
|
||||||
in `guess` and `secret_number`.
|
in `guess` and `secret_number`.
|
||||||
|
|
||||||
[match]: match.html
|
[match]: match.html
|
||||||
@ -657,7 +657,7 @@ Chapter XX, respectively.
|
|||||||
|
|
||||||
Let's walk through an example of what would happen with our `match`. Say that
|
Let's walk through an example of what would happen with our `match`. Say that
|
||||||
the user has guessed 50, and the randomly-generated secret number this time
|
the user has guessed 50, and the randomly-generated secret number this time
|
||||||
is 38. So when we compare 50 to 38, the `cmp()` method will return
|
is 38. So when we compare 50 to 38, the `cmp` method will return
|
||||||
`Ordering::Greater`, since 50 is greater than 38. `Ordering::Greater` is the
|
`Ordering::Greater`, since 50 is greater than 38. `Ordering::Greater` is the
|
||||||
value that the `match` statement gets. It looks at the first arm's pattern,
|
value that the `match` statement gets. It looks at the first arm's pattern,
|
||||||
`Ordering::Less`, and says nope, the value we have (`Ordering::Greater`) does
|
`Ordering::Less`, and says nope, the value we have (`Ordering::Greater`) does
|
||||||
@ -694,9 +694,9 @@ number; or others. Rust defaults to an `i32`, so that's the type of
|
|||||||
to infer a different numerical type. The error is because Rust will not compare
|
to infer a different numerical type. The error is because Rust will not compare
|
||||||
a string and a number type.
|
a string and a number type.
|
||||||
|
|
||||||
Ultimately, we want to convert the `String` we read as input
|
Ultimately, we want to convert the `String` we read as input into a real number
|
||||||
into a real number type so that we can compare it to the guess numerically. We
|
type so that we can compare it to the guess numerically. We can do that with
|
||||||
can do that with two more lines; to your `fn main()` body, add the following two lines:
|
two more lines; to your `main` function body, add the following two lines:
|
||||||
|
|
||||||
Filename: src/main.rs
|
Filename: src/main.rs
|
||||||
|
|
||||||
@ -751,15 +751,15 @@ come up with two unique bindings, like `guess_str` and `guess` or something
|
|||||||
|
|
||||||
We bind `guess` to the expression `guess.trim().parse()`. The `guess` in the
|
We bind `guess` to the expression `guess.trim().parse()`. The `guess` in the
|
||||||
expression refers to the original `guess` that was a `String` with our input in
|
expression refers to the original `guess` that was a `String` with our input in
|
||||||
it. The `trim()` method on `String`s will eliminate any whitespace at the
|
it. The `trim` method on `String`s will eliminate any whitespace at the
|
||||||
beginning and end. Our `u32` can only contain numerical characters, but we have
|
beginning and end. Our `u32` can only contain numerical characters, but we have
|
||||||
to press the return key to satisfy `read_line()`. When we press the return
|
to press the return key to satisfy `read_line`. When we press the return
|
||||||
key, it introduces a newline character. For example, if we type `5` and hit
|
key, it introduces a newline character. For example, if we type `5` and hit
|
||||||
return, `guess` looks like this: `5\n`. The `\n` represents "newline", the
|
return, `guess` looks like this: `5\n`. The `\n` represents "newline", the
|
||||||
return key. The `trim()` method gets rid of this, leaving our string with only
|
return key. The `trim` method gets rid of this, leaving our string with only
|
||||||
the `5`.
|
the `5`.
|
||||||
|
|
||||||
The [`parse()` method on strings][parse]<!-- ignore --> parses a string into
|
The [`parse` method on strings][parse]<!-- ignore --> parses a string into
|
||||||
some kind of number. Since this method can parse a variety of number types, we
|
some kind of number. Since this method can parse a variety of number types, we
|
||||||
need to tell Rust the exact type of number we want with `let guess: u32`. The
|
need to tell Rust the exact type of number we want with `let guess: u32`. The
|
||||||
colon (`:`) after `guess` tells Rust we’re going to annotate its type. Rust has
|
colon (`:`) after `guess` tells Rust we’re going to annotate its type. Rust has
|
||||||
@ -772,15 +772,15 @@ between two values of the same type!
|
|||||||
|
|
||||||
[parse]: ../std/primitive.str.html#method.parse
|
[parse]: ../std/primitive.str.html#method.parse
|
||||||
|
|
||||||
Our call to `parse()` could quite easily cause an error. If, for example, our
|
Our call to `parse` could quite easily cause an error. If, for example, our
|
||||||
string contained `A👍%`, there’d be no way to convert that to a number. Because
|
string contained `A👍%`, there’d be no way to convert that to a number. Because
|
||||||
it might fail, the `parse()` method returns a `Result` type, much like the
|
it might fail, the `parse` method returns a `Result` type, much like the
|
||||||
`read_line()` method does that we discussed earlier. We're going to treat this
|
`read_line` method does that we discussed earlier. We're going to treat this
|
||||||
`Result` the same way by using the `expect()` method again. If `parse()`
|
`Result` the same way by using the `expect` method again. If `parse`
|
||||||
returns an `Err` `Result` variant because it could not create a number from the
|
returns an `Err` `Result` variant because it could not create a number from the
|
||||||
string, the `expect()` call will crash the game and print the message we give
|
string, the `expect` call will crash the game and print the message we give
|
||||||
it. If `parse()` can successfully turn the string into a number, it will return
|
it. If `parse` can successfully turn the string into a number, it will return
|
||||||
the `Ok` variant of `Result`, and `expect()` will return the number that we
|
the `Ok` variant of `Result`, and `expect` will return the number that we
|
||||||
want that it will take out of the `Ok` value for us.
|
want that it will take out of the `Ok` value for us.
|
||||||
|
|
||||||
|
|
||||||
@ -856,7 +856,7 @@ told it to do: ask for another guess forever! It doesn't seem like we can quit!
|
|||||||
|
|
||||||
We could always halt the program by using the keyboard shortcut `control-c`.
|
We could always halt the program by using the keyboard shortcut `control-c`.
|
||||||
There's another way to escape the insatiable monster we've created, though,
|
There's another way to escape the insatiable monster we've created, though,
|
||||||
that can be found in our discussion about `parse()`: if we give a non-number
|
that can be found in our discussion about `parse`: if we give a non-number
|
||||||
answer, the program will crash. We can use that to quit! Observe:
|
answer, the program will crash. We can use that to quit! Observe:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -935,7 +935,7 @@ fn main() {
|
|||||||
|
|
||||||
By adding the `break` line after `You win!`, we’ll exit the loop when we guess
|
By adding the `break` line after `You win!`, we’ll exit the loop when we guess
|
||||||
the secret number correctly. Exiting the loop also means exiting the program,
|
the secret number correctly. Exiting the loop also means exiting the program,
|
||||||
since the loop is the last thing in `main()`.
|
since the loop is the last thing in `main`.
|
||||||
|
|
||||||
#### Handling Invalid Input
|
#### Handling Invalid Input
|
||||||
|
|
||||||
@ -952,25 +952,25 @@ let guess: u32 = match guess.trim().parse() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
This is how you generally move from "crash on error" to "actually handle the
|
This is how you generally move from "crash on error" to "actually handle the
|
||||||
error": by switching from an `expect()` statement to a `match` statement.
|
error": by switching from an `expect` statement to a `match` statement.
|
||||||
Remember that `parse()` returns a `Result` type, and `Result` is an enum that
|
Remember that `parse` returns a `Result` type, and `Result` is an enum that
|
||||||
has the variants `Ok` or `Err`. We're going to use a `match` statement here,
|
has the variants `Ok` or `Err`. We're going to use a `match` statement here,
|
||||||
like we did with the `Ordering` result of the `cmp()` method.
|
like we did with the `Ordering` result of the `cmp` method.
|
||||||
|
|
||||||
If `parse()` is able to successfully turn the string into a number, it will
|
If `parse` is able to successfully turn the string into a number, it will
|
||||||
return an `Ok` value that contains the resulting number. That `Ok` value will
|
return an `Ok` value that contains the resulting number. That `Ok` value will
|
||||||
match the first arm's pattern, and the match statement will just return the
|
match the first arm's pattern, and the match statement will just return the
|
||||||
`num` value that `parse()` produced and put inside the `Ok` value. That number
|
`num` value that `parse` produced and put inside the `Ok` value. That number
|
||||||
will end up right where we want it, in the new `guess` binding we're creating.
|
will end up right where we want it, in the new `guess` binding we're creating.
|
||||||
|
|
||||||
If `parse()` is *not* able to turn the string into a number, it will return an
|
If `parse` is *not* able to turn the string into a number, it will return an
|
||||||
`Err` value that contains more information about the error. The `Err` value
|
`Err` value that contains more information about the error. The `Err` value
|
||||||
does not match the `Ok(num)` pattern in the first match arm, but it does match
|
does not match the `Ok(num)` pattern in the first match arm, but it does match
|
||||||
the `Err(_)` pattern in the second arm. The `_` is a catch-all value; we're
|
the `Err(_)` pattern in the second arm. The `_` is a catch-all value; we're
|
||||||
saying we want to match all `Err` values, no matter what information they have
|
saying we want to match all `Err` values, no matter what information they have
|
||||||
inside them. So we execute the second arm's code, `continue`: this means to go
|
inside them. So we execute the second arm's code, `continue`: this means to go
|
||||||
to the next iteration of the `loop` and ask for another guess. So we have
|
to the next iteration of the `loop` and ask for another guess. So we have
|
||||||
effectively ignored all errors that `parse()` might hit!
|
effectively ignored all errors that `parse` might hit!
|
||||||
|
|
||||||
Now everything in our program should work as we expect it to! Let’s try it:
|
Now everything in our program should work as we expect it to! Let’s try it:
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ Something to keep in mind throughout this section: Rust is a *statically typed*
|
|||||||
language, which means that it must know the types of all bindings at compile
|
language, which means that it must know the types of all bindings at compile
|
||||||
time. The compiler can usually infer what type we want to use based on the
|
time. The compiler can usually infer what type we want to use based on the
|
||||||
value and how we use it. When many types are possible, such as when we
|
value and how we use it. When many types are possible, such as when we
|
||||||
converted a `String` to a numeric type using `parse()` in the guessing game
|
converted a `String` to a numeric type using `parse` in the guessing game
|
||||||
tutorial, we can add a type annotation, like this:
|
tutorial, we can add a type annotation, like this:
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
## How Functions Work
|
## How Functions Work
|
||||||
|
|
||||||
Functions are pervasive in Rust code. We’ve already seen one of the most
|
Functions are pervasive in Rust code. We’ve already seen one of the most
|
||||||
important functions in the language: the `main()` function that’s the entry
|
important functions in the language: the `main` function that’s the entry
|
||||||
point of many programs. We've also seen the `fn` keyword, which allows us to
|
point of many programs. We've also seen the `fn` keyword, which allows us to
|
||||||
declare new functions.
|
declare new functions.
|
||||||
|
|
||||||
@ -28,14 +28,14 @@ after the function name. The curly braces tell the compiler where the function
|
|||||||
body begins and ends.
|
body begins and ends.
|
||||||
|
|
||||||
We can call any function we’ve defined by entering its name followed by a pair
|
We can call any function we’ve defined by entering its name followed by a pair
|
||||||
of parentheses. Since `another_function()` is defined in the program, it can be
|
of parentheses. Since `another_function` is defined in the program, it can be
|
||||||
called from inside the `main()` function. Note that we defined
|
called from inside the `main` function. Note that we defined
|
||||||
`another_function()` _after_ the `main()` function in our source code; we could
|
`another_function` _after_ the `main` function in our source code; we could
|
||||||
have defined it before as well. Rust doesn’t care where you define your
|
have defined it before as well. Rust doesn’t care where you define your
|
||||||
functions, only that they are defined somewhere.
|
functions, only that they are defined somewhere.
|
||||||
|
|
||||||
Let’s start a new binary project named `functions` so that we can explore
|
Let’s start a new binary project named `functions` so that we can explore
|
||||||
further. Place the `another_function()` example in `src/main.rs` and run it.
|
further. Place the `another_function` example in `src/main.rs` and run it.
|
||||||
You should see the following output:
|
You should see the following output:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -46,14 +46,14 @@ Hello, world!
|
|||||||
Another function.
|
Another function.
|
||||||
```
|
```
|
||||||
|
|
||||||
The lines execute in the order they appear in the `main()` function. First, our
|
The lines execute in the order they appear in the `main` function. First, our
|
||||||
“Hello, world!” message prints, and then `another_function()` is called and its
|
“Hello, world!” message prints, and then `another_function` is called and its
|
||||||
message is printed.
|
message is printed.
|
||||||
|
|
||||||
### Function Arguments
|
### Function Arguments
|
||||||
|
|
||||||
Functions can also take arguments. The following rewritten version of
|
Functions can also take arguments. The following rewritten version of
|
||||||
`another_function()` shows what arguments look like in Rust:
|
`another_function` shows what arguments look like in Rust:
|
||||||
|
|
||||||
Filename: src/main.rs
|
Filename: src/main.rs
|
||||||
|
|
||||||
@ -76,9 +76,9 @@ $ cargo run
|
|||||||
The value of x is: 5
|
The value of x is: 5
|
||||||
```
|
```
|
||||||
|
|
||||||
Since we passed `5` to `another_function()`, the `println!` macro put `5` where
|
Since we passed `5` to `another_function`, the `println!` macro put `5` where
|
||||||
the pair of curly braces were in the format string. The declaration of
|
the pair of curly braces were in the format string. The declaration of
|
||||||
`another_function()` shows that it takes one argument named `x`, and the type
|
`another_function` shows that it takes one argument named `x`, and the type
|
||||||
of `x` is `i32`.
|
of `x` is `i32`.
|
||||||
|
|
||||||
In function signatures, we _must_ declare the type. This is a deliberate
|
In function signatures, we _must_ declare the type. This is a deliberate
|
||||||
@ -252,8 +252,8 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
There are no function calls, macros, or even `let` statements in the `five()`
|
There are no function calls, macros, or even `let` statements in the `five`
|
||||||
function-- just the number `5` by itself. That's a perfectly valid function in
|
function: just the number `5` by itself. That's a perfectly valid function in
|
||||||
Rust. Note the function's return type, too. Try running this code, and the
|
Rust. Note the function's return type, too. Try running this code, and the
|
||||||
output should look like this:
|
output should look like this:
|
||||||
|
|
||||||
@ -264,18 +264,18 @@ $ cargo run
|
|||||||
The value of x is: 5
|
The value of x is: 5
|
||||||
```
|
```
|
||||||
|
|
||||||
The `5` in `five()` is actually the function's return value, which is why the
|
The `5` in the `five` function is actually the function's return value, which
|
||||||
return type is `i32`. Let’s examine this in more detail. There are two
|
is why the return type is `i32`. Let’s examine this in more detail. There are
|
||||||
important bits. First, the line `let x = five();` in `main()` shows that we can
|
two important bits. First, the line `let x = five();` in `main` shows that we
|
||||||
use the return value of a function to initialize a binding.
|
can use the return value of a function to initialize a binding.
|
||||||
|
|
||||||
Because the function `five()` returns a `5`, that line is the same as saying:
|
Because the function `five` returns a `5`, that line is the same as saying:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let x = 5;
|
let x = 5;
|
||||||
```
|
```
|
||||||
|
|
||||||
The second interesting bit is the `five()` function itself. It requires no
|
The second interesting bit is the `five` function itself. It requires no
|
||||||
arguments and defines the type of the return value, but the body of the
|
arguments and defines the type of the return value, but the body of the
|
||||||
function is a lonely `5` with no semicolon because it is an expression whose
|
function is a lonely `5` with no semicolon because it is an expression whose
|
||||||
value we want to return. Let's look at another example:
|
value we want to return. Let's look at another example:
|
||||||
|
@ -386,9 +386,8 @@ item from the `a` array but forgot to update the condition to be `while index <
|
|||||||
remember to change any other code if we changed the number of values in the
|
remember to change any other code if we changed the number of values in the
|
||||||
array.
|
array.
|
||||||
|
|
||||||
If you're wondering about the `.iter()` code in this example, keep reading! We
|
If you're wondering about `iter` in this example, keep reading! We will cover
|
||||||
will cover method syntax generally in Chapter XX and iterators specifically in
|
method syntax generally in Chapter XX and iterators specifically in Chapter XX.
|
||||||
Chapter XX.
|
|
||||||
|
|
||||||
The safety and conciseness of `for` loops make them the most commonly used loop
|
The safety and conciseness of `for` loops make them the most commonly used loop
|
||||||
construct in Rust. Even in situations where you want to run some code a certain
|
construct in Rust. Even in situations where you want to run some code a certain
|
||||||
@ -397,7 +396,7 @@ Rustaceans would use a `for` loop. The way to do that is using a `Range`, which
|
|||||||
is a type provided by the standard library that generates numbers starting from
|
is a type provided by the standard library that generates numbers starting from
|
||||||
one number and ending before another number. Here's what the countdown would
|
one number and ending before another number. Here's what the countdown would
|
||||||
look like with a for loop, and using another method we haven't yet talked
|
look like with a for loop, and using another method we haven't yet talked
|
||||||
about, `.rev()`, to reverse the range:
|
about, `rev`, to reverse the range:
|
||||||
|
|
||||||
Filename: src/main.rs
|
Filename: src/main.rs
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ mod network {
|
|||||||
This is our first module declaration. As you can see, you use the `mod`
|
This is our first module declaration. As you can see, you use the `mod`
|
||||||
keyword, followed by the name of the module, and then a block of code in curly
|
keyword, followed by the name of the module, and then a block of code in curly
|
||||||
braces. Everything inside this block is inside the namespace `network`. In this
|
braces. Everything inside this block is inside the namespace `network`. In this
|
||||||
case, we have a single function, `connect()`. If we wanted to try and call this
|
case, we have a single function, `connect`. If we wanted to try and call this
|
||||||
function from outside the `network` module, we would say `network::connect()`
|
function from outside the `network` module, we would say `network::connect()`
|
||||||
rather than `connect()`.
|
rather than `connect()`.
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ mod client {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Now we have a `network::connect()` function and a `client::connect()` function.
|
Now we have a `network::connect` function and a `client::connect` function.
|
||||||
|
|
||||||
And you can put modules inside of modules. If you wanted to have `client` be
|
And you can put modules inside of modules. If you wanted to have `client` be
|
||||||
within `network`:
|
within `network`:
|
||||||
@ -84,7 +84,7 @@ mod network {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This gives us `network::connect()` and `network::client::connect()`.
|
This gives us `network::connect` and `network::client::connect`.
|
||||||
|
|
||||||
In this way, modules form a tree. The contents of `src/lib.rs` are at the root
|
In this way, modules form a tree. The contents of `src/lib.rs` are at the root
|
||||||
of the project's tree, and the submodules form the leaves. Here's what our
|
of the project's tree, and the submodules form the leaves. Here's what our
|
||||||
|
@ -49,7 +49,7 @@ functionality is in a library crate, and the executable crate uses that
|
|||||||
library. This way, other programs can also use the library crate, and it’s also
|
library. This way, other programs can also use the library crate, and it’s also
|
||||||
a nice separation of concerns.
|
a nice separation of concerns.
|
||||||
|
|
||||||
Our binary crate right now just calls our library's `connect()` function from
|
Our binary crate right now just calls our library's `connect` function from
|
||||||
the `client` module; we picked that one since it's the first warning in our
|
the `client` module; we picked that one since it's the first warning in our
|
||||||
build output above. Invoking `cargo build` will now give us an error after the
|
build output above. Invoking `cargo build` will now give us an error after the
|
||||||
warnings:
|
warnings:
|
||||||
@ -101,7 +101,7 @@ error: function `connect` is private
|
|||||||
|
|
||||||
Hooray! We have a different error! Yes, different error messages are a cause
|
Hooray! We have a different error! Yes, different error messages are a cause
|
||||||
for celebration. The new error says "function `connect` is private", so let's
|
for celebration. The new error says "function `connect` is private", so let's
|
||||||
edit `src/client.rs` to make `client::connect()` public:
|
edit `src/client.rs` to make `client::connect` public:
|
||||||
|
|
||||||
Filename: src/client.rs
|
Filename: src/client.rs
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ warning: function is never used: `connect`, #[warn(dead_code)] on by default
|
|||||||
| ^
|
| ^
|
||||||
```
|
```
|
||||||
|
|
||||||
It compiled! And the warning about `client::connect()` not being used is gone!
|
It compiled! And the warning about `client::connect` not being used is gone!
|
||||||
|
|
||||||
Making functions public isn't the only way to fix unused code warnings: if
|
Making functions public isn't the only way to fix unused code warnings: if
|
||||||
we *didn't* want these functions to be part of our public API and we got these
|
we *didn't* want these functions to be part of our public API and we got these
|
||||||
@ -230,26 +230,26 @@ fn try_me() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Before you try to compile this code, make a guess about which lines in
|
Before you try to compile this code, make a guess about which lines in
|
||||||
`try_me()` will have errors.
|
`try_me` will have errors.
|
||||||
|
|
||||||
Ready? Let's talk through them!
|
Ready? Let's talk through them!
|
||||||
|
|
||||||
The `try_me()` function is in the root module of our project. The module named
|
The `try_me` function is in the root module of our project. The module named
|
||||||
`outermost` is private, but the second rule says we're allowed to access it
|
`outermost` is private, but the second rule says we're allowed to access it
|
||||||
since `outermost` is in our current, root module.
|
since `outermost` is in our current, root module.
|
||||||
|
|
||||||
The function call `outermost::middle_function()` will work. `middle_function()`
|
The function call `outermost::middle_function()` will work. `middle_function`
|
||||||
is public, and we are accessing it through its parent module, `outermost`,
|
is public, and we are accessing it through its parent module, `outermost`,
|
||||||
which we just determined we can access in the previous paragraph.
|
which we just determined we can access in the previous paragraph.
|
||||||
|
|
||||||
`outermost::middle_secret_function()` will cause a compilation error.
|
`outermost::middle_secret_function()` will cause a compilation error.
|
||||||
`middle_secret_function()` is private, so the second rule applies. Our current
|
`middle_secret_function` is private, so the second rule applies. Our current
|
||||||
root module is neither the current module of `middle_secret_function()`
|
root module is neither the current module of `middle_secret_function`
|
||||||
(`outermost` is), nor is it a child module of the current module of
|
(`outermost` is), nor is it a child module of the current module of
|
||||||
`middle_secret_function()`.
|
`middle_secret_function`.
|
||||||
|
|
||||||
The module named `inside` is private and has no child modules, so it can only
|
The module named `inside` is private and has no child modules, so it can only
|
||||||
be accessed by its current module, `outermost`. That means the `try_me()`
|
be accessed by its current module, `outermost`. That means the `try_me`
|
||||||
function is not allowed to call `outermost::inside::inner_function()` or
|
function is not allowed to call `outermost::inside::inner_function()` or
|
||||||
`outermost::inside::secret_function()`.
|
`outermost::inside::secret_function()`.
|
||||||
|
|
||||||
@ -259,7 +259,7 @@ rules to understand why.
|
|||||||
|
|
||||||
* What if the `inside` module was public?
|
* What if the `inside` module was public?
|
||||||
* What if `outside` was public and `inside` was private?
|
* What if `outside` was public and `inside` was private?
|
||||||
* What if, in the body of `inner_function()`, we called
|
* What if, in the body of `inner_function`, we called
|
||||||
`::outermost::middle_secret_function()`? (The two colons at the beginning
|
`::outermost::middle_secret_function()`? (The two colons at the beginning
|
||||||
mean that we want to refer to the namespaces starting from the root
|
mean that we want to refer to the namespaces starting from the root
|
||||||
namespace.)
|
namespace.)
|
||||||
|
@ -125,11 +125,11 @@ mod tests {
|
|||||||
|
|
||||||
We'll explain more about testing in Chapter XX, but parts of this should make
|
We'll explain more about testing in Chapter XX, but parts of this should make
|
||||||
sense now: we have a module named `tests` that lives next to our other modules
|
sense now: we have a module named `tests` that lives next to our other modules
|
||||||
and contains one function named `it_works()`. Even though there are special
|
and contains one function named `it_works`. Even though there are special
|
||||||
annotations, the `tests` module is just another module!
|
annotations, the `tests` module is just another module!
|
||||||
|
|
||||||
Since tests are for exercising the code within our library, let's try to call
|
Since tests are for exercising the code within our library, let's try to call
|
||||||
our `client::connect()` function from this `it_works()` function, even though
|
our `client::connect` function from this `it_works` function, even though
|
||||||
we're not going to be checking any functionality right now:
|
we're not going to be checking any functionality right now:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
@ -24,7 +24,7 @@ fn bar() {
|
|||||||
```
|
```
|
||||||
|
|
||||||
This comment would then be interpreted by `rustdoc` as documenting the thing
|
This comment would then be interpreted by `rustdoc` as documenting the thing
|
||||||
that follows it: `foo()` and `bar()`.
|
that follows it: `foo` and `bar`.
|
||||||
|
|
||||||
Because documentation comments have semantic meaning to `rustdoc`, the compiler
|
Because documentation comments have semantic meaning to `rustdoc`, the compiler
|
||||||
will pay attention to the placement of your documentation comments. For
|
will pay attention to the placement of your documentation comments. For
|
||||||
|
@ -24,7 +24,7 @@ pub use a::namespace::function;
|
|||||||
Here, the `a` module is not public to users of our library, so neither are its
|
Here, the `a` module is not public to users of our library, so neither are its
|
||||||
children, even though `namespace` and `function` are public *within* our
|
children, even though `namespace` and `function` are public *within* our
|
||||||
library. So users of our library couldn't call `a::namespace::function()`
|
library. So users of our library couldn't call `a::namespace::function()`
|
||||||
themselves. However, since we've re-exported `function()` with `pub use`,
|
themselves. However, since we've re-exported `function` with `pub use`,
|
||||||
`function()` will be public. Users can just call `function()` themselves,
|
`function` will be public. Users can just call `function` themselves,
|
||||||
directly. This allows us to organize our code internally however we'd like,
|
directly. This allows us to organize our code internally however we'd like,
|
||||||
while presenting a different external interface.
|
while presenting a different external interface.
|
||||||
|
@ -125,7 +125,7 @@ fn foo<T>(x: T) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This `foo()` function has one generic parameter, `T`, and takes one argument,
|
This `foo` function has one generic parameter, `T`, and takes one argument,
|
||||||
`x`, which has the type `T`. Let's talk a little bit more about what this means.
|
`x`, which has the type `T`. Let's talk a little bit more about what this means.
|
||||||
|
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ more advanced features later, this distinction will become more useful.
|
|||||||
## There's more to the story
|
## There's more to the story
|
||||||
|
|
||||||
This section covered the basic syntax of generics, but it's not the full story.
|
This section covered the basic syntax of generics, but it's not the full story.
|
||||||
For example, let's try to implement our `foo()` function: we'll have it print out
|
For example, let's try to implement our `foo` function: we'll have it print out
|
||||||
the value of `x`:
|
the value of `x`:
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
|
Loading…
Reference in New Issue
Block a user