Skip to content

Commit af199f2

Browse files
committed
tutorial: Expand the section on datatypes
1 parent ad05996 commit af199f2

File tree

1 file changed

+61
-27
lines changed

1 file changed

+61
-27
lines changed

doc/tutorial.md

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,17 +1252,32 @@ fn contains(v: ~[int], elt: int) -> bool {
12521252
12531253
# Datatypes
12541254
1255-
Rust datatypes are, by default, immutable. The core datatypes of Rust
1256-
are structural records and 'enums' (tagged unions, algebraic data
1257-
types).
1255+
The core datatypes of Rust are structural records, enums (tagged
1256+
unions, algebraic data types), and classes. They are immutable
1257+
by default.
12581258
12591259
~~~~
12601260
type point = {x: float, y: float};
1261+
12611262
enum shape {
12621263
circle(point, float),
12631264
rectangle(point, point)
12641265
}
1265-
let my_shape = circle({x: 0.0, y: 0.0}, 10.0);
1266+
1267+
class drawing {
1268+
let mut shapes: [shape];
1269+
1270+
new() {
1271+
self.shapes = [];
1272+
}
1273+
1274+
fn add_shape(new_shape: shape) {
1275+
self.shapes += [new_shape];
1276+
}
1277+
}
1278+
1279+
let my_drawing = drawing();
1280+
my_drawing.add_shape(circle({x: 0.0, y: 0.0}, 10.0));
12661281
~~~~
12671282
12681283
## Records
@@ -1271,12 +1286,10 @@ Rust record types are written `{field1: T1, field2: T2 [, ...]}`,
12711286
where `T1`, `T2`, ... denote types. Record literals are written in
12721287
the same way, but with expressions instead of types. They are quite
12731288
similar to C structs, and even laid out the same way in memory (so you
1274-
can read from a Rust struct in C, and vice-versa).
1275-
1276-
The dot operator is used to access record fields (`mypoint.x`).
1289+
can read from a Rust struct in C, and vice-versa). The dot operator is
1290+
used to access record fields (`mypoint.x`).
12771291
1278-
Fields that you want to mutate must be explicitly marked as such. For
1279-
example...
1292+
Fields that you want to mutate must be explicitly marked `mut`.
12801293
12811294
~~~~
12821295
type stack = {content: ~[int], mut head: uint};
@@ -1286,16 +1299,16 @@ With such a type, you can do `mystack.head += 1u`. If `mut` were
12861299
omitted from the type, such an assignment would result in a type
12871300
error.
12881301
1289-
To 'update' an immutable record, you use functional record update
1290-
syntax, by ending a record literal with the keyword `with`:
1302+
To create a new record based on the value of an existing record
1303+
you construct it using the `with` keyword:
12911304
12921305
~~~~
12931306
let oldpoint = {x: 10f, y: 20f};
12941307
let newpoint = {x: 0f with oldpoint};
12951308
assert newpoint == {x: 0f, y: 20f};
12961309
~~~~
12971310
1298-
This will create a new struct, copying all the fields from `oldpoint`
1311+
This will create a new record, copying all the fields from `oldpoint`
12991312
into it, except for the ones that are explicitly set in the literal.
13001313
13011314
Rust record types are *structural*. This means that `{x: float, y:
@@ -1329,8 +1342,8 @@ the fields of a record, a record pattern may end with `, _` (as in
13291342
13301343
## Enums
13311344
1332-
Enums are datatypes that have several different representations. For
1333-
example, the type shown earlier:
1345+
Enums are datatypes that have several alternate representations. For
1346+
example, consider the type shown earlier:
13341347
13351348
~~~~
13361349
# type point = {x: float, y: float};
@@ -1352,7 +1365,7 @@ which can be used to construct values of the type (taking arguments of
13521365
the specified types). So `circle({x: 0f, y: 0f}, 10f)` is the way to
13531366
create a new circle.
13541367
1355-
Enum variants do not have to have parameters. This, for example, is
1368+
Enum variants need not have type parameters. This, for example, is
13561369
equivalent to a C enum:
13571370
13581371
~~~~
@@ -1448,8 +1461,8 @@ fn point_from_direction(dir: direction) -> point {
14481461
14491462
Tuples in Rust behave exactly like records, except that their fields
14501463
do not have names (and can thus not be accessed with dot notation).
1451-
Tuples can have any arity except for 0 or 1 (though you may see nil,
1452-
`()`, as the empty tuple if you like).
1464+
Tuples can have any arity except for 0 or 1 (though you may consider
1465+
nil, `()`, as the empty tuple if you like).
14531466
14541467
~~~~
14551468
let mytup: (int, int, float) = (10, 20, 30.0);
@@ -1472,11 +1485,15 @@ allocating memory and going through a pointer. But for big records, or
14721485
records with mutable fields, it can be useful to have a single copy on
14731486
the heap, and refer to that through a pointer.
14741487
1475-
Rust supports several types of pointers. The simplest is the unsafe
1476-
pointer, written `*T`, which is a completely unchecked pointer type
1477-
only used in unsafe code (and thus, in typical Rust code, very
1478-
rarely). The safe pointer types are `@T` for shared, reference-counted
1479-
boxes, and `~T`, for uniquely-owned pointers.
1488+
Rust supports several types of pointers. The safe pointer types are
1489+
`@T` for shared boxes allocated on the local heap, `~T`, for
1490+
uniquely-owned boxes allocated on the exchange heap, and `&T`, for
1491+
borrowed pointers, which may point to any memory, and whose lifetimes
1492+
are governed by the call stack.
1493+
1494+
Rust also has an unsafe pointer, written `*T`, which is a completely
1495+
unchecked pointer type only used in unsafe code (and thus, in typical
1496+
Rust code, very rarely).
14801497
14811498
All pointer types can be dereferenced with the `*` unary operator.
14821499
@@ -1496,20 +1513,32 @@ let y = x; // Copy the pointer, increase refcount
14961513
// When x and y go out of scope, refcount goes to 0, box is freed
14971514
~~~~
14981515
1499-
***Note:*** We may in the future switch to garbage collection, rather
1516+
***Note:*** We will in the future switch to garbage collection, rather
15001517
than reference counting, for shared boxes.
15011518
15021519
Shared boxes never cross task boundaries.
15031520
15041521
### Unique boxes
15051522
1506-
In contrast to shared boxes, unique boxes are not reference counted.
1507-
Instead, it is statically guaranteed that only a single owner of the
1508-
box exists at any time.
1523+
In contrast to shared boxes, unique boxes have a single owner and thus
1524+
two unique boxes may not refer to the same memory. All unique boxes
1525+
across all tasks are allocated on a single _exchange heap_, where
1526+
their uniquely owned nature allows them to be passed between tasks.
1527+
1528+
Because unique boxes are uniquely owned, copying them involves allocating
1529+
a new unique box and duplicating the contents. Copying unique boxes
1530+
is expensive so the compiler will complain if you do.
15091531
15101532
~~~~
15111533
let x = ~10;
1512-
let y <- x;
1534+
let y = x; // error: copying a non-implicitly copyable type
1535+
~~~~
1536+
1537+
If you really want to copy a unique box you must say so explicitly.
1538+
1539+
~~~~
1540+
let x = ~10;
1541+
let y = copy x;
15131542
~~~~
15141543
15151544
This is where the 'move' (`<-`) operator comes in. It is similar to
@@ -1518,6 +1547,11 @@ from `x` to `y`, without violating the constraint that it only has a
15181547
single owner (if you used assignment instead of the move operator, the
15191548
box would, in principle, be copied).
15201549
1550+
~~~~
1551+
let x = ~10;
1552+
let y <- x;
1553+
~~~~
1554+
15211555
Unique boxes, when they do not contain any shared boxes, can be sent
15221556
to other tasks. The sending task will give up ownership of the box,
15231557
and won't be able to access it afterwards. The receiving task will

0 commit comments

Comments
 (0)