```
Our distance calculation works regardless of our `Edge` type, so the `E` stuff in
-this signature is just a distraction.
+this signature is a distraction.
What we really want to say is that a certain `E`dge and `N`ode type come together
to form each kind of `Graph`. We can do that with associated types:
This silly implementation always returns `true` and an empty `Vec<Edge>`, 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 going to
use `struct`s for all three here.
-Next is the `impl` line, which is just like implementing any other trait.
+Next is the `impl` line, which is an implementation like 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
The `transmute` function is provided by a [compiler intrinsic][intrinsics], and
what it does is very simple, but very scary. It tells Rust to treat a value of
one type as though it were another type. It does this regardless of the
-typechecking system, and just completely trusts you.
+typechecking system, and completely trusts you.
[intrinsics]: intrinsics.html
## `*const T` and `*mut T`
-These are C-like raw pointers with no lifetime or ownership attached to them. They just point to
+These are C-like raw pointers with no lifetime or ownership attached to them. They point to
some location in memory with no other restrictions. The only guarantee that these provide is that
they cannot be dereferenced except in code marked `unsafe`.
## `Arc<T>`
-[`Arc<T>`][arc] is just a version of `Rc<T>` that uses an atomic reference count (hence, "Arc").
+[`Arc<T>`][arc] is a version of `Rc<T>` that uses an atomic reference count (hence, "Arc").
This can be sent freely between threads.
C++'s `shared_ptr` is similar to `Arc`, however in the case of C++ the inner data is always mutable.
# Taking closures as arguments
Now that we know that closures are traits, we already know how to accept and
-return closures: just like any other trait!
+return closures: the same as 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
assert_eq!(3, answer);
```
-We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it
+We pass our closure, `|x| x + 2`, to `call_with_one`. It 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:
we have a `[closure@<anon>:7:9: 7:20]`. Wait, what?
Because each closure generates its own environment `struct` and implementation
-of `Fn` and friends, these types are anonymous. They exist just solely for
+of `Fn` and friends, these types are anonymous. They exist solely for
this closure. So Rust shows them as `closure@<anon>`, rather than some
autogenerated name.
}
```
-We use the `mpsc::channel()` method to construct a new channel. We just `send`
+We use the `mpsc::channel()` method to construct a new channel. We `send`
a simple `()` down the channel, and then wait for ten of them to come back.
-While this channel is just sending a generic signal, we can send any data that
+While this channel is sending a generic signal, we can send any data that
is `Send` over the channel!
```rust
}
```
-Of course, you can copy and paste this from this web page, or just type
+Of course, you can copy and paste this from this web page, or type
something else. It’s not important that you actually put ‘konnichiwa’ to learn
about the module system.
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`
-to just this:
+to only this:
```rust,ignore
extern crate phrases;
## 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 only 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.
```
As you can see, the curly brackets compress `use` statements for several items
-under the same path, and in this context `self` just refers back to that path.
+under the same path, and in this context `self` refers back to that path.
Note: The curly brackets cannot be nested or mixed with star globbing.
The compiler currently ships two default allocators: `alloc_system` and
`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
-are just normal Rust crates and contain an implementation of the routines to
+are normal Rust crates and contain an implementation of the routines to
allocate and deallocate memory. The standard library is not compiled assuming
either one, and the compiler will decide which allocator is in use at
compile-time depending on the type of output artifact being produced.
size
}
-# // just needed to get rustdoc to test this
+# // only needed to get rustdoc to test this
# fn main() {}
# #[lang = "panic_fmt"] fn panic_fmt() {}
# #[lang = "eh_personality"] fn eh_personality() {}
```
This will highlight according to whatever language you're showing off.
-If you're just showing plain text, choose `text`.
+If you're only showing plain text, choose `text`.
It's important to choose the correct annotation here, because `rustdoc` uses it
in an interesting way: It can be used to actually test your examples in a
can use this to your advantage. In this case, documentation comments need
to apply to some kind of function, so if I want to show you just a
documentation comment, I need to add a little function definition below
-it. At the same time, it's just there to satisfy the compiler, so hiding
+it. At the same time, it's only there to satisfy the compiler, so hiding
it makes the example more clear. You can use this technique to explain
longer examples in detail, while still preserving the testability of your
documentation.
# fn foo() {}
```
-is just
+is:
~~~markdown
# Examples
panic is embedded in the calls to `unwrap`.
To “unwrap” something in Rust is to say, “Give me the result of the
-computation, and if there was an error, just panic and stop the program.”
-It would be better if we just showed the code for unwrapping because it is so
+computation, and if there was an error, panic and stop the program.”
+It would be better if we showed the code for unwrapping because it is so
simple, but to do that, we will first need to explore the `Option` and `Result`
types. Both of these types have a method called `unwrap` defined on them.
}
```
-Notice that when this function finds a matching character, it doesn't just
+Notice that when this function finds a matching character, it doesn't only
return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or
a *value constructor* for the `Option` type. You can think of it as a function
with the type `fn<T>(value: T) -> Option<T>`. Correspondingly, `None` is also a
not all file names have a `.` in them, so it's possible that the file name has
no extension. This *possibility of absence* is encoded into the types using
`Option<T>`. In other words, the compiler will force us to address the
-possibility that an extension does not exist. In our case, we just print out a
+possibility that an extension does not exist. In our case, we only print out a
message saying as such.
Getting the extension of a file name is a pretty common operation, so it makes
In fact, the case analysis in `extension_explicit` follows a very common
pattern: *map* a function on to the value inside of an `Option<T>`, unless the
-option is `None`, in which case, just return `None`.
+option is `None`, in which case, return `None`.
Rust has parametric polymorphism, so it is very easy to define a combinator
that abstracts this pattern:
}
```
-You might think that we could just use the `map` combinator to reduce the case
+You might think that we could use the `map` combinator to reduce the case
analysis, but its type doesn't quite fit. Namely, `map` takes a function that
does something only with the inner value. The result of that function is then
*always* [rewrapped with `Some`](#code-option-map). Instead, we need something
with both an `Option` and a `Result`, the solution is *usually* to convert the
`Option` to a `Result`. In our case, the absence of a command line parameter
(from `env::args()`) means the user didn't invoke the program correctly. We
-could just use a `String` to describe the error. Let's try:
+could use a `String` to describe the error. Let's try:
<span id="code-error-double-string"></span>
The other new combinator used here is
[`Result::map_err`](../std/result/enum.Result.html#method.map_err).
-This is just like `Result::map`, except it maps a function on to the *error*
+This is like `Result::map`, except it maps a function on to the *error*
portion of a `Result` value. If the `Result` is an `Ok(...)` value, then it is
returned unmodified.
an `i32`) by `2`. If an error had occurred before that point, this operation
would have been skipped because of how `map` is defined.
-`map_err` is the trick that makes all of this work. `map_err` is just like
+`map_err` is the trick that makes all of this work. `map_err` is like
`map`, except it applies a function to the `Err(...)` value of a `Result`. In
this case, we want to convert all of our errors to one type: `String`. Since
both `io::Error` and `num::ParseIntError` implement `ToString`, we can call the
## The `try!` macro
A cornerstone of error handling in Rust is the `try!` macro. The `try!` macro
-abstracts case analysis just like combinators, but unlike combinators, it also
+abstracts case analysis like combinators, but unlike combinators, it also
abstracts *control flow*. Namely, it can abstract the *early return* pattern
seen above.
[`ErrorKind`](../std/io/enum.ErrorKind.html)) or keep it hidden (like
[`ParseIntError`](../std/num/struct.ParseIntError.html)). Regardless
of how you do it, it's usually good practice to at least provide some
-information about the error beyond just its `String`
+information about the error beyond its `String`
representation. But certainly, this will vary depending on use cases.
At a minimum, you should probably implement the
The data we'll be using comes from the [Data Science
Toolkit][11]. I've prepared some data from it for this exercise. You
can either grab the [world population data][12] (41MB gzip compressed,
-145MB uncompressed) or just the [US population data][13] (2.2MB gzip
+145MB uncompressed) or only the [US population data][13] (2.2MB gzip
compressed, 7.2MB uncompressed).
Up until now, we've kept the code limited to Rust's standard library. For a real
[Previously](#the-limits-of-combinators) we started refactoring our code by
changing the type of our function from `T` to `Result<T, OurErrorType>`. In
-this case, `OurErrorType` is just `Box<Error>`. But what's `T`? And can we add
+this case, `OurErrorType` is only `Box<Error>`. But what's `T`? And can we add
a return type to `main`?
The answer to the second question is no, we can't. That means we'll need to
But how can we use the same code over both types? There's actually a
couple ways we could go about this. One way is to write `search` such
that it is generic on some type parameter `R` that satisfies
-`io::Read`. Another way is to just use trait objects:
+`io::Read`. Another way is to use trait objects:
```rust,ignore
fn search<P: AsRef<Path>>
...
```
-Now we just need to implement our “quiet” functionality. This requires us to
+Now we only need to implement our “quiet” functionality. This requires us to
tweak the case analysis in `main`:
```rust,ignore
heuristics!
* If you're writing short example code that would be overburdened by error
- handling, it's probably just fine to use `unwrap` (whether that's
+ handling, it's probably fine to use `unwrap` (whether that's
[`Result::unwrap`](../std/result/enum.Result.html#method.unwrap),
[`Option::unwrap`](../std/option/enum.Option.html#method.unwrap)
or preferably
A few examples of how this model can be used are:
* A native build dependency. Sometimes some C/C++ glue is needed when writing
- some Rust code, but distribution of the C/C++ code in a library format is just
+ some Rust code, but distribution of the C/C++ code in a library format is
a burden. In this case, the code will be archived into `libfoo.a` and then the
Rust crate would declare a dependency via `#[link(name = "foo", kind =
"static")]`.
architecture, this means that the abi used would be `stdcall`. On x86_64,
however, windows uses the `C` calling convention, so `C` would be used. This
means that in our previous example, we could have used `extern "system" { ... }`
-to define a block for all windows systems, not just x86 ones.
+to define a block for all windows systems, not only x86 ones.
# Interoperability with foreign code
Rust: ‘declaration statements’ and ‘expression statements’. Everything else is
an expression. Let’s talk about declaration statements first.
-In some languages, variable bindings can be written as expressions, not just
+In some languages, variable bindings can be written as expressions, not
statements. Like Ruby:
```ruby
expression, although its value is not particularly useful. Unlike other
languages where an assignment evaluates to the assigned value (e.g. `5` in the
previous example), in Rust the value of an assignment is an empty tuple `()`
-because the assigned value can have [just one owner](ownership.html), and any
+because the assigned value can have [only one owner](ownership.html), and any
other returned value would be too surprising:
```rust
// found `core::option::Option<_>` (expected f64 but found integral variable)
```
-That doesn’t mean we can’t make `Option<T>`s that hold an `f64`! They just have
+That doesn’t mean we can’t make `Option<T>`s that hold an `f64`! They have
to match up:
```rust
Similar to functions, the `<T>` is where we declare the generic parameters,
and we then use `x: T` in the type declaration, too.
-When you want to add an implementation for the generic `struct`, you just
+When you want to add an implementation for the generic `struct`, you
declare the type parameter after the `impl`:
```rust
## Uninstalling
-Uninstalling Rust is as easy as installing it. On Linux or Mac, just run
+Uninstalling Rust is as easy as installing it. On Linux or Mac, run
the uninstall script:
```bash
The nice thing about starting with such a simple program is that you can
quickly verify that your compiler is installed, and that it's working properly.
-Printing information to the screen is also just a pretty common thing to do, so
+Printing information to the screen is also a pretty common thing to do, so
practicing it early on is good.
> Note: This book assumes basic familiarity with the command line. Rust itself
Hello, world!
```
-In Windows, just replace `main` with `main.exe`. Regardless of your operating
+In Windows, replace `main` with `main.exe`. Regardless of your operating
system, you should see the string `Hello, world!` print to the terminal. If you
did, then congratulations! You've officially written a Rust program. That makes
you a Rust programmer! Welcome.
The second important part is the `println!()` line. This is calling a Rust
*[macro]*, 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 Rust macros in more detail later, but for now you just need to
+discuss Rust macros in more detail later, but for now you only need to
know that when you see a `!` that means that you’re calling a macro instead of
a normal function.
The first line, `[package]`, indicates that the following statements are
configuring a package. As we add more information to this file, we’ll add other
-sections, but for now, we just have the package configuration.
+sections, but for now, we only have the package configuration.
The other three lines set the three bits of configuration that Cargo needs to
know to compile your program: its name, what version it is, and who wrote it.
With simple projects, Cargo doesn't bring a whole lot over just using `rustc`,
but it will become useful in future. With complex projects composed of multiple
crates, it’s much easier to let Cargo coordinate the build. With Cargo, you can
-just run `cargo build`, and it should work the right way.
+run `cargo build`, and it should work the right way.
## Building for Release
```
Great! The `run` command comes in handy when you need to rapidly iterate on a
-project. Our game is just such a project, we need to quickly test each
+project. Our game is such a project, we need to quickly test each
iteration before moving on to the next one.
# Processing a Guess
Rust warns us that we haven’t used the `Result` value. This warning comes from
a special annotation that `io::Result` has. Rust is trying to tell you that
you haven’t handled a possible error. The right way to suppress the error is
-to actually write error handling. Luckily, if we just want to crash if there’s
+to actually write error handling. Luckily, if we want to crash if there’s
a problem, we can use these two little methods. If we can recover from the
error somehow, we’d do something else, but we’ll save that for a future
project.
-There’s just one line of this first example left:
+There’s only one line of this first example left:
```rust,ignore
println!("You guessed: {}", guess);
That’s right, no output! Cargo knows that our project has been built, and that
all of its dependencies are built, and so there’s no reason to do all that
stuff. With nothing to do, it simply exits. If we open up `src/main.rs` again,
-make a trivial change, and then save it again, we’ll just see one line:
+make a trivial change, and then save it again, we’ll only see one line:
```bash
$ cargo build
[concurrency]: concurrency.html
-The second line just prints out the secret number. This is useful while
+The second line prints out the secret number. This is useful while
we’re developing our program, so we can easily test it out. But we’ll be
deleting it for the final version. It’s not much of a game if it prints out
the answer when you start it up!
the beginning and end of our string. This is important, as we had to press the
‘return’ key to satisfy `read_line()`. This means that if we type `5` and hit
return, `guess` looks like this: `5\n`. The `\n` represents ‘newline’, the
-enter key. `trim()` gets rid of this, leaving our string with just the `5`. The
+enter key. `trim()` gets rid of this, leaving our string with only the `5`. The
[`parse()` method on strings][parse] parses a string into some kind of number.
Since it can parse a variety of numbers, we need to give Rust a hint as to the
exact type of number we want. Hence, `let guess: u32`. The colon (`:`) after
By adding the `break` line after the `You win!`, we’ll exit the loop when we
win. Exiting the loop also means exiting the program, since it’s the last
-thing in `main()`. We have just one more tweak to make: when someone inputs a
-non-number, we don’t want to quit, we just want to ignore it. We can do that
+thing in `main()`. We have only one more tweak to make: when someone inputs a
+non-number, we don’t want to quit, we want to ignore it. We can do that
like this:
```rust,ignore
```
This is how you generally move from ‘crash on error’ to ‘actually handle the
-returned by `parse()` is an `enum` just like `Ordering`, but in this case, each
+returned by `parse()` is an `enum` like `Ordering`, but in this case, each
variant has some data associated with it: `Ok` is a success, and `Err` is a
failure. Each contains more information: the successfully parsed integer, or an
error type. In this case, we `match` on `Ok(num)`, which sets the inner value
-of the `Ok` to the name `num`, and then we just return it on the right-hand
-side. In the `Err` case, we don’t care what kind of error it is, so we just
+of the `Ok` to the name `num`, and then we return it on the right-hand
+side. In the `Err` case, we don’t care what kind of error it is, so we
use `_` instead of a name. This ignores the error, and `continue` causes us
to go to the next iteration of the `loop`.
`None`, we `break` out of the loop.
This code sample is basically the same as our `for` loop version. The `for`
-loop is just a handy way to write this `loop`/`match`/`break` construct.
+loop is a handy way to write this `loop`/`match`/`break` construct.
`for` loops aren't the only thing that uses iterators, however. Writing your
own iterator involves implementing the `Iterator` trait. While doing that is
references? Firstly, because we explicitly asked it to with
`&`. Secondly, if it gave us the data itself, we would have to be its
owner, which would involve making a copy of the data and giving us the
-copy. With references, we're just borrowing a reference to the data,
-and so it's just passing a reference, without needing to do the move.
+copy. With references, we're only borrowing a reference to the data,
+and so it's only passing a reference, without needing to do the move.
So, now that we've established that ranges are often not what you want, let's
talk about what you do want instead.
```
If you are trying to execute a closure on an iterator for its side effects,
-just use `for` instead.
+use `for` instead.
There are tons of interesting iterator adaptors. `take(n)` will return an
iterator over the next `n` elements of the original iterator. Let's try it out
discuss the `<>`s after a function’s name. A function can have ‘generic
parameters’ between the `<>`s, of which lifetimes are one kind. We’ll discuss
other kinds of generics [later in the book][generics], but for now, let’s
-just focus on the lifetimes aspect.
+focus on the lifetimes aspect.
[functions]: functions.html
[generics]: generics.html
...(x: &'a mut i32)
```
-If you compare `&mut i32` to `&'a mut i32`, they’re the same, it’s just that
+If you compare `&mut i32` to `&'a mut i32`, they’re the same, it’s that
the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut
i32` as ‘a mutable reference to an `i32`’ and `&'a mut i32` as ‘a mutable
reference to an `i32` with the lifetime `'a`’.
```
As you can see, we need to declare a lifetime for `Foo` in the `impl` line. We repeat
-`'a` twice, just like on functions: `impl<'a>` defines a lifetime `'a`, and `Foo<'a>`
+`'a` twice, like on functions: `impl<'a>` defines a lifetime `'a`, and `Foo<'a>`
uses it.
## Multiple lifetimes
Methods take a special first parameter, of which there are three variants:
`self`, `&self`, and `&mut self`. You can think of this first parameter as
being the `foo` in `foo.bar()`. The three variants correspond to the three
-kinds of things `foo` could be: `self` if it’s just a value on the stack,
+kinds of things `foo` could be: `self` if it’s a value on the stack,
`&self` if it’s a reference, and `&mut self` if it’s a mutable reference.
-Because we took the `&self` parameter to `area`, we can use it just like any
+Because we took the `&self` parameter to `area`, we can use it like any
other parameter. Because we know it’s a `Circle`, we can access the `radius`
-just like we would with any other `struct`.
+like we would with any other `struct`.
We should default to using `&self`, as you should prefer borrowing over taking
ownership, as well as taking immutable references over mutable ones. Here’s an
# Circle } }
```
-We just say we’re returning a `Circle`. With this method, we can grow a new
+We say we’re returning a `Circle`. With this method, we can grow a new
`Circle` to any arbitrary size.
# Associated functions
$ sudo /usr/local/lib/rustlib/uninstall.sh
```
-If you used the Windows installer, just re-run the `.msi` and it will give you
+If you used the Windows installer, re-run the `.msi` and it will give you
an uninstall option.
Some people, and somewhat rightfully so, get very upset when we tell you to
platform upon release, but if we're honest, the Windows experience isn't as
integrated as the Linux/OS X experience is. We're working on it! If anything
does not work, it is a bug. Please let us know if that happens. Each and every
-commit is tested against Windows just like any other platform.
+commit is tested against Windows like any other platform.
If you've got Rust installed, you can open up a shell, and type this:
The core library has very few dependencies and is much more portable than the
standard library itself. Additionally, the core library has most of the
necessary functionality for writing idiomatic and effective Rust code. When
-using `#![no_std]`, Rust will automatically inject the `core` crate, just like
+using `#![no_std]`, Rust will automatically inject the `core` crate, like
we do for `std` when we’re using it.
As an example, here is a program that will calculate the dot product of two
}
```
-For `HasArea` and `Square`, we just declare a type parameter `T` and replace
+For `HasArea` and `Square`, we declare a type parameter `T` and replace
`f64` with it. The `impl` needs more involved modifications:
```ignore
This prints `x is 0`.
-You can do this kind of match on any member, not just the first:
+You can do this kind of match on any member, not only the first:
```rust
struct Point {
```
In the first arm, we bind the value inside the `Ok` variant to `value`. But
-in the `Err` arm, we use `_` to disregard the specific error, and just print
+in the `Err` arm, we use `_` to disregard the specific error, and print
a general error message.
`_` is valid in any pattern that creates a binding. This can be useful to
```
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
-just the `5`. In other words, the precedence of `if` behaves like this:
+only the `5`. In other words, the precedence of `if` behaves like this:
```text
(4 | 5) if y => ...
A ‘slice’ is a reference to (or “view” into) another data structure. They are
useful for allowing safe, efficient access to a portion of an array without
-copying. For example, you might want to reference just one line of a file read
+copying. For example, you might want to reference only one line of a file read
into memory. By nature, a slice is not created directly, but from an existing
variable binding. Slices have a defined length, can be mutable or immutable.
```rust
let a = [0, 1, 2, 3, 4];
let complete = &a[..]; // A slice containing all of the elements in a
-let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
+let middle = &a[1..4]; // A slice of a: only the elements 1, 2, and 3
```
Slices have type `&[T]`. We’ll talk about that `T` when we cover
let x: (i32, &str) = (1, "hello");
```
-As you can see, the type of a tuple looks just like the tuple, but with each
+As you can see, the type of a tuple looks like the tuple, but with each
position having a type name rather than the value. Careful readers will also
note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
In systems programming languages, strings are a bit more complex than in other
-languages. For now, just read `&str` as a *string slice*, and we’ll learn more
+languages. For now, read `&str` as a *string slice*, and we’ll learn more
soon.
You can assign one tuple into another, if they have the same contained types
```
Remember [before][let] when I said the left-hand side of a `let` statement was more
-powerful than just assigning a binding? Here we are. We can put a pattern on
+powerful than assigning a binding? Here we are. We can put a pattern on
the left-hand side of the `let`, and if it matches up to the right-hand side,
we can assign multiple bindings at once. In this case, `let` “destructures”
or “breaks up” the tuple, and assigns the bits to three bindings.
resource when it goes out of scope. This means that after the call to `foo()`,
we can use our original bindings again.
-References are immutable, just like bindings. This means that inside of `foo()`,
+References are immutable, like bindings. This means that inside of `foo()`,
the vectors can’t be changed at all:
```rust,ignore
this is because `y` is a `&mut` reference. You'll also need to use them for
accessing the contents of a reference as well.
-Otherwise, `&mut` references are just like references. There _is_ a large
+Otherwise, `&mut` references are like references. There _is_ a large
difference between the two, and how they interact, though. You can tell
something is fishy in the above example, because we need that extra scope, with
the `{` and `}`. If we remove them, we get an error:
assert_eq!("foobar", s);
```
-Rust has more than just `&str`s though. A `String`, is a heap-allocated string.
+Rust has more than only `&str`s though. A `String`, is a heap-allocated string.
This string is growable, and is also guaranteed to be UTF-8. `String`s are
commonly created by converting from a string slice using the `to_string`
method.
```
As you can see here, you can extract the inner integer type through a
-destructuring `let`, just as with regular tuples. In this case, the
+destructuring `let`, as with regular tuples. In this case, the
`let Inches(integer_length)` assigns `10` to `integer_length`.
# Unit-like structs
marker type), but in combination with other features, it can become
useful. For instance, a library may ask you to create a structure that
implements a certain [trait][trait] to handle events. If you don’t have
-any data you need to store in the structure, you can just create a
+any data you need to store in the structure, you can create a
unit-like `struct`.
[trait]: traits.html
It works!
The current convention is to use the `tests` module to hold your "unit-style"
-tests. Anything that just tests one small bit of functionality makes sense to
+tests. Anything that tests one small bit of functionality makes sense to
go here. But what about "integration-style" tests instead? For that, we have
the `tests` directory.
Well, when a function gets called, some memory gets allocated for all of its
local variables and some other information. This is called a ‘stack frame’, and
for the purpose of this tutorial, we’re going to ignore the extra information
-and just consider the local variables we’re allocating. So in this case, when
+and only consider the local variables we’re allocating. So in this case, when
`main()` is run, we’ll allocate a single 32-bit integer for our stack frame.
This is automatically handled for you, as you can see; we didn’t have to write
any special Rust code or anything.
| 0 | x | 42 |
Whew! Our stack is growing tall.
-After `italic()` is over, its frame is deallocated, leaving just `bold()` and
+After `italic()` is over, its frame is deallocated, leaving only `bold()` and
`main()`:
| Address | Name | Value |
| **1** | **a**| **5** |
| 0 | x | 42 |
-And then `bold()` ends, leaving just `main()`:
+And then `bold()` ends, leaving only `main()`:
| Address | Name | Value |
|---------|------|-------|
We haven’t really talked too much about what it actually means to allocate and
deallocate memory in these contexts. Getting into very deep detail is out of
the scope of this tutorial, but what’s important to point out here is that
-the heap isn’t just a stack that grows from the opposite end. We’ll have an
+the heap isn’t a stack that grows from the opposite end. We’ll have an
example of this later in the book, but because the heap can be allocated and
freed in any order, it can end up with ‘holes’. Here’s a diagram of the memory
layout of a program which has been running for a while now:
| 1 | y | → 0 |
| 0 | x | 5 |
-Stack frames aren’t just for local bindings, they’re for arguments too. So in
+Stack frames aren’t only for local bindings, they’re for arguments too. So in
this case, we need to have both `i`, our argument, and `z`, our local variable
binding. `i` is a copy of the argument, `y`. Since `y`’s value is `0`, so is
`i`’s.
This is one reason why borrowing a variable doesn’t deallocate any memory: the
-value of a reference is just a pointer to a memory location. If we got rid of
+value of a reference is a pointer to a memory location. If we got rid of
the underlying memory, things wouldn’t work very well.
# A complex example
| 0 | h | 3 |
We end up allocating another value on the heap, and so we have to subtract one
-from (2<sup>30</sup>) - 1. It’s easier to just write that than `1,073,741,822`. In any
+from (2<sup>30</sup>) - 1. It’s easier to write that than `1,073,741,822`. In any
case, we set up the variables as usual.
At the end of `bar()`, it calls `baz()`:
## Runtime Efficiency
-Managing the memory for the stack is trivial: The machine just
+Managing the memory for the stack is trivial: The machine
increments or decrements a single value, the so-called “stack pointer”.
Managing memory for the heap is non-trivial: heap-allocated memory is freed at
arbitrary points, and each block of heap-allocated memory can be of arbitrary
Suppose we’ve got some values that implement `Foo`. 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 pointers anyway):
```rust,ignore
let a: String = "foo".to_string();
```
As you can see, the `trait` block looks very similar to the `impl` block,
-but we don’t define a body, just a type signature. When we `impl` a trait,
-we use `impl Trait for Item`, rather than just `impl Item`.
+but we don’t define a body, only a type signature. When we `impl` a trait,
+we use `impl Trait for Item`, rather than only `impl Item`.
## Trait bounds on generic functions
That’s it. It’s important that `unsafe` does not, for example, ‘turn off the
borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its
-semantics, it won’t just start accepting anything. But it will let you write
+semantics, it won’t start accepting anything. But it will let you write
things that _do_ break some of the rules.
You will also encounter the `unsafe` keyword when writing bindings to foreign
are three:
1. We can only manipulate an instance of an unsized type via a pointer. An
- `&[T]` works just fine, but a `[T]` does not.
+ `&[T]` works fine, but a `[T]` does not.
2. Variables and arguments cannot have dynamically sized types.
3. Only the last field in a `struct` may have a dynamically sized type; the
other fields must not. Enum variants must not have dynamically sized types as
Virtually every non-'Hello World’ Rust program uses *variable bindings*. They
bind some value to a name, so it can be used later. `let` is
-used to introduce a binding, just like this:
+used to introduce a binding, like this:
```rust
fn main() {
In many languages, a variable binding would be called a *variable*, but Rust’s
variable bindings have a few tricks up their sleeves. For example the
-left-hand side of a `let` expression is a ‘[pattern][pattern]’, not just a
+left-hand side of a `let` expression is a ‘[pattern][pattern]’, not a
variable name. This means we can do things like:
```rust
After this expression is evaluated, `x` will be one, and `y` will be two.
Patterns are really powerful, and have [their own section][pattern] in the
-book. We don’t need those features for now, so we’ll just keep this in the back
+book. We don’t need those features for now, so we’ll keep this in the back
of our minds as we go forward.
[pattern]: patterns.html
want `x` to be the value we’re interpolating. The comma is used to separate
arguments we pass to functions and macros, if you’re passing more than one.
-When you just use the curly braces, Rust will attempt to display the value in a
+When you use the curly braces, Rust will attempt to display the value in a
meaningful way by checking out its type. If you want to specify the format in a
more detailed manner, there are a [wide number of options available][format].
-For now, we'll just stick to the default: integers aren't very complicated to
+For now, we'll stick to the default: integers aren't very complicated to
print.
[format]: ../std/fmt/index.html