Skip to content

Commit 6d25051

Browse files
committed
Copyedit sections 9 and 10 of the tutorial
1 parent 7582a48 commit 6d25051

File tree

1 file changed

+48
-45
lines changed

1 file changed

+48
-45
lines changed

doc/tutorial.md

+48-45
Original file line numberDiff line numberDiff line change
@@ -1366,7 +1366,7 @@ The indexing operator (`[]`) also auto-dereferences.
13661366
13671367
# Vectors and strings
13681368
1369-
Vectors are a contiguous section of memory containing zero or more
1369+
A vector is a contiguous section of memory containing zero or more
13701370
values of the same type. Like other types in Rust, vectors can be
13711371
stored on the stack, the local heap, or the exchange heap. Borrowed
13721372
pointers to vectors are also called 'slices'.
@@ -1411,10 +1411,10 @@ my_crayons += your_crayons;
14111411
14121412
> ***Note:*** The above examples of vector addition use owned
14131413
> vectors. Some operations on slices and stack vectors are
1414-
> not well supported yet, owned vectors are often the most
1414+
> not yet well-supported. Owned vectors are often the most
14151415
> usable.
14161416
1417-
Indexing into vectors is done with square brackets:
1417+
Square brackets denote indexing into a vector:
14181418
14191419
~~~~
14201420
# enum Crayon { Almond, AntiqueBrass, Apricot,
@@ -1429,7 +1429,7 @@ match crayons[0] {
14291429
~~~~
14301430
14311431
The elements of a vector _inherit the mutability of the vector_,
1432-
and as such individual elements may not be reassigned when the
1432+
and as such, individual elements may not be reassigned when the
14331433
vector lives in an immutable slot.
14341434
14351435
~~~ {.xfail-test}
@@ -1459,13 +1459,13 @@ mutable_crayons[0] = Apricot;
14591459
This is a simple example of Rust's _dual-mode data structures_, also
14601460
referred to as _freezing and thawing_.
14611461

1462-
Strings are implemented with vectors of `u8`, though they have a distinct
1463-
type. They support most of the same allocation options as
1464-
vectors, though the string literal without a storage sigil, e.g.
1465-
`"foo"` is treated differently than a comparable vector (`[foo]`).
1466-
Whereas plain vectors are stack-allocated fixed-length vectors,
1467-
plain strings are region pointers to read-only memory. Strings
1468-
are always immutable.
1462+
Strings are implemented with vectors of `u8`, though they have a
1463+
distinct type. They support most of the same allocation options as
1464+
vectors, though the string literal without a storage sigil (for
1465+
example, `"foo"`) is treated differently than a comparable vector
1466+
(`[foo]`). Whereas plain vectors are stack-allocated fixed-length
1467+
vectors, plain strings are region pointers to read-only
1468+
memory. All strings are immutable.
14691469

14701470
~~~
14711471
// A plain string is a slice to read-only (static) memory
@@ -1528,8 +1528,9 @@ if favorite_crayon_name.len() > 5 {
15281528
# Closures
15291529

15301530
Named functions, like those we've seen so far, may not refer to local
1531-
variables declared outside the function - they do not "close over
1532-
their environment". For example, you couldn't write the following:
1531+
variables declared outside the function: they do not close over their
1532+
environment (sometimes referred to as "capturing" variables in their
1533+
environment). For example, you couldn't write the following:
15331534

15341535
~~~~ {.ignore}
15351536
let foo = 10;
@@ -1552,10 +1553,10 @@ let closure = |arg| println(fmt!("captured_var=%d, arg=%d", captured_var, arg));
15521553
call_closure_with_ten(closure);
15531554
~~~~
15541555

1555-
Closures begin with the argument list between bars and are followed by
1556+
Closures begin with the argument list between vertical bars and are followed by
15561557
a single expression. The types of the arguments are generally omitted,
15571558
as is the return type, because the compiler can almost always infer
1558-
them. In the rare case where the compiler needs assistance though, the
1559+
them. In the rare case where the compiler needs assistance, though, the
15591560
arguments and return types may be annotated.
15601561

15611562
~~~~
@@ -1575,9 +1576,10 @@ let mut max = 0;
15751576
Stack closures are very efficient because their environment is
15761577
allocated on the call stack and refers by pointer to captured
15771578
locals. To ensure that stack closures never outlive the local
1578-
variables to which they refer, they can only be used in argument
1579-
position and cannot be stored in structures nor returned from
1580-
functions. Despite the limitations stack closures are used
1579+
variables to which they refer, stack closures are not
1580+
first-class. That is, they can only be used in argument position; they
1581+
cannot be stored in data structures or returned from
1582+
functions. Despite these limitations, stack closures are used
15811583
pervasively in Rust code.
15821584

15831585
## Managed closures
@@ -1586,12 +1588,12 @@ When you need to store a closure in a data structure, a stack closure
15861588
will not do, since the compiler will refuse to let you store it. For
15871589
this purpose, Rust provides a type of closure that has an arbitrary
15881590
lifetime, written `fn@` (boxed closure, analogous to the `@` pointer
1589-
type described earlier).
1591+
type described earlier). This type of closure *is* first-class.
15901592

15911593
A managed closure does not directly access its environment, but merely
15921594
copies out the values that it closes over into a private data
15931595
structure. This means that it can not assign to these variables, and
1594-
will not 'see' updates to them.
1596+
cannot observe updates to them.
15951597

15961598
This code creates a closure that adds a given string to its argument,
15971599
returns it from a function, and then calls it:
@@ -1608,12 +1610,12 @@ fn main() {
16081610
}
16091611
~~~~
16101612

1611-
This example uses the long closure syntax, `fn@(s: ~str) ...`,
1612-
making the fact that we are declaring a box closure explicit. In
1613-
practice boxed closures are usually defined with the short closure
1614-
syntax introduced earlier, in which case the compiler will infer
1615-
the type of closure. Thus our managed closure example could also
1616-
be written:
1613+
This example uses the long closure syntax, `fn@(s: ~str) ...`. Using
1614+
this syntax makes it explicit that we are declaring a boxed
1615+
closure. In practice, boxed closures are usually defined with the
1616+
short closure syntax introduced earlier, in which case the compiler
1617+
infers the type of closure. Thus our managed closure example could
1618+
also be written:
16171619

16181620
~~~~
16191621
fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str {
@@ -1626,18 +1628,18 @@ fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str {
16261628
Owned closures, written `fn~` in analogy to the `~` pointer type,
16271629
hold on to things that can safely be sent between
16281630
processes. They copy the values they close over, much like managed
1629-
closures, but they also 'own' them—meaning no other code can access
1631+
closures, but they also own them: that is, no other code can access
16301632
them. Owned closures are used in concurrent code, particularly
16311633
for spawning [tasks](#tasks).
16321634

16331635
## Closure compatibility
16341636

1635-
A nice property of Rust closures is that you can pass any kind of
1637+
Rust closures have a convenient subtyping property: you can pass any kind of
16361638
closure (as long as the arguments and return types match) to functions
16371639
that expect a `fn()`. Thus, when writing a higher-order function that
1638-
wants to do nothing with its function argument beyond calling it, you
1639-
should almost always specify the type of that argument as `fn()`, so
1640-
that callers have the flexibility to pass whatever they want.
1640+
only calls its function argument, and does nothing else with it, you
1641+
should almost always declare the type of that argument as `fn()`. That way,
1642+
callers may pass any kind of closure.
16411643

16421644
~~~~
16431645
fn call_twice(f: fn()) { f(); f(); }
@@ -1650,15 +1652,15 @@ call_twice(bare_function);
16501652
~~~~
16511653

16521654
> ***Note:*** Both the syntax and the semantics will be changing
1653-
> in small ways. At the moment they can be unsound in multiple
1655+
> in small ways. At the moment they can be unsound in some
16541656
> scenarios, particularly with non-copyable types.
16551657
16561658
## Do syntax
16571659

16581660
The `do` expression provides a way to treat higher-order functions
16591661
(functions that take closures as arguments) as control structures.
16601662

1661-
Consider this function which iterates over a vector of
1663+
Consider this function that iterates over a vector of
16621664
integers, passing in a pointer to each integer in the vector:
16631665

16641666
~~~~
@@ -1702,13 +1704,14 @@ do each(&[1, 2, 3]) |n| {
17021704
~~~~
17031705

17041706
The call is prefixed with the keyword `do` and, instead of writing the
1705-
final closure inside the argument list it is moved outside of the
1706-
parenthesis where it looks visually more like a typical block of
1707+
final closure inside the argument list, it appears outside of the
1708+
parentheses, where it looks more like a typical block of
17071709
code.
17081710

1709-
`do` is often used to create tasks with the `task::spawn` function.
1710-
`spawn` has the signature `spawn(fn: fn~())`. In other words, it
1711-
is a function that takes an owned closure that takes no arguments.
1711+
`do` is a convenient way to create tasks with the `task::spawn`
1712+
function. `spawn` has the signature `spawn(fn: fn~())`. In other
1713+
words, it is a function that takes an owned closure that takes no
1714+
arguments.
17121715

17131716
~~~~
17141717
use task::spawn;
@@ -1731,10 +1734,10 @@ do spawn {
17311734

17321735
## For loops
17331736

1734-
Most iteration in Rust is done with `for` loops. Like `do`,
1735-
`for` is a nice syntax for doing control flow with closures.
1736-
Additionally, within a `for` loop, `break`, `loop`, and `return`
1737-
work just as they do with `while` and `loop`.
1737+
The most common way to express iteration in Rust is with a `for`
1738+
loop. Like `do`, `for` is a nice syntax for describing control flow
1739+
with closures. Additionally, within a `for` loop, `break`, `loop`,
1740+
and `return` work just as they do with `while` and `loop`.
17381741

17391742
Consider again our `each` function, this time improved to
17401743
break early when the iteratee returns `false`:
@@ -1765,7 +1768,7 @@ each(&[2, 4, 8, 5, 16], |n| {
17651768
~~~~
17661769

17671770
With `for`, functions like `each` can be treated more
1768-
like builtin looping structures. When calling `each`
1771+
like built-in looping structures. When calling `each`
17691772
in a `for` loop, instead of returning `false` to break
17701773
out of the loop, you just write `break`. To skip ahead
17711774
to the next iteration, write `loop`.
@@ -1783,8 +1786,8 @@ for each(&[2, 4, 8, 5, 16]) |n| {
17831786

17841787
As an added bonus, you can use the `return` keyword, which is not
17851788
normally allowed in closures, in a block that appears as the body of a
1786-
`for` loop — this will cause a return to happen from the outer
1787-
function, not just the loop body.
1789+
`for` loop: the meaning of `return` in such a block is to return from
1790+
the enclosing function, not just the loop body.
17881791

17891792
~~~~
17901793
# use each = vec::each;

0 commit comments

Comments
 (0)