From 810ac592a6ee47089f51bcb683a0938541e142e8 Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Sat, 16 Sep 2023 20:08:57 -0400 Subject: [PATCH] Edit the std-types segment --- Cargo.lock | 4 + Cargo.toml | 1 + src/SUMMARY.md | 5 +- src/exercises/Cargo.toml | 4 - src/exercises/day-1/solutions-afternoon.md | 13 -- src/exercises/day-2/book-library.rs | 184 ------------------- src/exercises/day-2/solutions-morning.md | 9 - src/std-types.md | 2 +- src/std-types/Cargo.toml | 9 + src/std-types/exercise.md | 72 ++++---- src/std-types/exercise.rs | 197 ++++----------------- src/std-types/option.md | 68 ++----- src/std-types/result.md | 20 ++- src/std-types/std.md | 40 +++++ src/std-types/string.md | 2 +- src/std-types/vec.md | 2 - 16 files changed, 159 insertions(+), 473 deletions(-) delete mode 100644 src/exercises/day-1/solutions-afternoon.md delete mode 100644 src/exercises/day-2/book-library.rs delete mode 100644 src/exercises/day-2/solutions-morning.md create mode 100644 src/std-types/Cargo.toml create mode 100644 src/std-types/std.md diff --git a/Cargo.lock b/Cargo.lock index 04b1400ec6b6..13331727f9bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2076,6 +2076,10 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "std-types" +version = "0.1.0" + [[package]] name = "string_cache" version = "0.8.7" diff --git a/Cargo.toml b/Cargo.toml index 947ecd0c228d..47d59a8eae5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "src/language-features", "src/tuples-and-arrays", "src/user-defined-types", + "src/std-types", "src/exercises", "src/bare-metal/useful-crates/allocator-example", "src/bare-metal/useful-crates/zerocopy-example", diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 7ba5f02ae6ca..0476e33c0b8e 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -57,12 +57,13 @@ - [Let Control Flow](user-defined-types/let-control-flow.md) - [Exercise: Expression Evaluation](user-defined-types/exercise.md) - [Standard Library Types](std-types.md) + - [Standard Library](std-types/std.md) - [Option](std-types/option.md) - [Result](std-types/result.md) - [String](std-types/string.md) - [Vec](std-types/vec.md) - [HashMap](std-types/hashmap.md) - - [Exercise: Book Reviews](std-types/exercise.md) + - [Exercise: Hash Set](std-types/exercise.md) ---- @@ -287,8 +288,6 @@ ---- - [Solutions](exercises/solutions.md) - - [Day 1 Afternoon](exercises/day-1/solutions-afternoon.md) - - [Day 2 Morning](exercises/day-2/solutions-morning.md) - [Day 2 Afternoon](exercises/day-2/solutions-afternoon.md) - [Day 3 Morning](exercises/day-3/solutions-morning.md) - [Day 3 Afternoon](exercises/day-3/solutions-afternoon.md) diff --git a/src/exercises/Cargo.toml b/src/exercises/Cargo.toml index 23f79083079b..d9520daf1ee2 100644 --- a/src/exercises/Cargo.toml +++ b/src/exercises/Cargo.toml @@ -8,10 +8,6 @@ publish = false name = "luhn" path = "day-1/luhn.rs" -[[bin]] -name = "book-library" -path = "day-2/book-library.rs" - [[bin]] name = "strings-iterators" path = "day-2/strings-iterators.rs" diff --git a/src/exercises/day-1/solutions-afternoon.md b/src/exercises/day-1/solutions-afternoon.md deleted file mode 100644 index c8bff12cdfe3..000000000000 --- a/src/exercises/day-1/solutions-afternoon.md +++ /dev/null @@ -1,13 +0,0 @@ -# Day 1 Afternoon Exercises - -## Luhn Algorithm - -([back to exercise](luhn.md)) - -```rust -{{#include luhn.rs}} -``` - -## Pattern matching - -TBD. diff --git a/src/exercises/day-2/book-library.rs b/src/exercises/day-2/book-library.rs deleted file mode 100644 index a084b4caf6f7..000000000000 --- a/src/exercises/day-2/book-library.rs +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2022 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// ANCHOR: setup -struct Library { - books: Vec, -} - -struct Book { - title: String, - year: u16, -} - -impl Book { - // This is a constructor, used below. - fn new(title: &str, year: u16) -> Book { - Book { - title: String::from(title), - year, - } - } -} - -// Implement the methods below. Update the `self` parameter to -// indicate the method's required level of ownership over the object: -// -// - `&self` for shared read-only access, -// - `&mut self` for unique and mutable access, -// - `self` for unique access by value. -impl Library { - // ANCHOR_END: setup - - // ANCHOR: Library_new - fn new() -> Library { - // ANCHOR_END: Library_new - Library { books: Vec::new() } - } - - // ANCHOR: Library_len - //fn len(self) -> usize { - // todo!("Return the length of `self.books`") - //} - // ANCHOR_END: Library_len - fn len(&self) -> usize { - self.books.len() - } - - // ANCHOR: Library_is_empty - //fn is_empty(self) -> bool { - // todo!("Return `true` if `self.books` is empty") - //} - // ANCHOR_END: Library_is_empty - fn is_empty(&self) -> bool { - self.books.is_empty() - } - - // ANCHOR: Library_add_book - //fn add_book(self, book: Book) { - // todo!("Add a new book to `self.books`") - //} - // ANCHOR_END: Library_add_book - fn add_book(&mut self, book: Book) { - self.books.push(book) - } - - // ANCHOR: Library_print_books - //fn print_books(self) { - // todo!("Iterate over `self.books` and print each book's title and year") - //} - // ANCHOR_END: Library_print_books - fn print_books(&self) { - for book in &self.books { - println!("{}, published in {}", book.title, book.year); - } - } - - // ANCHOR: Library_oldest_book - //fn oldest_book(self) -> Option<&Book> { - // todo!("Return a reference to the oldest book (if any)") - //} - // ANCHOR_END: Library_oldest_book - fn oldest_book(&self) -> Option<&Book> { - // Using a closure and a built-in method: - // self.books.iter().min_by_key(|book| book.year) - - // Longer hand-written solution: - let mut oldest: Option<&Book> = None; - for book in self.books.iter() { - if oldest.is_none() || book.year < oldest.unwrap().year { - oldest = Some(book); - } - } - - oldest - } -} - -// ANCHOR: main -// This shows the desired behavior. Uncomment the code below and -// implement the missing methods. You will need to update the -// method signatures, including the "self" parameter! You may -// also need to update the variable bindings within main. -fn main() { - let library = Library::new(); - - //println!("The library is empty: library.is_empty() -> {}", library.is_empty()); - // - //library.add_book(Book::new("Lord of the Rings", 1954)); - //library.add_book(Book::new("Alice's Adventures in Wonderland", 1865)); - // - //println!("The library is no longer empty: library.is_empty() -> {}", library.is_empty()); - // - // - //library.print_books(); - // - //match library.oldest_book() { - // Some(book) => println!("The oldest book is {}", book.title), - // None => println!("The library is empty!"), - //} - // - //println!("The library has {} books", library.len()); - //library.print_books(); -} -// ANCHOR_END: main - -#[test] -fn test_library_len() { - let mut library = Library::new(); - assert_eq!(library.len(), 0); - assert!(library.is_empty()); - - library.add_book(Book::new("Lord of the Rings", 1954)); - library.add_book(Book::new("Alice's Adventures in Wonderland", 1865)); - assert_eq!(library.len(), 2); - assert!(!library.is_empty()); -} - -#[test] -fn test_library_is_empty() { - let mut library = Library::new(); - assert!(library.is_empty()); - - library.add_book(Book::new("Lord of the Rings", 1954)); - assert!(!library.is_empty()); -} - -#[test] -fn test_library_print_books() { - let mut library = Library::new(); - library.add_book(Book::new("Lord of the Rings", 1954)); - library.add_book(Book::new("Alice's Adventures in Wonderland", 1865)); - // We could try and capture stdout, but let us just call the - // method to start with. - library.print_books(); -} - -#[test] -fn test_library_oldest_book() { - let mut library = Library::new(); - assert!(library.oldest_book().is_none()); - - library.add_book(Book::new("Lord of the Rings", 1954)); - assert_eq!( - library.oldest_book().map(|b| b.title.as_str()), - Some("Lord of the Rings") - ); - - library.add_book(Book::new("Alice's Adventures in Wonderland", 1865)); - assert_eq!( - library.oldest_book().map(|b| b.title.as_str()), - Some("Alice's Adventures in Wonderland") - ); -} diff --git a/src/exercises/day-2/solutions-morning.md b/src/exercises/day-2/solutions-morning.md deleted file mode 100644 index a62cd4a30001..000000000000 --- a/src/exercises/day-2/solutions-morning.md +++ /dev/null @@ -1,9 +0,0 @@ -# Day 2 Morning Exercises - -## Designing a Library - -([back to exercise](book-library.md)) - -```rust -{{#include book-library.rs}} -``` diff --git a/src/std-types.md b/src/std-types.md index b630395b2eec..973374afda61 100644 --- a/src/std-types.md +++ b/src/std-types.md @@ -7,4 +7,4 @@ In this segment: * [String](std-types/string.md) * [Vec](std-types/vec.md) * [HashMap](std-types/hashmap.md) -* [Exercise: Book Reviews](std-types/exercise.md) +* [Exercise: Hash Set](std-types/exercise.md) diff --git a/src/std-types/Cargo.toml b/src/std-types/Cargo.toml new file mode 100644 index 000000000000..fe46d703726b --- /dev/null +++ b/src/std-types/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "std-types" +version = "0.1.0" +edition = "2021" +publish = false + +[[bin]] +name = "hashset" +path = "exercise.rs" diff --git a/src/std-types/exercise.md b/src/std-types/exercise.md index e1421bd257bf..d17f507194c8 100644 --- a/src/std-types/exercise.md +++ b/src/std-types/exercise.md @@ -1,56 +1,50 @@ --- minutes: 5 -existing course material: -- exercises/day-2/book-library.md --- - -# Exercise: Book Reviews - -# Storing Books - -We will learn much more about structs and the `Vec` type tomorrow. For now, -you just need to know part of its API: - -```rust,editable -fn main() { - let mut vec = vec![10, 20]; - vec.push(30); - let midpoint = vec.len() / 2; - println!("middle value: {}", vec[midpoint]); - for item in &vec { - println!("item: {item}"); - } -} -``` - -Use this to model a library's book collection. Copy the code below to - and update the types to make it compile: +# Exercise: Hash Set -```rust,should_panic -{{#include exercise.rs:setup}} -{{#include exercise.rs:Library_new}} - todo!("Initialize and return a `Library` value") - } +In this exercise you will build a very simple hash set that stores `u32` +values. The hash set will have a fixed size, and buckets should be selected +with a simple modulus operation (`i % num_buckets`). Use a `Vec` to represent +each bucket. -{{#include exercise.rs:Library_len}} +While solving this exercise, you may encounter a few "rough edges". The error +messages from the compiler may help you to solve these, but if not, don't +`panic!` -- discuss them with your classmates or instructor. -{{#include exercise.rs:Library_is_empty}} +```rust +// TODO: define a type IntegerHashSet. +struct IntegerHashSet; -{{#include exercise.rs:Library_add_book}} - -{{#include exercise.rs:Library_print_books}} +{{#include exercise.rs:new}} + todo!() +} -{{#include exercise.rs:Library_oldest_book}} +{{#include exercise.rs:test_membership}} + todo!() } -{{#include exercise.rs:main}} +{{#include exercise.rs:tests}} ``` +If you finish early, adjust the hash set to use open chaining. What happens if +all of the give integers do not fit? +
-[Solution](solutions-afternoon.md#designing-a-library) +Highlight that students should not suffer the rough edges silently. + + * The hashset is passed by reference, but we haven't yet covered references. + This is done in the provided code, so should not cause errors for students. + + * The integers are `u32` but the size of the hash table is a `usize`, so values must be cast. Are those casts correct? + + * Depending on how students implement iteration, they may run into ownership + issues. For example, `for elt in hashset.buckets[b]` will move the bucket. + The compiler will suggest `for elt in &hashset.buckets[b]`, but then `elt` + has type `&u32`, so students must write `*elt`. + * Consider this a kind of foreshadowing of memory and borrows on day 3. + * The `Vec::contains` method may avoid the need for a `for` loop.
diff --git a/src/std-types/exercise.rs b/src/std-types/exercise.rs index a084b4caf6f7..3a8ec121a036 100644 --- a/src/std-types/exercise.rs +++ b/src/std-types/exercise.rs @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,173 +12,52 @@ // See the License for the specific language governing permissions and // limitations under the License. -// ANCHOR: setup -struct Library { - books: Vec, -} - -struct Book { - title: String, - year: u16, -} - -impl Book { - // This is a constructor, used below. - fn new(title: &str, year: u16) -> Book { - Book { - title: String::from(title), - year, - } - } -} - -// Implement the methods below. Update the `self` parameter to -// indicate the method's required level of ownership over the object: -// -// - `&self` for shared read-only access, -// - `&mut self` for unique and mutable access, -// - `self` for unique access by value. -impl Library { - // ANCHOR_END: setup - - // ANCHOR: Library_new - fn new() -> Library { - // ANCHOR_END: Library_new - Library { books: Vec::new() } - } - - // ANCHOR: Library_len - //fn len(self) -> usize { - // todo!("Return the length of `self.books`") - //} - // ANCHOR_END: Library_len - fn len(&self) -> usize { - self.books.len() - } - - // ANCHOR: Library_is_empty - //fn is_empty(self) -> bool { - // todo!("Return `true` if `self.books` is empty") - //} - // ANCHOR_END: Library_is_empty - fn is_empty(&self) -> bool { - self.books.is_empty() - } - - // ANCHOR: Library_add_book - //fn add_book(self, book: Book) { - // todo!("Add a new book to `self.books`") - //} - // ANCHOR_END: Library_add_book - fn add_book(&mut self, book: Book) { - self.books.push(book) +/// A data structure storing a set of u32's. +struct IntegerHashSet(Vec>); + +// ANCHOR: new +/// Create a new IntegerHashSet containing the given integers. +fn new(size: usize, integers: Vec) -> IntegerHashSet { + // ANCHOR_END: new + // Create the appropriate number of buckets. + let mut buckets = vec![]; + for _ in 0..size { + buckets.push(vec![]); } - // ANCHOR: Library_print_books - //fn print_books(self) { - // todo!("Iterate over `self.books` and print each book's title and year") - //} - // ANCHOR_END: Library_print_books - fn print_books(&self) { - for book in &self.books { - println!("{}, published in {}", book.title, book.year); - } + for i in integers { + let b = i as usize % size; + buckets[b].push(i); } - // ANCHOR: Library_oldest_book - //fn oldest_book(self) -> Option<&Book> { - // todo!("Return a reference to the oldest book (if any)") - //} - // ANCHOR_END: Library_oldest_book - fn oldest_book(&self) -> Option<&Book> { - // Using a closure and a built-in method: - // self.books.iter().min_by_key(|book| book.year) - - // Longer hand-written solution: - let mut oldest: Option<&Book> = None; - for book in self.books.iter() { - if oldest.is_none() || book.year < oldest.unwrap().year { - oldest = Some(book); - } - } - - oldest - } + IntegerHashSet(buckets) } -// ANCHOR: main -// This shows the desired behavior. Uncomment the code below and -// implement the missing methods. You will need to update the -// method signatures, including the "self" parameter! You may -// also need to update the variable bindings within main. -fn main() { - let library = Library::new(); - - //println!("The library is empty: library.is_empty() -> {}", library.is_empty()); - // - //library.add_book(Book::new("Lord of the Rings", 1954)); - //library.add_book(Book::new("Alice's Adventures in Wonderland", 1865)); - // - //println!("The library is no longer empty: library.is_empty() -> {}", library.is_empty()); - // - // - //library.print_books(); - // - //match library.oldest_book() { - // Some(book) => println!("The oldest book is {}", book.title), - // None => println!("The library is empty!"), - //} - // - //println!("The library has {} books", library.len()); - //library.print_books(); +// ANCHOR: test_membership +/// Check whether the given integer is in the hash set. +fn test_membership(hashset: &IntegerHashSet, i: u32) -> bool { + // ANCHOR_END: test_membership + // Number of buckets always fits in a u32, by construction. + let b = i % hashset.0.len() as u32; + return hashset.0[b as usize].contains(&i); } -// ANCHOR_END: main +// ANCHOR: tests #[test] -fn test_library_len() { - let mut library = Library::new(); - assert_eq!(library.len(), 0); - assert!(library.is_empty()); - - library.add_book(Book::new("Lord of the Rings", 1954)); - library.add_book(Book::new("Alice's Adventures in Wonderland", 1865)); - assert_eq!(library.len(), 2); - assert!(!library.is_empty()); +fn empty() { + let hashset = new(16, vec![]); + assert_eq!(test_membership(&hashset, 0), false); + assert_eq!(test_membership(&hashset, 10), false); } #[test] -fn test_library_is_empty() { - let mut library = Library::new(); - assert!(library.is_empty()); - - library.add_book(Book::new("Lord of the Rings", 1954)); - assert!(!library.is_empty()); -} - -#[test] -fn test_library_print_books() { - let mut library = Library::new(); - library.add_book(Book::new("Lord of the Rings", 1954)); - library.add_book(Book::new("Alice's Adventures in Wonderland", 1865)); - // We could try and capture stdout, but let us just call the - // method to start with. - library.print_books(); -} - -#[test] -fn test_library_oldest_book() { - let mut library = Library::new(); - assert!(library.oldest_book().is_none()); - - library.add_book(Book::new("Lord of the Rings", 1954)); - assert_eq!( - library.oldest_book().map(|b| b.title.as_str()), - Some("Lord of the Rings") - ); - - library.add_book(Book::new("Alice's Adventures in Wonderland", 1865)); - assert_eq!( - library.oldest_book().map(|b| b.title.as_str()), - Some("Alice's Adventures in Wonderland") - ); -} +fn membership() { + let hashset = new(16, vec![0, 23, 11, 128]); + assert_eq!(test_membership(&hashset, 0), true); + assert_eq!(test_membership(&hashset, 16), false); + assert_eq!(test_membership(&hashset, 11), true); + assert_eq!(test_membership(&hashset, 23), true); + assert_eq!(test_membership(&hashset, 39), false); + assert_eq!(test_membership(&hashset, 128), true); +} +// ANCHOR_END: tests diff --git a/src/std-types/option.md b/src/std-types/option.md index c6588284212c..5d1cfc118259 100644 --- a/src/std-types/option.md +++ b/src/std-types/option.md @@ -2,67 +2,33 @@ minutes: 3 existing course material: - std/option-result.md -- std.md --- - # Option -# `Option` and `Result` +We have already seen some use of `Option`. It stores either a +value of type `T` or nothing. For example, +[`String::find`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.find) +returns an `Option`. -The types represent optional data: - -```rust,editable +```rust,editable,should_panic fn main() { - let numbers = vec![10, 20, 30]; - let first: Option<&i8> = numbers.first(); - println!("first: {first:?}"); - - let idx: Result = numbers.binary_search(&10); - println!("idx: {idx:?}"); + let name = "Löwe 老虎 Léopard Gepardi"; + let mut position: Option = name.find('é'); + println!("find returned {position:?}"); + assert_eq!(position.unwrap(), 14); + position = name.find('Z'); + println!("find returned {position:?}"); + assert_eq!(position.expect("Character not found"), 0); } ```
-* `Option` and `Result` are widely used not just in the standard library. -* `Option<&T>` has zero space overhead compared to `&T`. -* `Result` is the standard type to implement error handling as we will see on Day 3. -* `binary_search` returns `Result`. - * If found, `Result::Ok` holds the index where the element is found. - * Otherwise, `Result::Err` contains the index where such an element should be inserted. - -
-# Standard Library - -Rust comes with a standard library which helps establish a set of common types -used by Rust library and programs. This way, two libraries can work together -smoothly because they both use the same `String` type. - -The common vocabulary types include: - -* [`Option` and `Result`](std/option-result.md) types: used for optional values - and [error handling](error-handling.md). - -* [`String`](std/string.md): the default string type used for owned data. - -* [`Vec`](std/vec.md): a standard extensible vector. - -* [`HashMap`](std/hashmap.md): a hash map type with a configurable hashing - algorithm. - -* [`Box`](std/box.md): an owned pointer for heap-allocated data. - -* [`Rc`](std/rc.md): a shared reference-counted pointer for heap-allocated data. - -
- - * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. - * `core` includes the most basic types and functions that don't depend on `libc`, allocator or - even the presence of an operating system. - * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`. - * Embedded Rust applications often only use `core`, and sometimes `alloc`. + * `Option` is widely used, not just in the standard library. + * `unwrap` will return the value in an `Option`, or panic. `expect` is similar but takes an error message. + * You can panic on None, but you can't "accidentally" forget to check for None. + * It's common to `unwrap`/`expect` all over the place when hacking something together, but production code typically handles `None` in a nicer fashion. + * The niche optimization means that `Option` often has the same size in memory as `T`.
diff --git a/src/std-types/result.md b/src/std-types/result.md index c1d520c1b9f1..66812d66babf 100644 --- a/src/std-types/result.md +++ b/src/std-types/result.md @@ -4,22 +4,27 @@ existing course material: - error-handling/result.md --- -# Structured Error Handling with `Result` +# Result -We have already seen the `Result` enum. This is used pervasively when errors are -expected as part of normal operation: +`Result` is similar to `Option`, but indicates the success or failure of an +operation, each with a different type. This is similar to the `Result` defined +in the expression exercise, but generic: `Result` where `T` is used in +the `Ok` variant and `E` appears in the `Err` variant. ```rust,editable -use std::fs; +use std::fs::File; use std::io::Read; fn main() { - let file = fs::File::open("diary.txt"); + let file: Result = File::open("diary.txt"); match file { Ok(mut file) => { let mut contents = String::new(); - file.read_to_string(&mut contents); - println!("Dear diary: {contents}"); + if let Ok(bytes) = file.read_to_string(&mut contents) { + println!("Dear diary: {contents} ({bytes} bytes)"); + } else { + println!("Could not read file content"); + } }, Err(err) => { println!("The diary could not be opened: {err}"); @@ -35,5 +40,6 @@ fn main() { `unwrap()` or `expect()` can be called, and this is a signal of the developer intent too. * `Result` documentation is a recommended read. Not during the course, but it is worth mentioning. It contains a lot of convenience methods and functions that help functional-style programming. +* `Result` is the standard type to implement error handling as we will see on Day 3. diff --git a/src/std-types/std.md b/src/std-types/std.md new file mode 100644 index 000000000000..c28a3d279414 --- /dev/null +++ b/src/std-types/std.md @@ -0,0 +1,40 @@ +--- +minutes: 3 +existing course material: +- std/std.md +--- + +# Standard Library + +Rust comes with a standard library which helps establish a set of common types +used by Rust library and programs. It is extensively documented at https://doc.rust-lang.org/. + +## Generics + +The course will cover generics fully later on, but many important standard +library types are generic so it's important to understand a little bit now. + +Generic types are parameterized on one or more other types, and those types +must be fully specified to get a concrete type you can use in your program. The +type parameters are written between `<..>` after the type name. For example, a +vector of `u32` values is written `Vec`, while a vector of strings is +`Vec`. + +## Iterators + +Iterators, too, will be covered in more depth later. They are widely used to +iterate over collections in the standard library. When a method returns an +iterator, that iterator will have [lots of useful +methods](https://doc.rust-lang.org/std/iter/trait.Iterator.html) like `count()` +or `nth()`. + +
+ + * In fact, Rust contains several layers of the Standard Library: `core`, `alloc` and `std`. + * `core` includes the most basic types and functions that don't depend on `libc`, allocator or + even the presence of an operating system. + * `alloc` includes types which require a global heap allocator, such as `Vec`, `Box` and `Arc`. + * Embedded Rust applications often only use `core`, and sometimes `alloc`. + +
+ diff --git a/src/std-types/string.md b/src/std-types/string.md index b69abbd97ef6..e93c2ce45ee0 100644 --- a/src/std-types/string.md +++ b/src/std-types/string.md @@ -38,8 +38,8 @@ fn main() { * `String::chars` returns an iterator over the actual characters. Note that a `char` can be different from what a human will consider a "character" due to [grapheme clusters](https://docs.rs/unicode-segmentation/latest/unicode_segmentation/struct.Graphemes.html). * When people refer to strings they could either be talking about `&str` or `String`. * When a type implements `Deref`, the compiler will let you transparently call methods from `T`. + * We haven't discussed the `Deref` trait yet, so at this point this mostly explains the structure of the sidebar in the documentation. * `String` implements `Deref` which transparently gives it access to `str`'s methods. - * Write and compare `let s3 = s1.deref();` and `let s3 = &*s1`;. * `String` is implemented as a wrapper around a vector of bytes, many of the operations you see supported on vectors are also supported on `String`, but with some extra guarantees. * Compare the different ways to index a `String`: * To a character by using `s3.chars().nth(i).unwrap()` where `i` is in-bound, out-of-bounds. diff --git a/src/std-types/vec.md b/src/std-types/vec.md index 8cc29ebada8e..56af3673c26c 100644 --- a/src/std-types/vec.md +++ b/src/std-types/vec.md @@ -49,7 +49,5 @@ methods on a `Vec`. elements to the vector. * To index the vector you use `[` `]`, but they will panic if out of bounds. Alternatively, using `get` will return an `Option`. The `pop` function will remove the last element. -* Show iterating over a vector and mutating the value: - `for e in &mut v { *e += 50; }`