mirror of
https://github.com/rust-lang-cn/book-cn.git
synced 2025-02-02 23:38:41 +08:00
Merge remote-tracking branch 'origin/pr/383'
This commit is contained in:
commit
9c8014cdcd
@ -79,9 +79,9 @@ fn main() {
|
||||
|
||||
These lines define a *function* in Rust. The `main` function is special: it's
|
||||
the first thing that is run for every executable Rust program. The first line
|
||||
says, “I’m declaring a function named `main` that takes no arguments and
|
||||
returns nothing.” If there were arguments, they would go inside the parentheses,
|
||||
`(` and `)`.
|
||||
says, “I’m declaring a function named `main` that receives no arguments and
|
||||
returns nothing.” If there were arguments, the parameter names would go inside
|
||||
the parentheses, `(` and `)`.
|
||||
|
||||
Also note that the function body is wrapped in curly braces, `{` and `}`. Rust
|
||||
requires these around all function bodies. It's considered good style to put
|
||||
|
@ -127,7 +127,7 @@ fn main() {
|
||||
```
|
||||
|
||||
The `fn` syntax declares a new function, the `()` indicate there are no
|
||||
arguments, and `{` starts the body of the function.
|
||||
parameters, and `{` starts the body of the function.
|
||||
|
||||
As you also learned in Chapter 1, `println!` is a macro that prints a string to
|
||||
the screen:
|
||||
|
@ -50,10 +50,10 @@ The lines execute in the order in which they appear in the `main` function.
|
||||
First, the “Hello, world!” message prints, and then `another_function` is
|
||||
called and its message is printed.
|
||||
|
||||
### Function Arguments
|
||||
### Function Parameters
|
||||
|
||||
Functions can also take arguments. The following rewritten version of
|
||||
`another_function` shows what arguments look like in Rust:
|
||||
Functions can also have parameters. The following rewritten version of
|
||||
`another_function` shows what parameters look like in Rust:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -76,18 +76,18 @@ $ cargo run
|
||||
The value of x is: 5
|
||||
```
|
||||
|
||||
The declaration of `another_function` has one argument named `x`. The type of
|
||||
`x` is specified as `i32`. When `5` is passed to `another_function`, the
|
||||
`println!` macro puts `5` where the pair of curly braces were in the format
|
||||
string.
|
||||
The declaration of `another_function` has one parameter named `x`. The type of
|
||||
`x` is specified as `i32`. When `5` is passed as an argument to
|
||||
`another_function`, the `println!` macro puts `5` where the pair of curly
|
||||
braces were in the format string.
|
||||
|
||||
In function signatures, you *must* declare the type. This is a deliberate
|
||||
decision in Rust’s design: requiring type annotations in function definitions
|
||||
means the compiler almost never needs you to use them elsewhere in the code to
|
||||
figure out what you mean.
|
||||
In function signatures, you *must* declare the type of each parameter. This is
|
||||
a deliberate decision in Rust’s design: requiring type annotations in function
|
||||
definitions means the compiler almost never needs you to use them elsewhere in
|
||||
the code to figure out what you mean.
|
||||
|
||||
When you want a function to have multiple arguments, separate them inside the
|
||||
function signature with commas, like this:
|
||||
When you want a function to receive multiple arguments, separate the parameters
|
||||
inside the function signature with commas, like this:
|
||||
|
||||
<span class="filename">Filename: src/main.rs</span>
|
||||
|
||||
@ -102,10 +102,10 @@ fn another_function(x: i32, y: i32) {
|
||||
}
|
||||
```
|
||||
|
||||
This example creates a function with two arguments, both of which are `i32`
|
||||
types. If your function has multiple arguments, the arguments don’t need to be
|
||||
the same type, but they just happen to be in this example. The function then
|
||||
prints out the values of both of its arguments.
|
||||
This example creates a function with two parameters, both of which are `i32`
|
||||
types. The function then prints out the values of both of its arguments. Note
|
||||
that function parameters don't all need to be the same type - they just happen
|
||||
to be in this example.
|
||||
|
||||
Let’s try running this code. Replace the program currently in your *function*
|
||||
project’s *src/main.rs* file with the preceding example, and run it using
|
||||
@ -119,8 +119,8 @@ The value of x is: 5
|
||||
The value of y is: 6
|
||||
```
|
||||
|
||||
Because `5` is passed as the `x` argument and `6` is passed as the `y`
|
||||
argument, the two strings are printed with these values.
|
||||
Because `5` is passed into the `x` parameter and `6` is passed into the `y`
|
||||
parameter, the two strings are printed with these values.
|
||||
|
||||
### Function Bodies
|
||||
|
||||
|
@ -69,7 +69,7 @@ fn calculate_length(s: &String) -> usize { // s is a reference to a String
|
||||
```
|
||||
|
||||
The scope in which the variable `s` is valid is the same as any function
|
||||
argument's scope, but we don’t drop what the reference points to when it goes
|
||||
parameter's scope, but we don’t drop what the reference points to when it goes
|
||||
out of scope because we don’t have ownership. Functions that take references as
|
||||
arguments instead of the actual values mean we won’t need to return the values
|
||||
in order to give back ownership, since we never had ownership.
|
||||
|
@ -279,7 +279,7 @@ we defined the fields to be `length` and `width`, both of which have type
|
||||
`u32`. Then in `main`, we create a particular instance of a `Rectangle` that
|
||||
has a length of 50 and a width of 30.
|
||||
|
||||
Our `area` function now takes one argument that we’ve named `rectangle` whose
|
||||
Our `area` function now defines one parameter that we’ve named `rectangle` whose
|
||||
type is an immutable borrow of a struct `Rectangle` instance. As we covered in
|
||||
Chapter 4, we want to borrow the struct rather than take ownership of it so
|
||||
that `main` keeps its ownership and can continue using `rect1`, so that’s why
|
||||
|
@ -52,7 +52,7 @@ Listing 5-7: Defining an `area` method on the `Rectangle` struct
|
||||
In order to make the function be defined within the context of `Rectangle`, we
|
||||
start an `impl` block (`impl` is short for *implementation*). Then we move the
|
||||
function within the `impl` curly braces, and change the first (and in this
|
||||
case, only) argument to be `self` in the signature and everywhere within the
|
||||
case, only) parameter to be `self` in the signature and everywhere within the
|
||||
body. Then in `main` where we called the `area` function and passed `rect1` as
|
||||
an argument, we can instead use *method syntax* to call the `area` method on
|
||||
our `Rectangle` instance. Method syntax is taking an instance and adding a dot
|
||||
@ -69,8 +69,8 @@ We’ve chosen `&self` here for the same reason we used `&Rectangle` in the
|
||||
function version: we don’t want to take ownership, and we just want to be able
|
||||
to read the data in the struct, not write to it. If we wanted to be able to
|
||||
change the instance that we’ve called the method on as part of what the method
|
||||
does, we’d put `&mut self` as the first argument instead. Having a method that
|
||||
takes ownership of the instance by having just `self` as the first argument is
|
||||
does, we’d put `&mut self` as the first parameter instead. Having a method that
|
||||
takes ownership of the instance by having just `self` as the first parameter is
|
||||
rarer; this is usually used when the method transforms `self` into something
|
||||
else and we want to prevent the caller from using the original instance after
|
||||
the transformation.
|
||||
@ -202,8 +202,9 @@ impl Rectangle {
|
||||
<!-- Will add ghosting here in libreoffice /Carol -->
|
||||
|
||||
If we run this with the `main` from Listing 5-8, we will get our desired output!
|
||||
Methods can take multiple arguments that we add to the signature after the
|
||||
`self` parameter, and those arguments work just like arguments in functions do.
|
||||
Methods can have multiple parameters that we add to the signature after the
|
||||
`self` parameter, and those parameters work just like parameters in functions
|
||||
do.
|
||||
|
||||
### Associated Functions
|
||||
|
||||
|
@ -162,7 +162,7 @@ call this method with `String` values. This signature gives us the clues we
|
||||
need to understand the tricky bits of the `+` operator.
|
||||
|
||||
First of all, `s2` has an `&`, meaning that we are adding a *reference* of the
|
||||
second string to the first string. This is because of the `s` argument in the
|
||||
second string to the first string. This is because of the `s` parameter in the
|
||||
`add` function: we can only add a `&str` to a `String`, we can't add two
|
||||
`String`s together. Remember back in Chapter 4 when we talked about how
|
||||
`&String` will coerce to `&str`: we write `&s2` so that the `String` will
|
||||
|
@ -225,9 +225,9 @@ First, we define a struct named `Guess` that has a field named `value` that
|
||||
holds a `u32`. This is where the number will be stored.
|
||||
|
||||
Then we implement an associated function named `new` on `Guess` that is a
|
||||
constructor of `Guess` values. The `new` function takes one argument named
|
||||
constructor of `Guess` values. The `new` function defines one parameter named
|
||||
`value` of type `u32` and returns a `Guess`. The code in the body of the `new`
|
||||
function tests the `value` argument to make sure it is between 1 and 100. If
|
||||
function tests the `value` parameter to make sure it is between 1 and 100. If
|
||||
`value` doesn't pass this test, we call `panic!`, which will alert the
|
||||
programmer who is calling this code that they have a bug they need to fix,
|
||||
since creating a `Guess` with a `value` outside this range would violate the
|
||||
@ -236,7 +236,7 @@ might panic should be discussed in its public-facing API documentation; we'll
|
||||
cover documentation conventions around indicating the possibility of a `panic!`
|
||||
in the API documentation that you create in Chapter 14. If `value` does pass
|
||||
the test, we create a new `Guess` with its `value` field set to the `value`
|
||||
argument, and return the `Guess`.
|
||||
parameter, and return the `Guess`.
|
||||
|
||||
<!-- I'm not sure if you mean the function that creates the guess type (so
|
||||
listing 9-8) or the function that uses the guess type, below. You mean the
|
||||
|
@ -113,7 +113,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
The function takes an argument, `numbers`, which represents any concrete
|
||||
The function defines a parameter, `numbers`, which represents any concrete
|
||||
`Vec<i32>` that we might pass into the function. The code in the function
|
||||
definition operates on the `numbers` representation of any `Vec<i32>`. When
|
||||
we call the `largest` function, the code actually runs on the specific values
|
||||
|
@ -98,7 +98,7 @@ enum OptionalNumber { enum OptionalFloatingPointNumber {
|
||||
```
|
||||
|
||||
There's one problem, though: we've *used* `T`, but not defined it. This would
|
||||
be similar to using an argument to a function in the body without declaring it
|
||||
be similar to using a parameter of a function in the body without declaring it
|
||||
in the signature. We need to tell Rust that we've introduced a generic
|
||||
parameter. The syntax to do that is the angle brackets, like this:
|
||||
|
||||
@ -303,7 +303,7 @@ type small if you can.
|
||||
|
||||
In a similar way to data structures, we can use the `<>` syntax in function or
|
||||
method definitions. The angle brackets for type parameters go after the
|
||||
function or method name and before the argument list in parentheses:
|
||||
function or method name and before the parameter list in parentheses:
|
||||
|
||||
```rust
|
||||
fn generic_function<T>(value: T) {
|
||||
|
@ -272,7 +272,7 @@ Listing 10-3 referred to it:
|
||||
help: consider adding a `where T: std::fmt::Display` bound
|
||||
```
|
||||
|
||||
The `where` syntax moves the trait bounds after the function arguments list.
|
||||
The `where` syntax moves the trait bounds after the function parameters list.
|
||||
This definition of `show_anything` means the exact same thing as the definition
|
||||
in Listing 10-8, just said a different way:
|
||||
|
||||
|
@ -152,7 +152,7 @@ smaller scope than `x`, the value it refers to.
|
||||
|
||||
Note that we didn't have to name any lifetimes in the code itself; Rust figured
|
||||
it out for us. One situation in which Rust can't figure out the lifetimes is
|
||||
for a function or method when one of the arguments or return values is a
|
||||
for a function or method when one of the parameters or return values is a
|
||||
reference, except for a few scenarios we'll discuss in the lifetime elision
|
||||
section.
|
||||
|
||||
@ -176,8 +176,8 @@ function, we can't know beforehand exactly all of the arguments that it could
|
||||
be called with and how long they will be valid for. We have to explain to Rust
|
||||
what we expect the lifetime of the argument to be (we'll learn about how
|
||||
to know what you expect the lifetime to be in a bit). This is similar to
|
||||
writing a function that has an argument of a generic type: we don't know what
|
||||
type the arguments will actually end up being when the function gets called.
|
||||
writing a function that has a parameter of a generic type: we don't know what
|
||||
type the parameters will actually end up being when the function gets called.
|
||||
Lifetimes are the same idea, but they are generic over the scope of a
|
||||
reference, rather than a type.
|
||||
|
||||
@ -365,7 +365,7 @@ would create dangling pointers or otherwise violate memory safety.
|
||||
### Lifetime Elision
|
||||
|
||||
If every reference has a lifetime, and we need to provide them for functions
|
||||
that use references as arguments or return values, then why did this function
|
||||
that use references as parameters or return values, then why did this function
|
||||
from the "String Slices" section of Chapter 4 compile? We haven't annotated any
|
||||
lifetimes here, yet Rust happily compiles this function:
|
||||
|
||||
@ -405,15 +405,15 @@ could be ambiguity. The rules are a very basic set of particular cases, and if
|
||||
your code fits one of those cases, you don't need to write the lifetimes
|
||||
explicitly. Here are the rules:
|
||||
|
||||
Lifetimes on function arguments are called *input lifetimes*, and lifetimes on
|
||||
Lifetimes on function parameters are called *input lifetimes*, and lifetimes on
|
||||
return values are called *output lifetimes*. There's one rule related to how
|
||||
Rust infers input lifetimes in the absence of explicit annotations:
|
||||
|
||||
1. Each argument that is a reference and therefore needs a lifetime parameter
|
||||
gets its own. In other words, a function with one argument gets one lifetime
|
||||
parameter: `fn foo<'a>(x: &'a i32)`, a function with two arguments gets two
|
||||
separate lifetime parameters: `fn foo<'a, 'b>(x: &'a i32, y: &'b i32)`, and
|
||||
so on.
|
||||
1. Each function parameter that is a reference and therefore needs a lifetime
|
||||
parameter gets its own. In other words, a function with one parameter gets one
|
||||
lifetime parameter: `fn foo<'a>(x: &'a i32)`, a function with two parameters
|
||||
gets two separate lifetime parameters:
|
||||
`fn foo<'a, 'b>(x: &'a i32, y: &'b i32)`, and so on.
|
||||
|
||||
And two rules related to output lifetimes:
|
||||
|
||||
@ -443,7 +443,7 @@ any methods where the output type's lifetime is the same as that of the
|
||||
struct's because of the third elision rule. Here's a struct called `App` that
|
||||
holds a reference to another struct, `Config`, defined elsewhere. The
|
||||
`append_to_name` method does not need lifetime annotations even though the
|
||||
method has a reference as an argument and is returning a reference; the
|
||||
method has a reference as a parameter and is returning a reference; the
|
||||
lifetime of the return value will be the lifetime of `self`:
|
||||
|
||||
<span class="filename">Filename: src/lib.rs</span>
|
||||
|
@ -209,7 +209,7 @@ and includes the custom error message we specified:
|
||||
src/main.rs:4
|
||||
```
|
||||
|
||||
The two arguments to `assert_eq!` are named "left" and "right" rather than
|
||||
The two parameters to `assert_eq!` are named "left" and "right" rather than
|
||||
"expected" and "actual"; the order of the value that comes from your code and
|
||||
the value hardcoded into your test isn't important.
|
||||
|
||||
|
@ -506,7 +506,7 @@ wrapping. Unlike `unwrap`, if the value is an `Err` value, this method calls a
|
||||
*closure* which is an anonymous function that we define and pass as an argument
|
||||
to `unwrap_or_else`. We'll be covering closures in more detail in Chapter XX;
|
||||
the important part to understand in this case is that `unwrap_or_else` will
|
||||
pass the inner value of the `Err` to our closure in the argument `err` that
|
||||
pass the inner value of the `Err` to our closure into the parameter `err` that
|
||||
appears between the vertical pipes. Using `unwrap_or_else` lets us do some
|
||||
custom, non-`panic!` error handling.
|
||||
|
||||
|
@ -77,18 +77,18 @@ for that function
|
||||
<!-- Will add ghosting and wingdings in libreoffice /Carol -->
|
||||
|
||||
Notice that we need an explicit lifetime `'a` declared in the signature of
|
||||
`grep` and used with the `contents` argument and the return value. Remember,
|
||||
lifetime parameters are used to specify which arguments' lifetimes connect to
|
||||
the lifetime of the return value. In this case, we're indicating that the
|
||||
vector we're returning is going to contain string slices that reference slices
|
||||
of the argument `contents`, as opposed to referencing slices of the argument
|
||||
`search`. Another way to think about what we're telling Rust is that the data
|
||||
returned by the `grep` function will live as long as the data passed into this
|
||||
function in the `contents` argument. This is important! Given that the data a
|
||||
slice references needs to be valid in order for the reference to be valid, if
|
||||
the compiler thought that we were making string slices of `search` rather than
|
||||
`contents`, it would do its safety checking incorrectly. If we tried to compile
|
||||
this function without lifetimes, we would get this error:
|
||||
`grep` and used with the `contents` parameter and the return value. Remember,
|
||||
lifetime parameters are used to specify which function parameters' lifetimes
|
||||
connect to the lifetime of the return value. In this case, we're indicating that
|
||||
the vector we're returning is going to contain string slices that reference
|
||||
slices of the parameter `contents`, as opposed to referencing slices of the
|
||||
parameter `search`. Another way to think about what we're telling Rust is that
|
||||
the data returned by the `grep` function will live as long as the data passed
|
||||
into this function in the `contents` parameter. This is important! Given that
|
||||
the data a slice references needs to be valid in order for the reference to be
|
||||
valid, if the compiler thought that we were making string slices of `search`
|
||||
rather than `contents`, it would do its safety checking incorrectly. If we tried
|
||||
to compile this function without lifetimes, we would get this error:
|
||||
|
||||
```text
|
||||
error[E0106]: missing lifetime specifier
|
||||
@ -102,12 +102,13 @@ error[E0106]: missing lifetime specifier
|
||||
`contents`
|
||||
```
|
||||
|
||||
Rust can't possibly know which of the two arguments we need, so it needs us to
|
||||
tell it. Because `contents` is the argument that contains all of our text and
|
||||
Rust can't possibly know which of the two parameters we need, so it needs us to
|
||||
tell it. Because `contents` is the parameter that contains all of our text and
|
||||
we want to return the parts of that text that match, we know `contents` is the
|
||||
argument that should be connected to the return value using the lifetime syntax.
|
||||
parameter that should be connected to the return value using the lifetime
|
||||
syntax.
|
||||
|
||||
Connecting arguments to return values in the signature is something that other
|
||||
Connecting parameters to return values in the signature is something that other
|
||||
programming languages don't make you do, so don't worry if this still feels
|
||||
strange! Knowing how to specify lifetimes gets easier over time, and practice
|
||||
makes perfect. You may want to re-read the above section or go back and compare
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Patterns
|
||||
|
||||
We've actually used patterns a few times so far: they're used in `let`
|
||||
statements, in function arguments, and in the `match` expression. Patterns have
|
||||
statements, in function parameters, and in the `match` expression. Patterns have
|
||||
a lot more abilities than we have demonstrated so far, so we'll cover some of
|
||||
the most commonly used ones in this section. Any of these abilities work in any
|
||||
place where a pattern is used.
|
||||
|
Loading…
Reference in New Issue
Block a user