Skip to content

Commit e4761c8

Browse files
committed
auto merge of #17962 : jkleint/rust/guide-vectors, r=steveklabnik
The array is the fundamental concept; vectors are growable arrays, and slices are views into either. Show common array ops up front: length and iteration. Mention arrays are immutable by default. Highlight definite initialization and bounds-checking as safety features. Show that you only need a type suffix on one element of initializers. Explain that vectors are a value-add library type over arrays, not a fundamental type; show they have the same "interface." Motivate slices as efficient views into arrays; explain you can slice vectors, Strings, &str because they're backed by arrays. Show off new, easy-to-read [a..b] slice syntax.
2 parents 71dfa5b + 1ce5a56 commit e4761c8

File tree

1 file changed

+65
-50
lines changed

1 file changed

+65
-50
lines changed

src/doc/guide.md

+65-50
Original file line numberDiff line numberDiff line change
@@ -1496,87 +1496,102 @@ low-level details matter, they really matter. Just remember that `String`s
14961496
allocate memory and control their data, while `&str`s are a reference to
14971497
another string, and you'll be all set.
14981498

1499-
# Vectors
1499+
# Arrays, Vectors, and Slices
15001500

1501-
Like many programming languages, Rust has a list type for when you want a list
1502-
of things. But similar to strings, Rust has different types to represent this
1503-
idea: `Vec<T>` (a 'vector'), `[T, .. N]` (an 'array'), and `&[T]` (a 'slice').
1504-
Whew!
1501+
Like many programming languages, Rust has list types to represent a sequence of
1502+
things. The most basic is the **array**, a fixed-size list of elements of the
1503+
same type. By default, arrays are immutable.
15051504

1506-
Vectors are similar to `String`s: they have a dynamic length, and they
1507-
allocate enough memory to fit. You can create a vector with the `vec!` macro:
1505+
```{rust}
1506+
let a = [1i, 2i, 3i];
1507+
let mut m = [1i, 2i, 3i];
1508+
```
1509+
1510+
You can create an array with a given number of elements, all initialized to the
1511+
same value, with `[val, ..N]` syntax. The compiler ensures that arrays are
1512+
always initialized.
15081513

15091514
```{rust}
1510-
let nums = vec![1i, 2i, 3i];
1515+
let a = [0i, ..20]; // Shorthand for array of 20 elements all initialized to 0
15111516
```
15121517

1513-
Notice that unlike the `println!` macro we've used in the past, we use square
1514-
brackets (`[]`) with `vec!`. Rust allows you to use either in either situation,
1515-
this is just convention.
1518+
Arrays have type `[T,..N]`. We'll talk about this `T` notation later, when we
1519+
cover generics.
15161520

1517-
You can create an array with just square brackets:
1521+
You can get the number of elements in an array `a` with `a.len()`, and use
1522+
`a.iter()` to iterate over them with a for loop. This code will print each
1523+
number in order:
15181524

15191525
```{rust}
1520-
let nums = [1i, 2i, 3i];
1521-
let nums = [1i, ..20]; // Shorthand for an array of 20 elements all initialized to 1
1526+
let a = [1i, 2, 3]; // Only the first item needs a type suffix
1527+
1528+
println!("a has {} elements", a.len());
1529+
for e in a.iter() {
1530+
println!("{}", e);
1531+
}
15221532
```
15231533

1524-
So what's the difference? An array has a fixed size, so you can't add or
1525-
subtract elements:
1534+
You can access a particular element of an array with **subscript notation**:
15261535

1527-
```{rust,ignore}
1528-
let mut nums = vec![1i, 2i, 3i];
1529-
nums.push(4i); // works
1536+
```{rust}
1537+
let names = ["Graydon", "Brian", "Niko"];
15301538
1531-
let mut nums = [1i, 2i, 3i];
1532-
nums.push(4i); // error: type `[int, .. 3]` does not implement any method
1533-
// in scope named `push`
1539+
println!("The second name is: {}", names[1]);
15341540
```
15351541

1536-
The `push()` method lets you append a value to the end of the vector. But
1537-
since arrays have fixed sizes, adding an element doesn't make any sense.
1538-
You can see how it has the exact type in the error message: `[int, .. 3]`.
1539-
An array of `int`s, with length 3.
1542+
Subscripts start at zero, like in most programming languages, so the first name
1543+
is `names[0]` and the second name is `names[1]`. The above example prints
1544+
`The second name is: Brian`. If you try to use a subscript that is not in the
1545+
array, you will get an error: array access is bounds-checked at run-time. Such
1546+
errant access is the source of many bugs in other systems programming
1547+
languages.
15401548

1541-
Similar to `&str`, a slice is a reference to another array. We can get a
1542-
slice from a vector by using the `as_slice()` method:
1549+
A **vector** is a dynamic or "growable" array, implemented as the standard
1550+
library type [`Vec<T>`](std/vec/) (we'll talk about what the `<T>` means
1551+
later). Vectors are to arrays what `String` is to `&str`. You can create them
1552+
with the `vec!` macro:
15431553

15441554
```{rust}
1545-
let vec = vec![1i, 2i, 3i];
1546-
let slice = vec.as_slice();
1555+
let v = vec![1i, 2, 3];
15471556
```
15481557

1549-
All three types implement an `iter()` method, which returns an iterator. We'll
1550-
talk more about the details of iterators later, but for now, the `iter()` method
1551-
allows you to write a `for` loop that prints out the contents of a vector, array,
1552-
or slice:
1558+
(Notice that unlike the `println!` macro we've used in the past, we use square
1559+
brackets `[]` with `vec!`. Rust allows you to use either in either situation,
1560+
this is just convention.)
15531561

1554-
```{rust}
1555-
let vec = vec![1i, 2i, 3i];
1562+
You can get the length of, iterate over, and subscript vectors just like
1563+
arrays. In addition, (mutable) vectors can grow automatically:
15561564

1557-
for i in vec.iter() {
1558-
println!("{}", i);
1559-
}
1565+
```{rust}
1566+
let mut nums = vec![1i, 2, 3];
1567+
nums.push(4);
1568+
println!("The length of nums is now {}", nums.len()); // Prints 4
15601569
```
15611570

1562-
This code will print each number in order, on its own line.
1571+
Vectors have many more useful methods.
15631572

1564-
You can access a particular element of a vector, array, or slice by using
1565-
**subscript notation**:
1573+
A **slice** is a reference to (or "view" into) an array. They are useful for
1574+
allowing safe, efficient access to a portion of an array without copying. For
1575+
example, you might want to reference just one line of a file read into memory.
1576+
By nature, a slice is not created directly, but from an existing variable.
1577+
Slices have a length, can be mutable or not, and in many ways behave like
1578+
arrays:
15661579

15671580
```{rust}
1568-
let names = ["Graydon", "Brian", "Niko"];
1581+
let a = [0i, 1, 2, 3, 4];
1582+
let middle = a.slice(1, 4); // A slice of a: just the elements [1,2,3]
15691583
1570-
println!("The second name is: {}", names[1]);
1584+
for e in middle.iter() {
1585+
println!("{}", e); // Prints 1, 2, 3
1586+
}
15711587
```
15721588

1573-
These subscripts start at zero, like in most programming languages, so the
1574-
first name is `names[0]` and the second name is `names[1]`. The above example
1575-
prints `The second name is: Brian`.
1589+
You can also take a slice of a vector, `String`, or `&str`, because they are
1590+
backed by arrays. Slices have type `&[T]`, which we'll talk about when we cover
1591+
generics.
15761592

1577-
There's a whole lot more to vectors, but that's enough to get started. We have
1578-
now learned all of the most basic Rust concepts. We're ready to start building
1579-
our guessing game, but we need to know how to do one last thing first: get
1593+
We have now learned all of the most basic Rust concepts. We're ready to start
1594+
building our guessing game, we just need to know one last thing: how to get
15801595
input from the keyboard. You can't have a guessing game without the ability to
15811596
guess!
15821597

0 commit comments

Comments
 (0)