Skip to content

Commit 9d8dc00

Browse files
committed
auto merge of #10354 : thestinger/rust/vector, r=huonw
This section desperately needs to be expanded, but removing the misleading/incorrect information is a priority. Managed vectors/strings are not covered, as they are feature-gated and are only a micro-optimization to avoid double-indirection. Closes #6882
2 parents 4ce7d57 + eca52e6 commit 9d8dc00

File tree

1 file changed

+64
-133
lines changed

1 file changed

+64
-133
lines changed

doc/tutorial.md

+64-133
Original file line numberDiff line numberDiff line change
@@ -1240,58 +1240,80 @@ The indexing operator (`[]`) also auto-dereferences.
12401240
12411241
# Vectors and strings
12421242
1243-
A vector is a contiguous section of memory containing zero or more
1244-
values of the same type. Like other types in Rust, vectors can be
1245-
stored on the stack, the local heap, or the exchange heap. Borrowed
1246-
pointers to vectors are also called 'slices'.
1243+
A vector is a contiguous block of memory containing zero or more values of the
1244+
same type. Rust also supports vector reference types, called slices, which are
1245+
a view into a block of memory represented as a pointer and a length.
1246+
1247+
Strings are represented as vectors of `u8`, with the guarantee of containing a
1248+
valid UTF-8 sequence.
1249+
1250+
Fixed-size vectors are an unboxed block of memory, with the element length as
1251+
part of the type. A fixed-size vector owns the elements it contains, so the
1252+
elements are mutable if the vector is mutable. Fixed-size strings do not exist.
12471253
12481254
~~~
1249-
# enum Crayon {
1250-
# Almond, AntiqueBrass, Apricot,
1251-
# Aquamarine, Asparagus, AtomicTangerine,
1252-
# BananaMania, Beaver, Bittersweet,
1253-
# Black, BlizzardBlue, Blue
1254-
# }
1255-
// A fixed-size stack vector
1256-
let stack_crayons: [Crayon, ..3] = [Almond, AntiqueBrass, Apricot];
1255+
// A fixed-size vector
1256+
let numbers = [1, 2, 3];
1257+
let more_numbers = numbers;
12571258

1258-
// A borrowed pointer to stack-allocated vector
1259-
let stack_crayons: &[Crayon] = &[Aquamarine, Asparagus, AtomicTangerine];
1259+
// The type of a fixed-size vector is written as `[Type, ..length]`
1260+
let five_zeroes: [int, ..5] = [0, ..5];
1261+
~~~
12601262
1261-
// A local heap (managed) vector of crayons
1262-
let local_crayons: @[Crayon] = @[BananaMania, Beaver, Bittersweet];
1263+
A unique vector is dynamically sized, and has a destructor to clean up
1264+
allocated memory on the heap. A unique vector owns the elements it contains, so
1265+
the elements are mutable if the vector is mutable.
12631266
1264-
// An exchange heap (owned) vector of crayons
1265-
let exchange_crayons: ~[Crayon] = ~[Black, BlizzardBlue, Blue];
12661267
~~~
1268+
// A dynamically sized vector (unique vector)
1269+
let mut numbers = ~[1, 2, 3];
1270+
numbers.push(4);
1271+
numbers.push(5);
12671272

1268-
The `+` operator means concatenation when applied to vector types.
1273+
// The type of a unique vector is written as ~[int]
1274+
let more_numbers: ~[int] = numbers;
12691275

1270-
~~~~
1271-
# enum Crayon { Almond, AntiqueBrass, Apricot,
1272-
# Aquamarine, Asparagus, AtomicTangerine,
1273-
# BananaMania, Beaver, Bittersweet };
1274-
# impl Clone for Crayon {
1275-
# fn clone(&self) -> Crayon {
1276-
# *self
1277-
# }
1278-
# }
1276+
// The original `numbers` value can no longer be used, due to move semantics.
12791277

1280-
let my_crayons = ~[Almond, AntiqueBrass, Apricot];
1281-
let your_crayons = ~[BananaMania, Beaver, Bittersweet];
1278+
let mut string = ~"fo";
1279+
string.push_char('o');
1280+
~~~
12821281
1283-
// Add two vectors to create a new one
1284-
let our_crayons = my_crayons + your_crayons;
1282+
Slices are similar to fixed-size vectors, but the length is not part of the
1283+
type. They simply point into a block of memory and do not have ownership over
1284+
the elements.
12851285
1286-
// .push_all() will append to a vector, provided it lives in a mutable slot
1287-
let mut my_crayons = my_crayons;
1288-
my_crayons.push_all(your_crayons);
1289-
~~~~
1286+
~~~
1287+
// A slice
1288+
let xs = &[1, 2, 3];
12901289

1291-
> ***Note:*** The above examples of vector addition use owned
1292-
> vectors. Some operations on slices and stack vectors are
1293-
> not yet well-supported. Owned vectors are often the most
1294-
> usable.
1290+
// Slices have their type written as &[int]
1291+
let ys: &[int] = xs;
1292+
1293+
// Other vector types coerce to slices
1294+
let three = [1, 2, 3];
1295+
let zs: &[int] = three;
1296+
1297+
// An unadorned string literal is an immutable string slice
1298+
let string = "foobar";
1299+
1300+
// A string slice type is written as &str
1301+
let view: &str = string.slice(0, 3);
1302+
~~~
1303+
1304+
Mutable slices also exist, just as there are mutable references. However, there
1305+
are no mutable string slices. Strings are a multi-byte encoding (UTF-8) of
1306+
Unicode code points, so they cannot be freely mutated without the ability to
1307+
alter the length.
1308+
1309+
~~~
1310+
let mut xs = [1, 2, 3];
1311+
let view = xs.mut_slice(0, 2);
1312+
view[0] = 5;
1313+
1314+
// The type of a mutable slice is written as &mut [T]
1315+
let ys: &mut [int] = &mut [1, 2, 3];
1316+
~~~
12951317
12961318
Square brackets denote indexing into a vector:
12971319
@@ -1319,103 +1341,12 @@ let score = match numbers {
13191341
};
13201342
~~~~
13211343
1322-
The elements of a vector _inherit the mutability of the vector_,
1323-
and as such, individual elements may not be reassigned when the
1324-
vector lives in an immutable slot.
1325-
1326-
~~~ {.xfail-test}
1327-
# enum Crayon { Almond, AntiqueBrass, Apricot,
1328-
# Aquamarine, Asparagus, AtomicTangerine,
1329-
# BananaMania, Beaver, Bittersweet };
1330-
let crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];
1331-
1332-
crayons[0] = Apricot; // ERROR: Can't assign to immutable vector
1333-
~~~
1334-
1335-
Moving it into a mutable slot makes the elements assignable.
1336-
1337-
~~~
1338-
# enum Crayon { Almond, AntiqueBrass, Apricot,
1339-
# Aquamarine, Asparagus, AtomicTangerine,
1340-
# BananaMania, Beaver, Bittersweet };
1341-
let crayons: ~[Crayon] = ~[BananaMania, Beaver, Bittersweet];
1342-
1343-
// Put the vector into a mutable slot
1344-
let mut mutable_crayons = crayons;
1345-
1346-
// Now it's mutable to the bone
1347-
mutable_crayons[0] = Apricot;
1348-
~~~
1349-
1350-
This is a simple example of Rust's _dual-mode data structures_, also
1351-
referred to as _freezing and thawing_.
1352-
1353-
Strings are implemented with vectors of `u8`, though they have a
1354-
distinct type. They support most of the same allocation options as
1355-
vectors, though the string literal without a storage sigil (for
1356-
example, `"foo"`) is treated differently than a comparable vector
1357-
(`[foo]`). Whereas plain vectors are stack-allocated fixed-length
1358-
vectors, plain strings are borrowed pointers to read-only (static)
1359-
memory. All strings are immutable.
1360-
1361-
~~~
1362-
// A plain string is a slice to read-only (static) memory
1363-
let stack_crayons: &str = "Almond, AntiqueBrass, Apricot";
1364-
1365-
// The same thing, but with the `&`
1366-
let stack_crayons: &str = &"Aquamarine, Asparagus, AtomicTangerine";
1367-
1368-
// A local heap (managed) string
1369-
let local_crayons: @str = @"BananaMania, Beaver, Bittersweet";
1370-
1371-
// An exchange heap (owned) string
1372-
let exchange_crayons: ~str = ~"Black, BlizzardBlue, Blue";
1373-
~~~
1374-
1375-
Both vectors and strings support a number of useful
1376-
[methods](#methods), defined in [`std::vec`]
1377-
and [`std::str`]. Here are some examples.
1344+
Both vectors and strings support a number of useful [methods](#methods),
1345+
defined in [`std::vec`] and [`std::str`].
13781346
13791347
[`std::vec`]: std/vec/index.html
13801348
[`std::str`]: std/str/index.html
13811349
1382-
~~~
1383-
# enum Crayon {
1384-
# Almond, AntiqueBrass, Apricot,
1385-
# Aquamarine, Asparagus, AtomicTangerine,
1386-
# BananaMania, Beaver, Bittersweet
1387-
# }
1388-
# fn unwrap_crayon(c: Crayon) -> int { 0 }
1389-
# fn eat_crayon_wax(i: int) { }
1390-
# fn store_crayon_in_nasal_cavity(i: uint, c: Crayon) { }
1391-
# fn crayon_to_str(c: Crayon) -> &str { "" }
1392-
1393-
let crayons = [Almond, AntiqueBrass, Apricot];
1394-
1395-
// Check the length of the vector
1396-
assert!(crayons.len() == 3);
1397-
assert!(!crayons.is_empty());
1398-
1399-
// Iterate over a vector, obtaining a pointer to each element
1400-
// (`for` is explained in the container/iterator tutorial)
1401-
for crayon in crayons.iter() {
1402-
let delicious_crayon_wax = unwrap_crayon(*crayon);
1403-
eat_crayon_wax(delicious_crayon_wax);
1404-
}
1405-
1406-
// Map vector elements
1407-
let crayon_names = crayons.map(|v| crayon_to_str(*v));
1408-
let favorite_crayon_name = crayon_names[0];
1409-
1410-
// Remove whitespace from before and after the string
1411-
let new_favorite_crayon_name = favorite_crayon_name.trim();
1412-
1413-
if favorite_crayon_name.len() > 5 {
1414-
// Create a substring
1415-
println(favorite_crayon_name.slice_chars(0, 5));
1416-
}
1417-
~~~
1418-
14191350
# Closures
14201351
14211352
Named functions, like those we've seen so far, may not refer to local

0 commit comments

Comments
 (0)