From 0070625495709bb2f6020d9d1ae628f8f035358f Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Tue, 21 Apr 2015 13:17:43 -0400 Subject: [PATCH] small edits for recently written book chapters --- src/doc/trpl/associated-types.md | 16 +++--- src/doc/trpl/closures.md | 60 ++++++++++----------- src/doc/trpl/crates-and-modules.md | 86 +++++++++++++++--------------- src/doc/trpl/macros.md | 84 ++++++++++++++--------------- src/doc/trpl/trait-objects.md | 44 +++++++-------- 5 files changed, 145 insertions(+), 145 deletions(-) diff --git a/src/doc/trpl/associated-types.md b/src/doc/trpl/associated-types.md index d59239016d881..55e2787cc2591 100644 --- a/src/doc/trpl/associated-types.md +++ b/src/doc/trpl/associated-types.md @@ -1,8 +1,8 @@ % Associated Types -Associated types are a powerful part of Rust's type system. They're related to -the idea of a 'type family', in other words, grouping multiple types together. That -description is a bit abstract, so let's dive right into an example. If you want +Associated types are a powerful part of Rust’s type system. They’re related to +the idea of a ‘type family’, in other words, grouping multiple types together. That +description is a bit abstract, so let’s dive right into an example. If you want to write a `Graph` trait, you have two types to be generic over: the node type and the edge type. So you might write a trait, `Graph`, that looks like this: @@ -48,11 +48,11 @@ fn distance(graph: &G, start: &G::N, end: &G::N) -> uint { ... } No need to deal with the `E`dge type here! -Let's go over all this in more detail. +Let’s go over all this in more detail. ## Defining associated types -Let's build that `Graph` trait. Here's the definition: +Let’s build that `Graph` trait. Here’s the definition: ```rust trait Graph { @@ -86,7 +86,7 @@ trait Graph { ## Implementing associated types Just like any trait, traits that use associated types use the `impl` keyword to -provide implementations. Here's a simple implementation of Graph: +provide implementations. Here’s a simple implementation of Graph: ```rust # trait Graph { @@ -118,13 +118,13 @@ impl Graph for MyGraph { This silly implementation always returns `true` and an empty `Vec`, but it gives you an idea of how to implement this kind of thing. We first need three `struct`s, one for the graph, one for the node, and one for the edge. If it made -more sense to use a different type, that would work as well, we're just going to +more sense to use a different type, that would work as well, we’re just going to use `struct`s for all three here. Next is the `impl` line, which is just like implementing any other trait. From here, we use `=` to define our associated types. The name the trait uses -goes on the left of the `=`, and the concrete type we're `impl`ementing this +goes on the left of the `=`, and the concrete type we’re `impl`ementing this for goes on the right. Finally, we use the concrete types in our function declarations. diff --git a/src/doc/trpl/closures.md b/src/doc/trpl/closures.md index e3de8eb30be91..604dcb739df63 100644 --- a/src/doc/trpl/closures.md +++ b/src/doc/trpl/closures.md @@ -1,9 +1,9 @@ % Closures Rust not only has named functions, but anonymous functions as well. Anonymous -functions that have an associated environment are called 'closures', because they +functions that have an associated environment are called ‘closures’, because they close over an environment. Rust has a really great implementation of them, as -we'll see. +we’ll see. # Syntax @@ -15,7 +15,7 @@ let plus_one = |x: i32| x + 1; assert_eq!(2, plus_one(1)); ``` -We create a binding, `plus_one`, and assign it to a closure. The closure's +We create a binding, `plus_one`, and assign it to a closure. The closure’s arguments go between the pipes (`|`), and the body is an expression, in this case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line closures too: @@ -33,7 +33,7 @@ let plus_two = |x| { assert_eq!(4, plus_two(2)); ``` -You'll notice a few things about closures that are a bit different than regular +You’ll notice a few things about closures that are a bit different than regular functions defined with `fn`. The first of which is that we did not need to annotate the types of arguments the closure takes or the values it returns. We can: @@ -44,13 +44,13 @@ let plus_one = |x: i32| -> i32 { x + 1 }; assert_eq!(2, plus_one(1)); ``` -But we don't have to. Why is this? Basically, it was chosen for ergonomic reasons. +But we don’t have to. Why is this? Basically, it was chosen for ergonomic reasons. While specifying the full type for named functions is helpful with things like documentation and type inference, the types of closures are rarely documented since they’re anonymous, and they don’t cause the kinds of error-at-a-distance that inferring named function types can. -The second is that the syntax is similar, but a bit different. I've added spaces +The second is that the syntax is similar, but a bit different. I’ve added spaces here to make them look a little closer: ```rust @@ -59,11 +59,11 @@ let plus_one_v2 = |x: i32 | -> i32 { x + 1 }; let plus_one_v3 = |x: i32 | x + 1 ; ``` -Small differences, but they're similar in ways. +Small differences, but they’re similar in ways. # Closures and their environment -Closures are called such because they 'close over their environment.' It +Closures are called such because they ‘close over their environment’. It looks like this: ```rust @@ -105,7 +105,7 @@ fn main() { ^ ``` -A verbose yet helpful error message! As it says, we can't take a mutable borrow +A verbose yet helpful error message! As it says, we can’t take a mutable borrow on `num` because the closure is already borrowing it. If we let the closure go out of scope, we can: @@ -140,7 +140,7 @@ let takes_nums = || nums; ``` `Vec` has ownership over its contents, and therefore, when we refer to it -in our closure, we have to take ownership of `nums`. It's the same as if we'd +in our closure, we have to take ownership of `nums`. It’s the same as if we’d passed `nums` to a function that took ownership of it. ## `move` closures @@ -156,7 +156,7 @@ let owns_num = move |x: i32| x + num; Now, even though the keyword is `move`, the variables follow normal move semantics. In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy -of `num`. So what's the difference? +of `num`. So what’s the difference? ```rust let mut num = 5; @@ -171,11 +171,11 @@ assert_eq!(10, num); ``` So in this case, our closure took a mutable reference to `num`, and then when -we called `add_num`, it mutated the underlying value, as we'd expect. We also +we called `add_num`, it mutated the underlying value, as we’d expect. We also needed to declare `add_num` as `mut` too, because we’re mutating its environment. -If we change to a `move` closure, it's different: +If we change to a `move` closure, it’s different: ```rust let mut num = 5; @@ -203,8 +203,8 @@ you tons of control over what your code does, and closures are no different. # Closure implementation -Rust's implementation of closures is a bit different than other languages. They -are effectively syntax sugar for traits. You'll want to make sure to have read +Rust’s implementation of closures is a bit different than other languages. They +are effectively syntax sugar for traits. You’ll want to make sure to have read the [traits chapter][traits] before this one, as well as the chapter on [trait objects][trait-objects]. @@ -237,9 +237,9 @@ pub trait FnOnce { # } ``` -You'll notice a few differences between these traits, but a big one is `self`: +You’ll notice a few differences between these traits, but a big one is `self`: `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This -covers all three kinds of `self` via the usual method call syntax. But we've +covers all three kinds of `self` via the usual method call syntax. But we’ve split them up into three traits, rather than having a single one. This gives us a large amount of control over what kind of closures we can take. @@ -253,7 +253,7 @@ Now that we know that closures are traits, we already know how to accept and return closures: just like any other trait! This also means that we can choose static vs dynamic dispatch as well. First, -let's write a function which takes something callable, calls it, and returns +let’s write a function which takes something callable, calls it, and returns the result: ```rust @@ -271,7 +271,7 @@ assert_eq!(3, answer); We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it suggests: it calls the closure, giving it `1` as an argument. -Let's examine the signature of `call_with_one` in more depth: +Let’s examine the signature of `call_with_one` in more depth: ```rust fn call_with_one(some_closure: F) -> i32 @@ -280,7 +280,7 @@ fn call_with_one(some_closure: F) -> i32 ``` We take one parameter, and it has the type `F`. We also return a `i32`. This part -isn't interesting. The next part is: +isn’t interesting. The next part is: ```rust # fn call_with_one(some_closure: F) -> i32 @@ -292,9 +292,9 @@ Because `Fn` is a trait, we can bound our generic with it. In this case, our clo takes a `i32` as an argument and returns an `i32`, and so the generic bound we use is `Fn(i32) -> i32`. -There's one other key point here: because we're bounding a generic with a -trait, this will get monomorphized, and therefore, we'll be doing static -dispatch into the closure. That's pretty neat. In many langauges, closures are +There’s one other key point here: because we’re bounding a generic with a +trait, this will get monomorphized, and therefore, we’ll be doing static +dispatch into the closure. That’s pretty neat. In many langauges, closures are inherently heap allocated, and will always involve dynamic dispatch. In Rust, we can stack allocate our closure environment, and statically dispatch the call. This happens quite often with iterators and their adapters, which often @@ -320,7 +320,7 @@ to our closure when we pass it to `call_with_one`, so we use `&||`. It’s very common for functional-style code to return closures in various situations. If you try to return a closure, you may run into an error. At -first, it may seem strange, but we'll figure it out. Here's how you'd probably +first, it may seem strange, but we’ll figure it out. Here’s how you’d probably try to return a closure from a function: ```rust,ignore @@ -361,7 +361,7 @@ In order to return something from a function, Rust needs to know what size the return type is. But since `Fn` is a trait, it could be various things of various sizes: many different types can implement `Fn`. An easy way to give something a size is to take a reference to it, as references -have a known size. So we'd write this: +have a known size. So we’d write this: ```rust,ignore fn factory() -> &(Fn(i32) -> Vec) { @@ -385,7 +385,7 @@ fn factory() -> &(Fn(i32) -> i32) { ``` Right. Because we have a reference, we need to give it a lifetime. But -our `factory()` function takes no arguments, so elision doesn't kick in +our `factory()` function takes no arguments, so elision doesn’t kick in here. What lifetime can we choose? `'static`: ```rust,ignore @@ -414,7 +414,7 @@ error: mismatched types: ``` -This error is letting us know that we don't have a `&'static Fn(i32) -> i32`, +This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`, we have a `[closure :7:9: 7:20]`. Wait, what? Because each closure generates its own environment `struct` and implementation @@ -422,7 +422,7 @@ of `Fn` and friends, these types are anonymous. They exist just solely for this closure. So Rust shows them as `closure `, rather than some autogenerated name. -But why doesn't our closure implement `&'static Fn`? Well, as we discussed before, +But why doesn’t our closure implement `&'static Fn`? Well, as we discussed before, closures borrow their environment. And in this case, our environment is based on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime of the stack frame. So if we returned this closure, the function call would be @@ -445,7 +445,7 @@ assert_eq!(6, answer); # } ``` -We use a trait object, by `Box`ing up the `Fn`. There's just one last problem: +We use a trait object, by `Box`ing up the `Fn`. There’s just one last problem: ```text error: `num` does not live long enough @@ -471,5 +471,5 @@ assert_eq!(6, answer); ``` By making the inner closure a `move Fn`, we create a new stack frame for our -closure. By `Box`ing it up, we've given it a known size, and allowing it to +closure. By `Box`ing it up, we’ve given it a known size, and allowing it to escape our stack frame. diff --git a/src/doc/trpl/crates-and-modules.md b/src/doc/trpl/crates-and-modules.md index 83e8cc629fd5e..3ab3401e61264 100644 --- a/src/doc/trpl/crates-and-modules.md +++ b/src/doc/trpl/crates-and-modules.md @@ -1,16 +1,16 @@ % Crates and Modules -When a project starts getting large, it's considered good software +When a project starts getting large, it’s considered good software engineering practice to split it up into a bunch of smaller pieces, and then -fit them together. It's also important to have a well-defined interface, so +fit them together. It’s also important to have a well-defined interface, so that some of your functionality is private, and some is public. To facilitate these kinds of things, Rust has a module system. # Basic terminology: Crates and Modules -Rust has two distinct terms that relate to the module system: *crate* and -*module*. A crate is synonymous with a *library* or *package* in other -languages. Hence "Cargo" as the name of Rust's package management tool: you +Rust has two distinct terms that relate to the module system: ‘crate’ and +‘module’. A crate is synonymous with a ‘library’ or ‘package’ in other +languages. Hence “Cargo” as the name of Rust’s package management tool: you ship your crates to others with Cargo. Crates can produce an executable or a library, depending on the project. @@ -18,10 +18,10 @@ Each crate has an implicit *root module* that contains the code for that crate. You can then define a tree of sub-modules under that root module. Modules allow you to partition your code within the crate itself. -As an example, let's make a *phrases* crate, which will give us various phrases -in different languages. To keep things simple, we'll stick to "greetings" and -"farewells" as two kinds of phrases, and use English and Japanese (日本語) as -two languages for those phrases to be in. We'll use this module layout: +As an example, let’s make a *phrases* crate, which will give us various phrases +in different languages. To keep things simple, we’ll stick to ‘greetings’ and +‘farewells’ as two kinds of phrases, and use English and Japanese (日本語) as +two languages for those phrases to be in. We’ll use this module layout: ```text +-----------+ @@ -47,7 +47,7 @@ In this example, `phrases` is the name of our crate. All of the rest are modules. You can see that they form a tree, branching out from the crate *root*, which is the root of the tree: `phrases` itself. -Now that we have a plan, let's define these modules in code. To start, +Now that we have a plan, let’s define these modules in code. To start, generate a new crate with Cargo: ```bash @@ -72,7 +72,7 @@ above. # Defining Modules -To define each of our modules, we use the `mod` keyword. Let's make our +To define each of our modules, we use the `mod` keyword. Let’s make our `src/lib.rs` look like this: ``` @@ -101,7 +101,7 @@ Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules with double-colon (`::`) notation: our four nested modules are `english::greetings`, `english::farewells`, `japanese::greetings`, and `japanese::farewells`. Because these sub-modules are namespaced under their -parent module, the names don't conflict: `english::greetings` and +parent module, the names don’t conflict: `english::greetings` and `japanese::greetings` are distinct, even though their names are both `greetings`. @@ -116,11 +116,11 @@ build deps examples libphrases-a7448e02a0468eaa.rlib native ``` `libphrase-hash.rlib` is the compiled crate. Before we see how to use this -crate from another crate, let's break it up into multiple files. +crate from another crate, let’s break it up into multiple files. # Multiple file crates -If each crate were just one file, these files would get very large. It's often +If each crate were just one file, these files would get very large. It’s often easier to split up crates into multiple files, and Rust supports this in two ways. @@ -141,7 +141,7 @@ mod english; If we do that, Rust will expect to find either a `english.rs` file, or a `english/mod.rs` file with the contents of our module. -Note that in these files, you don't need to re-declare the module: that's +Note that in these files, you don’t need to re-declare the module: that’s already been done with the initial `mod` declaration. Using these two techniques, we can break up our crate into two directories and @@ -180,7 +180,7 @@ mod japanese; These two declarations tell Rust to look for either `src/english.rs` and `src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending -on our preference. In this case, because our modules have sub-modules, we've +on our preference. In this case, because our modules have sub-modules, we’ve chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look like this: @@ -192,11 +192,11 @@ mod farewells; Again, these declarations tell Rust to look for either `src/english/greetings.rs` and `src/japanese/greetings.rs` or `src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because -these sub-modules don't have their own sub-modules, we've chosen to make them +these sub-modules don’t have their own sub-modules, we’ve chosen to make them `src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew! The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are -both empty at the moment. Let's add some functions. +both empty at the moment. Let’s add some functions. Put this in `src/english/greetings.rs`: @@ -223,7 +223,7 @@ fn hello() -> String { ``` Of course, you can copy and paste this from this web page, or just type -something else. It's not important that you actually put "konnichiwa" to learn +something else. It’s not important that you actually put ‘konnichiwa’ to learn about the module system. Put this in `src/japanese/farewells.rs`: @@ -234,17 +234,17 @@ fn goodbye() -> String { } ``` -(This is "Sayōnara", if you're curious.) +(This is ‘Sayōnara’, if you’re curious.) -Now that we have some functionality in our crate, let's try to use it from +Now that we have some functionality in our crate, let’s try to use it from another crate. # Importing External Crates -We have a library crate. Let's make an executable crate that imports and uses +We have a library crate. Let’s make an executable crate that imports and uses our library. -Make a `src/main.rs` and put this in it (it won't quite compile yet): +Make a `src/main.rs` and put this in it (it won’t quite compile yet): ```rust,ignore extern crate phrases; @@ -259,7 +259,7 @@ fn main() { ``` The `extern crate` declaration tells Rust that we need to compile and link to -the `phrases` crate. We can then use `phrases`' modules in this one. As we +the `phrases` crate. We can then use `phrases`’ modules in this one. As we mentioned earlier, you can use double colons to refer to sub-modules and the functions inside of them. @@ -267,10 +267,10 @@ Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate, rather than a library crate. Our package now has two crates: `src/lib.rs` and `src/main.rs`. This pattern is quite common for executable crates: most 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. -This doesn't quite work yet, though. We get four errors that look similar to +This doesn’t quite work yet, though. We get four errors that look similar to this: ```bash @@ -287,14 +287,14 @@ note: in expansion of format_args! phrases/src/main.rs:4:5: 4:76 note: expansion site ``` -By default, everything is private in Rust. Let's talk about this in some more +By default, everything is private in Rust. Let’s talk about this in some more depth. # Exporting a Public Interface Rust allows you to precisely control which aspects of your interface are public, and so private is the default. To make things public, you use the `pub` -keyword. Let's focus on the `english` module first, so let's reduce our `src/main.rs` +keyword. Let’s focus on the `english` module first, so let’s reduce our `src/main.rs` to just this: ```{rust,ignore} @@ -306,21 +306,21 @@ fn main() { } ``` -In our `src/lib.rs`, let's add `pub` to the `english` module declaration: +In our `src/lib.rs`, let’s add `pub` to the `english` module declaration: ```{rust,ignore} pub mod english; mod japanese; ``` -And in our `src/english/mod.rs`, let's make both `pub`: +And in our `src/english/mod.rs`, let’s make both `pub`: ```{rust,ignore} pub mod greetings; pub mod farewells; ``` -In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration: +In our `src/english/greetings.rs`, let’s add `pub` to our `fn` declaration: ```{rust,ignore} pub fn hello() -> String { @@ -358,12 +358,12 @@ Goodbye in English: Goodbye. Now that our functions are public, we can use them. Great! However, typing out `phrases::english::greetings::hello()` is very long and repetitive. Rust has another keyword for importing names into the current scope, so that you can -refer to them with shorter names. Let's talk about `use`. +refer to them with shorter names. Let’s talk about `use`. # Importing Modules with `use` Rust has a `use` keyword, which allows us to import names into our local scope. -Let's change our `src/main.rs` to look like this: +Let’s change our `src/main.rs` to look like this: ```{rust,ignore} extern crate phrases; @@ -378,7 +378,7 @@ fn main() { ``` The two `use` lines import each module into the local scope, so we can refer to -the functions by a much shorter name. By convention, when importing functions, it's +the functions by a much shorter name. By convention, when importing functions, it’s considered best practice to import the module, rather than the function directly. In other words, you _can_ do this: @@ -395,7 +395,7 @@ fn main() { ``` But it is not idiomatic. This is significantly more likely to introduce a -naming conflict. In our short program, it's not a big deal, but as it grows, it +naming conflict. In our short program, it’s not a big deal, but as it grows, it becomes a problem. If we have conflicting names, Rust will give a compilation error. For example, if we made the `japanese` functions public, and tried to do this: @@ -423,7 +423,7 @@ error: aborting due to previous error Could not compile `phrases`. ``` -If we're importing multiple names from the same module, we don't have to type it out +If we’re importing multiple names from the same module, we don’t have to type it out twice. Instead of this: ```{rust,ignore} @@ -439,11 +439,11 @@ use phrases::english::{greetings, farewells}; ## Re-exporting with `pub use` -You don't just use `use` to shorten identifiers. You can also use it inside of your crate +You don’t just use `use` to shorten identifiers. You can also use it inside of your crate to re-export a function inside another module. This allows you to present an external interface that may not directly map to your internal code organization. -Let's look at an example. Modify your `src/main.rs` to read like this: +Let’s look at an example. Modify your `src/main.rs` to read like this: ```{rust,ignore} extern crate phrases; @@ -494,11 +494,11 @@ mod farewells; ``` The `pub use` declaration brings the function into scope at this part of our -module hierarchy. Because we've `pub use`d this inside of our `japanese` +module hierarchy. Because we’ve `pub use`d this inside of our `japanese` module, we now have a `phrases::japanese::hello()` function and a `phrases::japanese::goodbye()` function, even though the code for them lives in `phrases::japanese::greetings::hello()` and -`phrases::japanese::farewells::goodbye()`. Our internal organization doesn't +`phrases::japanese::farewells::goodbye()`. Our internal organization doesn’t define our external interface. Here we have a `pub use` for each function we want to bring into the @@ -507,13 +507,13 @@ everything from `greetings` into the current scope: `pub use self::greetings::*` What about the `self`? Well, by default, `use` declarations are absolute paths, starting from your crate root. `self` makes that path relative to your current -place in the hierarchy instead. There's one more special form of `use`: you can +place in the hierarchy instead. There’s one more special form of `use`: you can `use super::` to reach one level up the tree from your current location. Some -people like to think of `self` as `.` and `super` as `..`, from many shells' +people like to think of `self` as `.` and `super` as `..`, from many shells’ display for the current directory and the parent directory. Outside of `use`, paths are relative: `foo::bar()` refers to a function inside -of `foo` relative to where we are. If that's prefixed with `::`, as in +of `foo` relative to where we are. If that’s prefixed with `::`, as in `::foo::bar()`, it refers to a different `foo`, an absolute path from your crate root. diff --git a/src/doc/trpl/macros.md b/src/doc/trpl/macros.md index 1d4452754baa2..9fa870ab1ac7c 100644 --- a/src/doc/trpl/macros.md +++ b/src/doc/trpl/macros.md @@ -1,20 +1,20 @@ % Macros -By now you've learned about many of the tools Rust provides for abstracting and +By now you’ve learned about many of the tools Rust provides for abstracting and reusing code. These units of code reuse have a rich semantic structure. For example, functions have a type signature, type parameters have trait bounds, and overloaded functions must belong to a particular trait. -This structure means that Rust's core abstractions have powerful compile-time +This structure means that Rust’s core abstractions have powerful compile-time correctness checking. But this comes at the price of reduced flexibility. If -you visually identify a pattern of repeated code, you may find it's difficult +you visually identify a pattern of repeated code, you may find it’s difficult or cumbersome to express that pattern as a generic function, a trait, or -anything else within Rust's semantics. +anything else within Rust’s semantics. -Macros allow us to abstract at a *syntactic* level. A macro invocation is +Macros allow us to abstract at a syntactic level. A macro invocation is shorthand for an "expanded" syntactic form. This expansion happens early in compilation, before any static checking. As a result, macros can capture many -patterns of code reuse that Rust's core abstractions cannot. +patterns of code reuse that Rust’s core abstractions cannot. The drawback is that macro-based code can be harder to understand, because fewer of the built-in rules apply. Like an ordinary function, a well-behaved @@ -23,8 +23,8 @@ difficult to design a well-behaved macro! Additionally, compiler errors in macro code are harder to interpret, because they describe problems in the expanded code, not the source-level form that developers use. -These drawbacks make macros something of a "feature of last resort". That's not -to say that macros are bad; they are part of Rust because sometimes they're +These drawbacks make macros something of a "feature of last resort". That’s not +to say that macros are bad; they are part of Rust because sometimes they’re needed for truly concise, well-abstracted code. Just keep this tradeoff in mind. @@ -40,7 +40,7 @@ let x: Vec = vec![1, 2, 3]; # assert_eq!(x, [1, 2, 3]); ``` -This can't be an ordinary function, because it takes any number of arguments. +This can’t be an ordinary function, because it takes any number of arguments. But we can imagine it as syntactic shorthand for ```rust @@ -77,20 +77,20 @@ macro_rules! vec { # } ``` -Whoa, that's a lot of new syntax! Let's break it down. +Whoa, that’s a lot of new syntax! Let’s break it down. ```ignore macro_rules! vec { ... } ``` -This says we're defining a macro named `vec`, much as `fn vec` would define a -function named `vec`. In prose, we informally write a macro's name with an +This says we’re defining a macro named `vec`, much as `fn vec` would define a +function named `vec`. In prose, we informally write a macro’s name with an exclamation point, e.g. `vec!`. The exclamation point is part of the invocation syntax and serves to distinguish a macro from an ordinary function. ## Matching -The macro is defined through a series of *rules*, which are pattern-matching +The macro is defined through a series of rules, which are pattern-matching cases. Above, we had ```ignore @@ -99,13 +99,13 @@ cases. Above, we had This is like a `match` expression arm, but the matching happens on Rust syntax trees, at compile time. The semicolon is optional on the last (here, only) -case. The "pattern" on the left-hand side of `=>` is known as a *matcher*. +case. The "pattern" on the left-hand side of `=>` is known as a ‘matcher’. These have [their own little grammar] within the language. [their own little grammar]: ../reference.html#macros The matcher `$x:expr` will match any Rust expression, binding that syntax tree -to the *metavariable* `$x`. The identifier `expr` is a *fragment specifier*; +to the ‘metavariable’ `$x`. The identifier `expr` is a ‘fragment specifier’; the full possibilities are enumerated in the [advanced macros chapter][]. Surrounding the matcher with `$(...),*` will match zero or more expressions, separated by commas. @@ -158,8 +158,8 @@ Each matched expression `$x` will produce a single `push` statement in the macro expansion. The repetition in the expansion proceeds in "lockstep" with repetition in the matcher (more on this in a moment). -Because `$x` was already declared as matching an expression, we don't repeat -`:expr` on the right-hand side. Also, we don't include a separating comma as +Because `$x` was already declared as matching an expression, we don’t repeat +`:expr` on the right-hand side. Also, we don’t include a separating comma as part of the repetition operator. Instead, we have a terminating semicolon within the repeated block. @@ -180,7 +180,7 @@ The outer braces are part of the syntax of `macro_rules!`. In fact, you can use The inner braces are part of the expanded syntax. Remember, the `vec!` macro is used in an expression context. To write an expression with multiple statements, including `let`-bindings, we use a block. If your macro expands to a single -expression, you don't need this extra layer of braces. +expression, you don’t need this extra layer of braces. Note that we never *declared* that the macro produces an expression. In fact, this is not determined until we use the macro as an expression. With care, you @@ -194,7 +194,7 @@ The repetition operator follows two principal rules: 1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s it contains, in lockstep, and 2. each `$name` must be under at least as many `$(...)*`s as it was matched - against. If it is under more, it'll be duplicated, as appropriate. + against. If it is under more, it’ll be duplicated, as appropriate. This baroque macro illustrates the duplication of variables from outer repetition levels. @@ -219,7 +219,7 @@ fn main() { } ``` -That's most of the matcher syntax. These examples use `$(...)*`, which is a +That’s most of the matcher syntax. These examples use `$(...)*`, which is a "zero or more" match. Alternatively you can write `$(...)+` for a "one or more" match. Both forms optionally include a separator, which can be any token except `+` or `*`. @@ -244,9 +244,9 @@ int main() { ``` After expansion we have `5 * 2 + 3`, and multiplication has greater precedence -than addition. If you've used C macros a lot, you probably know the standard +than addition. If you’ve used C macros a lot, you probably know the standard idioms for avoiding this problem, as well as five or six others. In Rust, we -don't have to worry about it. +don’t have to worry about it. ```rust macro_rules! five_times { @@ -261,8 +261,8 @@ fn main() { The metavariable `$x` is parsed as a single expression node, and keeps its place in the syntax tree even after substitution. -Another common problem in macro systems is *variable capture*. Here's a C -macro, using [a GNU C extension] to emulate Rust's expression blocks. +Another common problem in macro systems is ‘variable capture’. Here’s a C +macro, using [a GNU C extension] to emulate Rust’s expression blocks. [a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html @@ -275,7 +275,7 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks. }) ``` -Here's a simple use case that goes terribly wrong: +Here’s a simple use case that goes terribly wrong: ```text const char *state = "reticulating splines"; @@ -315,10 +315,10 @@ fn main() { ``` This works because Rust has a [hygienic macro system][]. Each macro expansion -happens in a distinct *syntax context*, and each variable is tagged with the -syntax context where it was introduced. It's as though the variable `state` +happens in a distinct ‘syntax context’, and each variable is tagged with the +syntax context where it was introduced. It’s as though the variable `state` inside `main` is painted a different "color" from the variable `state` inside -the macro, and therefore they don't conflict. +the macro, and therefore they don’t conflict. [hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro @@ -336,7 +336,7 @@ fn main() { } ``` -Instead you need to pass the variable name into the invocation, so it's tagged +Instead you need to pass the variable name into the invocation, so it’s tagged with the right syntax context. ```rust @@ -368,7 +368,7 @@ fn main() { # Recursive macros -A macro's expansion can include more macro invocations, including invocations +A macro’s expansion can include more macro invocations, including invocations of the very same macro being expanded. These recursive macros are useful for processing tree-structured input, as illustrated by this (simplistic) HTML shorthand: @@ -429,7 +429,7 @@ they are unstable and require feature gates. Even when Rust code contains un-expanded macros, it can be parsed as a full [syntax tree][ast]. This property can be very useful for editors and other tools that process code. It also has a few consequences for the design of -Rust's macro system. +Rust’s macro system. [ast]: glossary.html#abstract-syntax-tree @@ -454,13 +454,13 @@ consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces must be balanced within a macro invocation. For example, `foo!([)` is forbidden. This allows Rust to know where the macro invocation ends. -More formally, the macro invocation body must be a sequence of *token trees*. +More formally, the macro invocation body must be a sequence of ‘token trees’. A token tree is defined recursively as either * a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or * any other single token. -Within a matcher, each metavariable has a *fragment specifier*, identifying +Within a matcher, each metavariable has a ‘fragment specifier’, identifying which syntactic form it matches. * `ident`: an identifier. Examples: `x`; `foo`. @@ -482,7 +482,7 @@ There are additional rules regarding the next token after a metavariable: * `pat` variables must be followed by one of: `=> , =` * Other variables may be followed by any token. -These rules provide some flexibility for Rust's syntax to evolve without +These rules provide some flexibility for Rust’s syntax to evolve without breaking existing macros. The macro system does not deal with parse ambiguity at all. For example, the @@ -500,7 +500,7 @@ One downside is that scoping works differently for macros, compared to other constructs in the language. Definition and expansion of macros both happen in a single depth-first, -lexical-order traversal of a crate's source. So a macro defined at module scope +lexical-order traversal of a crate’s source. So a macro defined at module scope is visible to any subsequent code in the same module, which includes the body of any subsequent child `mod` items. @@ -508,8 +508,8 @@ A macro defined within the body of a single `fn`, or anywhere else not at module scope, is visible only within that item. If a module has the `macro_use` attribute, its macros are also visible in its -parent module after the child's `mod` item. If the parent also has `macro_use` -then the macros will be visible in the grandparent after the parent's `mod` +parent module after the child’s `mod` item. If the parent also has `macro_use` +then the macros will be visible in the grandparent after the parent’s `mod` item, and so forth. The `macro_use` attribute can also appear on `extern crate`. In this context @@ -524,7 +524,7 @@ If the attribute is given simply as `#[macro_use]`, all macros are loaded. If there is no `#[macro_use]` attribute then no macros are loaded. Only macros defined with the `#[macro_export]` attribute may be loaded. -To load a crate's macros *without* linking it into the output, use `#[no_link]` +To load a crate’s macros without linking it into the output, use `#[no_link]` as well. An example: @@ -619,12 +619,12 @@ only appear at the root of your crate, not inside `mod`. This ensures that The introductory chapter mentioned recursive macros, but it did not give the full story. Recursive macros are useful for another reason: Each recursive -invocation gives you another opportunity to pattern-match the macro's +invocation gives you another opportunity to pattern-match the macro’s arguments. As an extreme example, it is possible, though hardly advisable, to implement the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton -within Rust's macro system. +within Rust’s macro system. ```rust macro_rules! bct { @@ -765,9 +765,9 @@ as `unimplemented!` until you’re ready to write them. # Procedural macros -If Rust's macro system can't do what you need, you may want to write a +If Rust’s macro system can’t do what you need, you may want to write a [compiler plugin](plugins.html) instead. Compared to `macro_rules!` macros, this is significantly more work, the interfaces are much less stable, and bugs can be much harder to track down. In exchange you get the flexibility of running arbitrary Rust code within the compiler. Syntax -extension plugins are sometimes called *procedural macros* for this reason. +extension plugins are sometimes called ‘procedural macros’ for this reason. diff --git a/src/doc/trpl/trait-objects.md b/src/doc/trpl/trait-objects.md index d008d30597fea..52f8cb335a93a 100644 --- a/src/doc/trpl/trait-objects.md +++ b/src/doc/trpl/trait-objects.md @@ -1,15 +1,15 @@ % Trait Objects When code involves polymorphism, there needs to be a mechanism to determine -which specific version is actually run. This is called 'dispatch.' There are +which specific version is actually run. This is called ‘dispatch’. There are two major forms of dispatch: static dispatch and dynamic dispatch. While Rust favors static dispatch, it also supports dynamic dispatch through a mechanism -called 'trait objects.' +called ‘trait objects’. ## Background -For the rest of this chapter, we'll need a trait and some implementations. -Let's make a simple one, `Foo`. It has one method that is expected to return a +For the rest of this chapter, we’ll need a trait and some implementations. +Let’s make a simple one, `Foo`. It has one method that is expected to return a `String`. ```rust @@ -18,7 +18,7 @@ trait Foo { } ``` -We'll also implement this trait for `u8` and `String`: +We’ll also implement this trait for `u8` and `String`: ```rust # trait Foo { fn method(&self) -> String; } @@ -53,7 +53,7 @@ fn main() { } ``` -Rust uses 'monomorphization' to perform static dispatch here. This means that +Rust uses ‘monomorphization’ to perform static dispatch here. This means that Rust will create a special version of `do_something()` for both `u8` and `String`, and then replace the call sites with calls to these specialized functions. In other words, Rust generates something like this: @@ -82,7 +82,7 @@ fn main() { This has a great upside: static dispatch allows function calls to be inlined because the callee is known at compile time, and inlining is the key to good optimization. Static dispatch is fast, but it comes at -a tradeoff: 'code bloat', due to many copies of the same function +a tradeoff: ‘code bloat’, due to many copies of the same function existing in the binary, one for each type. Furthermore, compilers aren’t perfect and may “optimize” code to become slower. @@ -99,7 +99,7 @@ reason. ## Dynamic dispatch -Rust provides dynamic dispatch through a feature called 'trait objects.' Trait +Rust provides dynamic dispatch through a feature called ‘trait objects’. Trait objects, like `&Foo` or `Box`, are normal values that store a value of *any* type that implements the given trait, where the precise type can only be known at runtime. @@ -109,12 +109,12 @@ implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it (e.g. using `&x` as an argument to a function that takes `&Foo`). These trait object coercions and casts also work for pointers like `&mut T` to -`&mut Foo` and `Box` to `Box`, but that's all at the moment. Coercions +`&mut Foo` and `Box` to `Box`, but that’s all at the moment. Coercions and casts are identical. -This operation can be seen as "erasing" the compiler's knowledge about the +This operation can be seen as ‘erasing’ the compiler’s knowledge about the specific type of the pointer, and hence trait objects are sometimes referred to -as "type erasure". +as ‘type erasure’. Coming back to the example above, we can use the same trait to perform dynamic dispatch with trait objects by casting: @@ -167,7 +167,7 @@ on the heap to store it. For `Foo`, we would need to have a value that could be at least either a `String` (24 bytes) or a `u8` (1 byte), as well as any other type for which -dependent crates may implement `Foo` (any number of bytes at all). There's no +dependent crates may implement `Foo` (any number of bytes at all). There’s no way to guarantee that this last point can work if the values are stored without a pointer, because those other types can be arbitrarily large. @@ -177,14 +177,14 @@ when we are tossing a trait object around, only the size of the pointer itself. ### Representation The methods of the trait can be called on a trait object via a special record -of function pointers traditionally called a 'vtable' (created and managed by +of function pointers traditionally called a ‘vtable’ (created and managed by the compiler). Trait objects are both simple and complicated: their core representation and layout is quite straight-forward, but there are some curly error messages and surprising behaviors to discover. -Let's start simple, with the runtime representation of a trait object. The +Let’s start simple, with the runtime representation of a trait object. The `std::raw` module contains structs with layouts that are the same as the complicated built-in types, [including trait objects][stdraw]: @@ -199,12 +199,12 @@ pub struct TraitObject { [stdraw]: ../std/raw/struct.TraitObject.html -That is, a trait object like `&Foo` consists of a "data" pointer and a "vtable" +That is, a trait object like `&Foo` consists of a ‘data’ pointer and a ‘vtable’ pointer. The data pointer addresses the data (of some unknown type `T`) that the trait -object is storing, and the vtable pointer points to the vtable ("virtual method -table") corresponding to the implementation of `Foo` for `T`. +object is storing, and the vtable pointer points to the vtable (‘virtual method +table’) corresponding to the implementation of `Foo` for `T`. A vtable is essentially a struct of function pointers, pointing to the concrete @@ -212,7 +212,7 @@ piece of machine code for each method in the implementation. A method call like `trait_object.method()` will retrieve the correct pointer out of the vtable and then do a dynamic call of it. For example: -```{rust,ignore} +```rust,ignore struct FooVtable { destructor: fn(*mut ()), size: usize, @@ -261,7 +261,7 @@ static Foo_for_String_vtable: FooVtable = FooVtable { ``` The `destructor` field in each vtable points to a function that will clean up -any resources of the vtable's type, for `u8` it is trivial, but for `String` it +any resources of the vtable’s type, for `u8` it is trivial, but for `String` it will free the memory. This is necessary for owning trait objects like `Box`, which need to clean-up both the `Box` allocation as well as the internal type when they go out of scope. The `size` and `align` fields store @@ -270,11 +270,11 @@ essentially unused at the moment since the information is embedded in the destructor, but will be used in the future, as trait objects are progressively made more flexible. -Suppose we've got some values that implement `Foo`, then the explicit form of +Suppose we’ve got some values that implement `Foo`, then the explicit form of construction and use of `Foo` trait objects might look a bit like (ignoring the -type mismatches: they're all just pointers anyway): +type mismatches: they’re all just pointers anyway): -```{rust,ignore} +```rust,ignore let a: String = "foo".to_string(); let x: u8 = 1;