@@ -381,7 +381,7 @@ more detail later on (the `T`s here stand for any other type):
381
381
` {field1: T1, field2: T2} `
382
382
: Record type.
383
383
384
- ` fn(arg1: T1, arg2: T2) -> T3 ` , ` lambda ()` , ` block ()`
384
+ ` fn(arg1: T1, arg2: T2) -> T3 ` , ` fn@ ()` , ` fn~() ` , ` fn& ()`
385
385
: Function types.
386
386
387
387
` @T ` , ` ~T ` , ` *T `
@@ -824,32 +824,36 @@ functions that can access variables in the scope in which they are
824
824
created.
825
825
826
826
There are several forms of closures, each with its own role. The most
827
- common type is called a 'block', this is a closure which has full
828
- access to its environment.
827
+ common type is called a 'stack closure'; this is a closure which has
828
+ full access to its environment.
829
829
830
830
~~~~
831
- fn call_block_with_ten (b: block (int)) { b(10); }
831
+ fn call_closure_with_ten (b: fn (int)) { b(10); }
832
832
833
833
let x = 20;
834
- call_block_with_ten ({|arg|
834
+ call_closure_with_ten ({|arg|
835
835
#info("x=%d, arg=%d", x, arg);
836
836
});
837
837
~~~~
838
838
839
- This defines a function that accepts a block , and then calls it with a
840
- simple block that executes a log statement, accessing both its
841
- argument and the variable ` x ` from its environment.
839
+ This defines a function that accepts a closure , and then calls it with
840
+ a simple stack closure that executes a log statement, accessing both
841
+ its argument and the variable ` x ` from its environment.
842
842
843
- Blocks can only be used in a restricted way, because it is not allowed
844
- to survive the scope in which it was created. They are allowed to
845
- appear in function argument position and in call position, but nowhere
846
- else.
843
+ Stack closures are called stack closures because they directly access
844
+ the stack frame in which they are created. This makes them very
845
+ lightweight to construct and lets them modify local variables from the
846
+ enclosing scope, but it also makes it unsafe for the closure to
847
+ survive the scope in which it was created. To prevent them from being
848
+ used after the creating scope has returned, stack closures can only be
849
+ used in a restricted way: they are allowed to appear in function
850
+ argument position and in call position, but nowhere else.
847
851
848
852
### Boxed closures
849
853
850
- When you need to store a closure in a data structure, a block will not
851
- do, since the compiler will refuse to let you store it. For this
852
- purpose, Rust provides a type of closure that has an arbitrary
854
+ When you need to store a closure in a data structure, a stack closure
855
+ will not do, since the compiler will refuse to let you store it. For
856
+ this purpose, Rust provides a type of closure that has an arbitrary
853
857
lifetime, written ` fn@ ` (boxed closure, analogous to the ` @ ` pointer
854
858
type described in the next section).
855
859
@@ -879,14 +883,14 @@ fn main() {
879
883
880
884
A nice property of Rust closures is that you can pass any kind of
881
885
closure (as long as the arguments and return types match) to functions
882
- that expect a ` block ` . Thus, when writing a higher-order function that
886
+ that expect a ` fn() ` . Thus, when writing a higher-order function that
883
887
wants to do nothing with its function argument beyond calling it, you
884
- should almost always specify the type of that argument as ` block ` , so
888
+ should almost always specify the type of that argument as ` fn() ` , so
885
889
that callers have the flexibility to pass whatever they want.
886
890
887
891
~~~~
888
- fn call_twice(f: block ()) { f(); f(); }
889
- call_twice({|| "I am a block" ; });
892
+ fn call_twice(f: fn ()) { f(); f(); }
893
+ call_twice({|| "I am a stack closure ; });
890
894
call_twice(fn@() { "I am a boxed closure"; });
891
895
fn bare_function() { "I am a plain function"; }
892
896
call_twice(bare_function);
@@ -903,9 +907,9 @@ them. Unique closures mostly exist to for spawning new
903
907
904
908
### Shorthand syntax
905
909
906
- The compact syntax used for blocks (` {|arg1, arg2| body} ` ) can also
907
- be used to express boxed and unique closures in situations where the
908
- closure style can be unambiguously derived from the context. Most
910
+ The compact syntax used for stack closures (` {|arg1, arg2| body} ` ) can
911
+ also be used to express boxed and unique closures in situations where
912
+ the closure style can be unambiguously derived from the context. Most
909
913
notably, when calling a higher-order function you do not have to use
910
914
the long-hand syntax for the function you're passing, since the
911
915
compiler can look at the argument type to find out what the parameter
@@ -941,12 +945,12 @@ returning the day of the week that string corresponds to (if any).
941
945
942
946
## Iteration
943
947
944
- Functions taking blocks provide a good way to define non-trivial
948
+ Functions taking closures provide a good way to define non-trivial
945
949
iteration constructs. For example, this one iterates over a vector
946
950
of integers backwards:
947
951
948
952
~~~~
949
- fn for_rev(v: [int], act: block (int)) {
953
+ fn for_rev(v: [int], act: fn (int)) {
950
954
let i = vec::len(v);
951
955
while (i > 0u) {
952
956
i -= 1u;
@@ -958,7 +962,7 @@ fn for_rev(v: [int], act: block(int)) {
958
962
To run such an iteration, you could do this:
959
963
960
964
~~~~
961
- # fn for_rev(v: [int], act: block (int)) {}
965
+ # fn for_rev(v: [int], act: fn (int)) {}
962
966
for_rev([1, 2, 3], {|n| log(error, n); });
963
967
~~~~
964
968
@@ -967,7 +971,7 @@ moved outside of the parentheses permits the following, which
967
971
looks quite like a normal loop:
968
972
969
973
~~~~
970
- # fn for_rev(v: [int], act: block (int)) {}
974
+ # fn for_rev(v: [int], act: fn (int)) {}
971
975
for_rev([1, 2, 3]) {|n|
972
976
log(error, n);
973
977
}
@@ -1387,7 +1391,7 @@ Here we know for sure that no one else has access to the `x` variable
1387
1391
in ` main ` , so we're good. But the call could also look like this:
1388
1392
1389
1393
~~~~
1390
- # fn myfunc(a: int, b: block ()) {}
1394
+ # fn myfunc(a: int, b: fn ()) {}
1391
1395
# fn get_another_record() -> int { 1 }
1392
1396
# let x = 1;
1393
1397
myfunc(x, {|| x = get_another_record(); });
@@ -1408,7 +1412,7 @@ to pessimistically assume a value will get mutated, even though it is
1408
1412
not sure.
1409
1413
1410
1414
~~~~
1411
- fn for_each(v: [mutable @int], iter: block (@int)) {
1415
+ fn for_each(v: [mutable @int], iter: fn (@int)) {
1412
1416
for elt in v { iter(elt); }
1413
1417
}
1414
1418
~~~~
@@ -1431,7 +1435,7 @@ with the `copy` operator:
1431
1435
1432
1436
~~~~
1433
1437
type mutrec = {mutable x: int};
1434
- fn for_each(v: [mutable mutrec], iter: block (mutrec)) {
1438
+ fn for_each(v: [mutable mutrec], iter: fn (mutrec)) {
1435
1439
for elt in v { iter(copy elt); }
1436
1440
}
1437
1441
~~~~
@@ -1509,23 +1513,23 @@ defining such functions again and again for every type they apply to.
1509
1513
Thus, Rust allows functions and datatypes to have type parameters.
1510
1514
1511
1515
~~~~
1512
- fn for_rev<T>(v: [T], act: block (T)) {
1516
+ fn for_rev<T>(v: [T], act: fn (T)) {
1513
1517
let i = vec::len(v);
1514
1518
while i > 0u {
1515
1519
i -= 1u;
1516
1520
act(v[i]);
1517
1521
}
1518
1522
}
1519
1523
1520
- fn map<T, U>(v: [T], f: block (T) -> U) -> [U] {
1524
+ fn map<T, U>(v: [T], f: fn (T) -> U) -> [U] {
1521
1525
let acc = [];
1522
1526
for elt in v { acc += [f(elt)]; }
1523
1527
ret acc;
1524
1528
}
1525
1529
~~~~
1526
1530
1527
1531
When defined in this way, these functions can be applied to any type
1528
- of vector, as long as the type of the block 's argument and the type of
1532
+ of vector, as long as the type of the closure 's argument and the type of
1529
1533
the vector's content agree with each other.
1530
1534
1531
1535
Inside a parameterized (generic) function, the names of the type
@@ -1635,7 +1639,7 @@ by value based on their type. There is one situation in which this is
1635
1639
difficult. If you try this program:
1636
1640
1637
1641
~~~~
1638
- # fn map(f: block (int) -> int, v: [int]) {}
1642
+ # fn map(f: fn (int) -> int, v: [int]) {}
1639
1643
fn plus1(x: int) -> int { x + 1 }
1640
1644
map(plus1, [1, 2, 3]);
1641
1645
~~~~
@@ -1650,7 +1654,7 @@ pass to a generic higher-order function as being passed by pointer,
1650
1654
using the ` && ` sigil:
1651
1655
1652
1656
~~~~
1653
- # fn map<T, U>(f: block (T) -> U, v: [T]) {}
1657
+ # fn map<T, U>(f: fn (T) -> U, v: [T]) {}
1654
1658
fn plus1(&&x: int) -> int { x + 1 }
1655
1659
map(plus1, [1, 2, 3]);
1656
1660
~~~~
@@ -2027,11 +2031,11 @@ generalized sequence types:
2027
2031
~~~~
2028
2032
iface seq<T> {
2029
2033
fn len() -> uint;
2030
- fn iter(block (T));
2034
+ fn iter(fn (T));
2031
2035
}
2032
2036
impl <T> of seq<T> for [T] {
2033
2037
fn len() -> uint { vec::len(self) }
2034
- fn iter(b: block (T)) {
2038
+ fn iter(b: fn (T)) {
2035
2039
for elt in self { b(elt); }
2036
2040
}
2037
2041
}
@@ -2112,7 +2116,7 @@ to leave off the `of` clause.
2112
2116
# type currency = ();
2113
2117
# fn mk_currency(x: int, s: str) {}
2114
2118
impl int_util for int {
2115
- fn times(b: block (int)) {
2119
+ fn times(b: fn (int)) {
2116
2120
let i = 0;
2117
2121
while i < self { b(i); i += 1; }
2118
2122
}
0 commit comments