@@ -1366,7 +1366,7 @@ The indexing operator (`[]`) also auto-dereferences.
1366
1366
1367
1367
# Vectors and strings
1368
1368
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
1370
1370
values of the same type. Like other types in Rust, vectors can be
1371
1371
stored on the stack, the local heap, or the exchange heap. Borrowed
1372
1372
pointers to vectors are also called 'slices'.
@@ -1411,10 +1411,10 @@ my_crayons += your_crayons;
1411
1411
1412
1412
> ***Note:*** The above examples of vector addition use owned
1413
1413
> 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
1415
1415
> usable.
1416
1416
1417
- Indexing into vectors is done with square brackets :
1417
+ Square brackets denote indexing into a vector :
1418
1418
1419
1419
~~~~
1420
1420
# enum Crayon { Almond, AntiqueBrass, Apricot,
@@ -1429,7 +1429,7 @@ match crayons[0] {
1429
1429
~~~~
1430
1430
1431
1431
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
1433
1433
vector lives in an immutable slot.
1434
1434
1435
1435
~~~ {.xfail-test}
@@ -1459,13 +1459,13 @@ mutable_crayons[0] = Apricot;
1459
1459
This is a simple example of Rust's _ dual-mode data structures_ , also
1460
1460
referred to as _ freezing and thawing_ .
1461
1461
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.
1469
1469
1470
1470
~~~
1471
1471
// A plain string is a slice to read-only (static) memory
@@ -1528,8 +1528,9 @@ if favorite_crayon_name.len() > 5 {
1528
1528
# Closures
1529
1529
1530
1530
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:
1533
1534
1534
1535
~~~~ {.ignore}
1535
1536
let foo = 10;
@@ -1552,10 +1553,10 @@ let closure = |arg| println(fmt!("captured_var=%d, arg=%d", captured_var, arg));
1552
1553
call_closure_with_ten(closure);
1553
1554
~~~~
1554
1555
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
1556
1557
a single expression. The types of the arguments are generally omitted,
1557
1558
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
1559
1560
arguments and return types may be annotated.
1560
1561
1561
1562
~~~~
@@ -1575,9 +1576,10 @@ let mut max = 0;
1575
1576
Stack closures are very efficient because their environment is
1576
1577
allocated on the call stack and refers by pointer to captured
1577
1578
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
1581
1583
pervasively in Rust code.
1582
1584
1583
1585
## Managed closures
@@ -1586,12 +1588,12 @@ When you need to store a closure in a data structure, a stack closure
1586
1588
will not do, since the compiler will refuse to let you store it. For
1587
1589
this purpose, Rust provides a type of closure that has an arbitrary
1588
1590
lifetime, written ` fn@ ` (boxed closure, analogous to the ` @ ` pointer
1589
- type described earlier).
1591
+ type described earlier). This type of closure * is * first-class.
1590
1592
1591
1593
A managed closure does not directly access its environment, but merely
1592
1594
copies out the values that it closes over into a private data
1593
1595
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.
1595
1597
1596
1598
This code creates a closure that adds a given string to its argument,
1597
1599
returns it from a function, and then calls it:
@@ -1608,12 +1610,12 @@ fn main() {
1608
1610
}
1609
1611
~~~~
1610
1612
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:
1617
1619
1618
1620
~~~~
1619
1621
fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str {
@@ -1626,18 +1628,18 @@ fn mk_appender(suffix: ~str) -> fn@(~str) -> ~str {
1626
1628
Owned closures, written ` fn~ ` in analogy to the ` ~ ` pointer type,
1627
1629
hold on to things that can safely be sent between
1628
1630
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
1630
1632
them. Owned closures are used in concurrent code, particularly
1631
1633
for spawning [ tasks] ( #tasks ) .
1632
1634
1633
1635
## Closure compatibility
1634
1636
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
1636
1638
closure (as long as the arguments and return types match) to functions
1637
1639
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 .
1641
1643
1642
1644
~~~~
1643
1645
fn call_twice(f: fn()) { f(); f(); }
@@ -1650,15 +1652,15 @@ call_twice(bare_function);
1650
1652
~~~~
1651
1653
1652
1654
> *** 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
1654
1656
> scenarios, particularly with non-copyable types.
1655
1657
1656
1658
## Do syntax
1657
1659
1658
1660
The ` do ` expression provides a way to treat higher-order functions
1659
1661
(functions that take closures as arguments) as control structures.
1660
1662
1661
- Consider this function which iterates over a vector of
1663
+ Consider this function that iterates over a vector of
1662
1664
integers, passing in a pointer to each integer in the vector:
1663
1665
1664
1666
~~~~
@@ -1702,13 +1704,14 @@ do each(&[1, 2, 3]) |n| {
1702
1704
~~~~
1703
1705
1704
1706
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
1707
1709
code.
1708
1710
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.
1712
1715
1713
1716
~~~~
1714
1717
use task::spawn;
@@ -1731,10 +1734,10 @@ do spawn {
1731
1734
1732
1735
## For loops
1733
1736
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 ` .
1738
1741
1739
1742
Consider again our ` each ` function, this time improved to
1740
1743
break early when the iteratee returns ` false ` :
@@ -1765,7 +1768,7 @@ each(&[2, 4, 8, 5, 16], |n| {
1765
1768
~~~~
1766
1769
1767
1770
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 `
1769
1772
in a ` for ` loop, instead of returning ` false ` to break
1770
1773
out of the loop, you just write ` break ` . To skip ahead
1771
1774
to the next iteration, write ` loop ` .
@@ -1783,8 +1786,8 @@ for each(&[2, 4, 8, 5, 16]) |n| {
1783
1786
1784
1787
As an added bonus, you can use the ` return ` keyword, which is not
1785
1788
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.
1788
1791
1789
1792
~~~~
1790
1793
# use each = vec::each;
0 commit comments