rollup merge of #18355 : chastell/guide_iterators_macros_unsafe_fixes
This commit is contained in:
commit
fff2b35a6e
1 changed files with 21 additions and 20 deletions
|
@ -4467,18 +4467,19 @@ see why consumers matter.
|
||||||
|
|
||||||
## Iterators
|
## Iterators
|
||||||
|
|
||||||
As we've said before, an iterator is something that we can call the `.next()`
|
As we've said before, an iterator is something that we can call the
|
||||||
method on repeatedly, and it gives us a sequence of things. Because you need
|
`.next()` method on repeatedly, and it gives us a sequence of things.
|
||||||
to call the method, this means that iterators are **lazy**. This code, for
|
Because you need to call the method, this means that iterators
|
||||||
example, does not actually generate the numbers `1-100`, and just creates a
|
are **lazy** and don't need to generate all of the values upfront.
|
||||||
value that represents the sequence:
|
This code, for example, does not actually generate the numbers
|
||||||
|
`1-100`, and just creates a value that represents the sequence:
|
||||||
|
|
||||||
```{rust}
|
```{rust}
|
||||||
let nums = range(1i, 100i);
|
let nums = range(1i, 100i);
|
||||||
```
|
```
|
||||||
|
|
||||||
Since we didn't do anything with the range, it didn't generate the sequence.
|
Since we didn't do anything with the range, it didn't generate the sequence.
|
||||||
Once we add the consumer:
|
Let's add the consumer:
|
||||||
|
|
||||||
```{rust}
|
```{rust}
|
||||||
let nums = range(1i, 100i).collect::<Vec<int>>();
|
let nums = range(1i, 100i).collect::<Vec<int>>();
|
||||||
|
@ -4507,8 +4508,8 @@ std::iter::count(1i, 5i);
|
||||||
```
|
```
|
||||||
|
|
||||||
This iterator counts up from one, adding five each time. It will give
|
This iterator counts up from one, adding five each time. It will give
|
||||||
you a new integer every time, forever. Well, technically, until the
|
you a new integer every time, forever (well, technically, until it reaches the
|
||||||
maximum number that an `int` can represent. But since iterators are lazy,
|
maximum number representable by an `int`). But since iterators are lazy,
|
||||||
that's okay! You probably don't want to use `collect()` on it, though...
|
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
|
That's enough about iterators. Iterator adapters are the last concept
|
||||||
|
@ -5251,8 +5252,8 @@ to do something that it can't currently do? You may be able to write a macro
|
||||||
to extend Rust's capabilities.
|
to extend Rust's capabilities.
|
||||||
|
|
||||||
You've already used one macro extensively: `println!`. When we invoke
|
You've already used one macro extensively: `println!`. When we invoke
|
||||||
a Rust macro, we need to use the exclamation mark (`!`). There's two reasons
|
a Rust macro, we need to use the exclamation mark (`!`). There are two reasons
|
||||||
that this is true: the first is that it makes it clear when you're using a
|
why this is so: the first is that it makes it clear when you're using a
|
||||||
macro. The second is that macros allow for flexible syntax, and so Rust must
|
macro. The second is that macros allow for flexible syntax, and so Rust must
|
||||||
be able to tell where a macro starts and ends. The `!(...)` helps with this.
|
be able to tell where a macro starts and ends. The `!(...)` helps with this.
|
||||||
|
|
||||||
|
@ -5267,7 +5268,7 @@ println!("x is: {}", x);
|
||||||
|
|
||||||
The `println!` macro does a few things:
|
The `println!` macro does a few things:
|
||||||
|
|
||||||
1. It parses the string to find any `{}`s
|
1. It parses the string to find any `{}`s.
|
||||||
2. It checks that the number of `{}`s matches the number of other arguments.
|
2. It checks that the number of `{}`s matches the number of other arguments.
|
||||||
3. It generates a bunch of Rust code, taking this in mind.
|
3. It generates a bunch of Rust code, taking this in mind.
|
||||||
|
|
||||||
|
@ -5276,8 +5277,8 @@ Rust will generate code that takes all of the types into account. If
|
||||||
`println!` was a function, it could still do this type checking, but it
|
`println!` was a function, it could still do this type checking, but it
|
||||||
would happen at run time rather than compile time.
|
would happen at run time rather than compile time.
|
||||||
|
|
||||||
We can check this out using a special flag to `rustc`. This code, in a file
|
We can check this out using a special flag to `rustc`. Put this code in a file
|
||||||
`print.rs`:
|
called `print.rs`:
|
||||||
|
|
||||||
```{rust}
|
```{rust}
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -5286,7 +5287,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Can have its macros expanded like this: `rustc print.rs --pretty=expanded`, will
|
You can have the macros expanded like this: `rustc print.rs --pretty=expanded` – which will
|
||||||
give us this huge result:
|
give us this huge result:
|
||||||
|
|
||||||
```{rust,ignore}
|
```{rust,ignore}
|
||||||
|
@ -5325,12 +5326,12 @@ invoke the `println_args` function with the generated arguments.
|
||||||
This is the code that Rust actually compiles. You can see all of the extra
|
This is the code that Rust actually compiles. You can see all of the extra
|
||||||
information that's here. We get all of the type safety and options that it
|
information that's here. We get all of the type safety and options that it
|
||||||
provides, but at compile time, and without needing to type all of this out.
|
provides, but at compile time, and without needing to type all of this out.
|
||||||
This is how macros are powerful. Without them, you would need to type all of
|
This is how macros are powerful: without them you would need to type all of
|
||||||
this by hand to get a type checked `println`.
|
this by hand to get a type-checked `println`.
|
||||||
|
|
||||||
For more on macros, please consult [the Macros Guide](guide-macros.html).
|
For more on macros, please consult [the Macros Guide](guide-macros.html).
|
||||||
Macros are a very advanced and still slightly experimental feature, but don't
|
Macros are a very advanced and still slightly experimental feature, but they don't
|
||||||
require a deep understanding to call, since they look just like functions. The
|
require a deep understanding to be called, since they look just like functions. The
|
||||||
Guide can help you if you want to write your own.
|
Guide can help you if you want to write your own.
|
||||||
|
|
||||||
# Unsafe
|
# Unsafe
|
||||||
|
@ -5347,8 +5348,8 @@ keyword, which indicates that the function may not behave properly.
|
||||||
|
|
||||||
Second, if you'd like to create some sort of shared-memory data structure, Rust
|
Second, if you'd like to create some sort of shared-memory data structure, Rust
|
||||||
won't allow it, because memory must be owned by a single owner. However, if
|
won't allow it, because memory must be owned by a single owner. However, if
|
||||||
you're planning on making access to that shared memory safe, such as with a
|
you're planning on making access to that shared memory safe – such as with a
|
||||||
mutex, _you_ know that it's safe, but Rust can't know. Writing an `unsafe`
|
mutex – _you_ know that it's safe, but Rust can't know. Writing an `unsafe`
|
||||||
block allows you to ask the compiler to trust you. In this case, the _internal_
|
block allows you to ask the compiler to trust you. In this case, the _internal_
|
||||||
implementation of the mutex is considered unsafe, but the _external_ interface
|
implementation of the mutex is considered unsafe, but the _external_ interface
|
||||||
we present is safe. This allows it to be effectively used in normal Rust, while
|
we present is safe. This allows it to be effectively used in normal Rust, while
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue