@@ -329,7 +329,6 @@ something—in which case you'll have embedded it in a bigger statement.
329
329
# fn foo() -> bool { true }
330
330
# fn bar() -> bool { true }
331
331
# fn baz() -> bool { true }
332
-
333
332
// `let` is not an expression, so it is semi-colon terminated;
334
333
let x = foo();
335
334
@@ -711,8 +710,8 @@ Structs can be destructured in `match` patterns. The basic syntax is
711
710
# struct Point { x: float, y: float }
712
711
# let mypoint = Point { x: 0.0, y: 0.0 };
713
712
match mypoint {
714
- Point { x: 0.0, y: y } => { io::println(y .to_str()); }
715
- Point { x: x, y: y } => { io::println(x .to_str() + " " + y .to_str()); }
713
+ Point { x: 0.0, y: yy } => { io::println(yy .to_str()); }
714
+ Point { x: xx, y: yy } => { io::println(xx .to_str() + " " + yy .to_str()); }
716
715
}
717
716
~~~~
718
717
@@ -802,7 +801,7 @@ dereference (`*`) unary operator:
802
801
803
802
~~~~
804
803
# enum GizmoId = int;
805
- let my_gizmo_id = GizmoId(10);
804
+ let my_gizmo_id: GizmoId = GizmoId(10);
806
805
let id_int: int = *my_gizmo_id;
807
806
~~~~
808
807
@@ -863,12 +862,8 @@ back to [later](#modules-and-crates)). They are introduced with the
863
862
the return type follows the arrow.
864
863
865
864
~~~~
866
- fn repeat(string: &str, count: int) -> ~str {
867
- let mut result = ~"";
868
- for count.times {
869
- result += string;
870
- }
871
- return result;
865
+ fn line(a: int, b: int, x: int) -> int {
866
+ return a*x + b;
872
867
}
873
868
~~~~
874
869
@@ -889,10 +884,8 @@ fn int_to_str(i: int) -> ~str {
889
884
~~~~
890
885
891
886
~~~~
892
- # const copernicus: int = 0;
893
- fn int_to_str(i: int) -> ~str {
894
- if i == copernicus { ~"tube sock" }
895
- else { ~"violin" }
887
+ fn line(a: int, b: int, x: int) -> int {
888
+ a*x + b
896
889
}
897
890
~~~~
898
891
@@ -906,6 +899,16 @@ fn do_nothing_the_hard_way() -> () { return (); }
906
899
fn do_nothing_the_easy_way() { }
907
900
~~~~
908
901
902
+ Ending the function with a semicolon like so is equivalent to returning ` () ` .
903
+
904
+ ~~~~
905
+ fn line(a: int, b: int, x: int) -> int { a*x + b }
906
+ fn oops(a: int, b: int, x: int) -> () { a*x + b; }
907
+
908
+ assert 8 == line(5,3,1);
909
+ assert () == oops(5,3,1);
910
+ ~~~~
911
+
909
912
Methods are like functions, except that they are defined for a specific
910
913
'self' type (like 'this' in C++). Calling a method is done with
911
914
dot notation, as in ` my_vec.len() ` . Methods may be defined on most
@@ -1005,7 +1008,7 @@ easy for programmers to reason about. Heap isolation has the
1005
1008
additional benefit that garbage collection must only be done
1006
1009
per-heap. Rust never "stops the world" to reclaim memory.
1007
1010
1008
- Complete isolation of heaps between tasks implies that any data
1011
+ Complete isolation of heaps between tasks would, however, mean that any data
1009
1012
transferred between tasks must be copied. While this is a fine and
1010
1013
useful way to implement communication between tasks, it is also very
1011
1014
inefficient for large data structures. Because of this, Rust also
@@ -1117,6 +1120,9 @@ If you really want to copy a unique box you must say so explicitly.
1117
1120
~~~~
1118
1121
let x = ~10;
1119
1122
let y = copy x;
1123
+
1124
+ let z = *x + *y;
1125
+ assert z = 20;
1120
1126
~~~~
1121
1127
1122
1128
This is where the 'move' operator comes in. It is similar to
@@ -1125,9 +1131,11 @@ from `x` to `y`, without violating the constraint that it only has a
1125
1131
single owner (if you used assignment instead of the move operator, the
1126
1132
box would, in principle, be copied).
1127
1133
1128
- ~~~~
1134
+ ~~~~ {.ignore}
1129
1135
let x = ~10;
1130
1136
let y = move x;
1137
+
1138
+ let z = *x + *y; // would cause an error: use of moved variable: `x`
1131
1139
~~~~
1132
1140
1133
1141
Owned boxes, when they do not contain any managed boxes, can be sent
@@ -1265,7 +1273,7 @@ also done with square brackets (zero-based):
1265
1273
# BananaMania, Beaver, Bittersweet };
1266
1274
# fn draw_scene(c: Crayon) { }
1267
1275
1268
- let crayons = [BananaMania, Beaver, Bittersweet];
1276
+ let crayons: [Crayon] = [BananaMania, Beaver, Bittersweet];
1269
1277
match crayons[0] {
1270
1278
Bittersweet => draw_scene(crayons[0]),
1271
1279
_ => ()
@@ -1282,7 +1290,7 @@ elements. Mutable vector literals are written `[mut]` (empty) or `[mut
1282
1290
# Aquamarine, Asparagus, AtomicTangerine,
1283
1291
# BananaMania, Beaver, Bittersweet };
1284
1292
1285
- let crayons = [mut BananaMania, Beaver, Bittersweet];
1293
+ let crayons: [mut Crayon] = [mut BananaMania, Beaver, Bittersweet];
1286
1294
crayons[0] = AtomicTangerine;
1287
1295
~~~~
1288
1296
@@ -1318,8 +1326,8 @@ my_crayons += your_crayons;
1318
1326
> not well supported yet, owned vectors are often the most
1319
1327
> usable.
1320
1328
1321
- Strings are simply vectors of `[u8]`, though they have a distinct
1322
- type. They support most of the same allocation aptions as
1329
+ Strings are implemented with vectors of `[u8]`, though they have a distinct
1330
+ type. They support most of the same allocation options as
1323
1331
vectors, though the string literal without a storage sigil, e.g.
1324
1332
`"foo"` is treated differently than a comparable vector (`[foo]`).
1325
1333
Where
@@ -1328,7 +1336,7 @@ Where
1328
1336
// A plain string is a slice to read-only (static) memory
1329
1337
let stack_crayons: &str = "Almond, AntiqueBrass, Apricot";
1330
1338
1331
- // The same thing, but without
1339
+ // The same thing, but with the ` & `
1332
1340
let stack_crayons: &str = &"Almond, AntiqueBrass, Apricot";
1333
1341
1334
1342
// A local heap (managed) string
@@ -1511,9 +1519,12 @@ call_twice(bare_function);
1511
1519
1512
1520
## Do syntax
1513
1521
1514
- Closures in Rust are frequently used in combination with higher-order
1515
- functions to simulate control structures like `if` and
1516
- `loop`. Consider this function that iterates over a vector of
1522
+ The `do` expression is syntactic sugar for use with functions which
1523
+ take a closure as a final argument, because closures in Rust
1524
+ are so frequently used in combination with higher-order
1525
+ functions.
1526
+
1527
+ Consider this function which iterates over a vector of
1517
1528
integers, passing in a pointer to each integer in the vector:
1518
1529
1519
1530
~~~~
@@ -1558,8 +1569,7 @@ do each(&[1, 2, 3]) |n| {
1558
1569
The call is prefixed with the keyword `do` and, instead of writing the
1559
1570
final closure inside the argument list it is moved outside of the
1560
1571
parenthesis where it looks visually more like a typical block of
1561
- code. The `do` expression is purely syntactic sugar for a call that
1562
- takes a final closure argument.
1572
+ code.
1563
1573
1564
1574
`do` is often used for task spawning.
1565
1575
@@ -1653,6 +1663,10 @@ fn contains(v: &[int], elt: int) -> bool {
1653
1663
1654
1664
`for` syntax only works with stack closures.
1655
1665
1666
+ > ***Note:*** This is, essentially, a special loop protocol:
1667
+ > the keywords `break`, `loop`, and `return` work, in varying degree,
1668
+ > with `while`, `loop`, `do`, and `for` constructs.
1669
+
1656
1670
# Generics
1657
1671
1658
1672
Throughout this tutorial, we've been defining functions that act only on
@@ -2057,6 +2071,9 @@ The compiler will now look for `poultry/chicken.rs` and
2057
2071
and ` poultry::turkey ` . You can also provide a ` poultry.rs ` to add
2058
2072
content to the ` poultry ` module itself.
2059
2073
2074
+ The compiler then builds the crate as a platform-specific shared library or
2075
+ executable which can be distributed.
2076
+
2060
2077
## Using other crates
2061
2078
2062
2079
Having compiled a crate that contains the ` #[crate_type = "lib"] `
@@ -2111,22 +2128,22 @@ Now for something that you can actually compile yourself. We have
2111
2128
these two files:
2112
2129
2113
2130
~~~~
2114
- // mylib .rs
2115
- #[link(name = "mylib ", vers = "1.0")];
2116
- fn world () -> ~str { ~"world" }
2131
+ // world .rs
2132
+ #[link(name = "world ", vers = "1.0")];
2133
+ fn explore () -> ~str { ~"world" }
2117
2134
~~~~
2118
2135
2119
2136
~~~~ {.ignore}
2120
2137
// main.rs
2121
- extern mod mylib ;
2122
- fn main() { io::println(~"hello " + mylib::world ()); }
2138
+ extern mod world ;
2139
+ fn main() { io::println(~"hello " + world::explore ()); }
2123
2140
~~~~
2124
2141
2125
2142
Now compile and run like this (adjust to your platform if necessary):
2126
2143
2127
2144
~~~~ {.notrust}
2128
- > rustc --lib mylib .rs
2129
- > rustc main.rs -L .
2145
+ > rustc --lib world .rs # compiles libworld-94839cbfe144198-1.0.so
2146
+ > rustc main.rs -L . # compiles main
2130
2147
> ./main
2131
2148
"hello world"
2132
2149
~~~~
@@ -2146,12 +2163,14 @@ fn main() {
2146
2163
}
2147
2164
~~~~
2148
2165
2166
+
2149
2167
It is also possible to import just the name of a module (`use
2150
2168
std::list;` , then use ` list::find`), to import all identifiers exported
2151
2169
by a given module (` use io::* ` ), or to import a specific set
2152
2170
of identifiers (` use math::{min, max, pi} ` ).
2153
2171
2154
- You can rename an identifier when importing using the ` = ` operator:
2172
+ Rust uses different namespaces for modules, types, and values. You
2173
+ can also rename an identifier when importing using the ` = ` operator:
2155
2174
2156
2175
~~~~
2157
2176
use prnt = io::println;
@@ -2175,27 +2194,6 @@ This defines a rock-solid encryption algorithm. Code outside of the
2175
2194
module can refer to the ` enc::encrypt ` and ` enc::decrypt ` identifiers
2176
2195
just fine, but it does not have access to ` enc::super_secret_number ` .
2177
2196
2178
- ## Namespaces
2179
-
2180
- Rust uses three different namespaces: one for modules, one for types,
2181
- and one for values. This means that this code is valid:
2182
-
2183
- ~~~~
2184
- #[legacy_exports]
2185
- mod buffalo {
2186
- type buffalo = int;
2187
- fn buffalo<buffalo>(+buffalo: buffalo) -> buffalo { buffalo }
2188
- }
2189
- fn main() {
2190
- let buffalo: buffalo::buffalo = 1;
2191
- buffalo::buffalo::<buffalo::buffalo>(buffalo::buffalo(buffalo));
2192
- }
2193
- ~~~~
2194
-
2195
- You don't want to write things like that, but it * is* very practical
2196
- to not have to worry about name clashes between types, values, and
2197
- modules.
2198
-
2199
2197
## Resolution
2200
2198
2201
2199
The resolution process in Rust simply goes up the chain of contexts,
@@ -2211,21 +2209,25 @@ Identifiers can shadow each other. In this program, `x` is of type
2211
2209
type MyType = ~str;
2212
2210
fn main() {
2213
2211
type MyType = int;
2214
- let x: MyType;
2212
+ let x: MyType = 17 ;
2215
2213
}
2216
2214
~~~~
2217
2215
2218
2216
An ` use ` directive will only import into the namespaces for which
2219
2217
identifiers are actually found. Consider this example:
2220
2218
2221
2219
~~~~
2222
- mod foo { fn bar() {} }
2223
- fn baz() {
2224
- let bar = 10u;
2220
+ mod foo {
2221
+ fn bar() {}
2222
+ }
2223
+
2224
+ fn main() {
2225
+ let bar = 10;
2225
2226
2226
2227
{
2227
2228
use foo::bar;
2228
2229
let quux = bar;
2230
+ assert quux == 10;
2229
2231
}
2230
2232
}
2231
2233
~~~~
0 commit comments