@@ -1618,10 +1618,8 @@ call_twice(bare_function);
1618
1618
1619
1619
## Do syntax
1620
1620
1621
- The ` do ` expression is syntactic sugar for use with functions which
1622
- take a closure as a final argument, because closures in Rust
1623
- are so frequently used in combination with higher-order
1624
- functions.
1621
+ The ` do ` expression provides a way to treat higher-order functions
1622
+ (functions that take closures as arguments) as control structures.
1625
1623
1626
1624
Consider this function which iterates over a vector of
1627
1625
integers, passing in a pointer to each integer in the vector:
@@ -1636,20 +1634,22 @@ fn each(v: &[int], op: fn(v: &int)) {
1636
1634
}
1637
1635
~~~~
1638
1636
1639
- The reason we pass in a * pointer* to an integer rather than the
1640
- integer itself is that this is how the actual ` each() ` function for
1641
- vectors works. Using a pointer means that the function can be used
1642
- for vectors of any type, even large structs that would be impractical
1643
- to copy out of the vector on each iteration. As a caller, if we use a
1644
- closure to provide the final operator argument, we can write it in a
1645
- way that has a pleasant, block-like structure.
1637
+ As an aside, the reason we pass in a * pointer* to an integer rather
1638
+ than the integer itself is that this is how the actual ` each() `
1639
+ function for vectors works. ` vec::each ` though is a
1640
+ [ generic] ( #generics ) function, so must be efficient to use for all
1641
+ types. Passing the elements by pointer avoids copying potentially
1642
+ large objects.
1643
+
1644
+ As a caller, if we use a closure to provide the final operator
1645
+ argument, we can write it in a way that has a pleasant, block-like
1646
+ structure.
1646
1647
1647
1648
~~~~
1648
1649
# fn each(v: &[int], op: fn(v: &int)) { }
1649
- # fn do_some_work(i: int) { }
1650
+ # fn do_some_work(i: & int) { }
1650
1651
each(&[1, 2, 3], |n| {
1651
- debug!("%i", *n);
1652
- do_some_work(*n);
1652
+ do_some_work(n);
1653
1653
});
1654
1654
~~~~
1655
1655
@@ -1658,10 +1658,9 @@ call that can be written more like a built-in control structure:
1658
1658
1659
1659
~~~~
1660
1660
# fn each(v: &[int], op: fn(v: &int)) { }
1661
- # fn do_some_work(i: int) { }
1661
+ # fn do_some_work(i: & int) { }
1662
1662
do each(&[1, 2, 3]) |n| {
1663
- debug!("%i", *n);
1664
- do_some_work(*n);
1663
+ do_some_work(n);
1665
1664
}
1666
1665
~~~~
1667
1666
@@ -1670,7 +1669,9 @@ final closure inside the argument list it is moved outside of the
1670
1669
parenthesis where it looks visually more like a typical block of
1671
1670
code.
1672
1671
1673
- ` do ` is often used for task spawning.
1672
+ ` do ` is often used to create tasks with the ` task::spawn ` function.
1673
+ ` spawn ` has the signature ` spawn(fn: fn~()) ` . In other words, it
1674
+ is a function that takes an owned closure that takes no arguments.
1674
1675
1675
1676
~~~~
1676
1677
use task::spawn;
@@ -1680,9 +1681,9 @@ do spawn() || {
1680
1681
}
1681
1682
~~~~
1682
1683
1683
- That's nice, but look at all those bars and parentheses - that's two empty
1684
- argument lists back to back. Wouldn't it be great if they weren't
1685
- there?
1684
+ Look at all those bars and parentheses - that's two empty argument
1685
+ lists back to back. Since that is so unsightly, empty argument lists
1686
+ may be omitted from ` do ` expressions.
1686
1687
1687
1688
~~~~
1688
1689
# use task::spawn;
@@ -1691,8 +1692,6 @@ do spawn {
1691
1692
}
1692
1693
~~~~
1693
1694
1694
- Empty argument lists can be omitted from ` do ` expressions.
1695
-
1696
1695
## For loops
1697
1696
1698
1697
Most iteration in Rust is done with ` for ` loops. Like ` do ` ,
0 commit comments