├── .gitattributes ├── .github └── workflows │ └── rbe.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── TRANSLATING.md ├── TRANSLATING_JA.md ├── TRANSLATING_ZH.md ├── book.toml ├── po ├── es.po ├── ja.po └── zh.po ├── src ├── SUMMARY.md ├── attribute.md ├── attribute │ ├── cfg.md │ ├── cfg │ │ └── custom.md │ ├── crate.md │ └── unused.md ├── cargo.md ├── cargo │ ├── build_scripts.md │ ├── conventions.md │ ├── deps.md │ └── test.md ├── compatibility.md ├── compatibility │ └── raw_identifiers.md ├── conversion.md ├── conversion │ ├── from_into.md │ ├── string.md │ └── try_from_try_into.md ├── crates.md ├── crates │ ├── lib.md │ └── using_lib.md ├── custom_types.md ├── custom_types │ ├── constants.md │ ├── enum.md │ ├── enum │ │ ├── c_like.md │ │ ├── enum_use.md │ │ └── testcase_linked_list.md │ └── structs.md ├── error.md ├── error │ ├── abort_unwind.md │ ├── iter_result.md │ ├── multiple_error_types.md │ ├── multiple_error_types │ │ ├── boxing_errors.md │ │ ├── define_error_type.md │ │ ├── option_result.md │ │ ├── reenter_question_mark.md │ │ └── wrap_error.md │ ├── option_unwrap.md │ ├── option_unwrap │ │ ├── and_then.md │ │ ├── defaults.md │ │ ├── map.md │ │ └── question_mark.md │ ├── panic.md │ ├── result.md │ └── result │ │ ├── early_returns.md │ │ ├── enter_question_mark.md │ │ ├── result_alias.md │ │ └── result_map.md ├── expression.md ├── flow_control.md ├── flow_control │ ├── for.md │ ├── if_else.md │ ├── if_let.md │ ├── let_else.md │ ├── loop.md │ ├── loop │ │ ├── nested.md │ │ └── return.md │ ├── match.md │ ├── match │ │ ├── binding.md │ │ ├── destructuring.md │ │ ├── destructuring │ │ │ ├── destructure_enum.md │ │ │ ├── destructure_pointers.md │ │ │ ├── destructure_slice.md │ │ │ ├── destructure_structures.md │ │ │ └── destructure_tuple.md │ │ └── guard.md │ ├── while.md │ └── while_let.md ├── fn.md ├── fn │ ├── closures.md │ ├── closures │ │ ├── anonymity.md │ │ ├── capture.md │ │ ├── closure_examples.md │ │ ├── closure_examples │ │ │ ├── iter_any.md │ │ │ └── iter_find.md │ │ ├── input_functions.md │ │ ├── input_parameters.md │ │ └── output_parameters.md │ ├── diverging.md │ ├── hof.md │ └── methods.md ├── generics.md ├── generics │ ├── assoc_items.md │ ├── assoc_items │ │ ├── the_problem.md │ │ └── types.md │ ├── bounds.md │ ├── bounds │ │ └── testcase_empty.md │ ├── gen_fn.md │ ├── gen_trait.md │ ├── impl.md │ ├── multi_bounds.md │ ├── new_types.md │ ├── phantom.md │ ├── phantom │ │ └── testcase_units.md │ └── where.md ├── hello.md ├── hello │ ├── comment.md │ ├── print.md │ └── print │ │ ├── fmt.md │ │ ├── print_debug.md │ │ ├── print_display.md │ │ └── print_display │ │ └── testcase_list.md ├── index.md ├── macros.md ├── macros │ ├── designators.md │ ├── dry.md │ ├── dsl.md │ ├── overload.md │ ├── repeat.md │ ├── syntax.md │ └── variadics.md ├── meta.md ├── meta │ ├── doc.md │ └── playground.md ├── mod.md ├── mod │ ├── split.md │ ├── struct_visibility.md │ ├── super.md │ ├── use.md │ └── visibility.md ├── primitives.md ├── primitives │ ├── array.md │ ├── literals.md │ └── tuples.md ├── scope.md ├── scope │ ├── borrow.md │ ├── borrow │ │ ├── alias.md │ │ ├── mut.md │ │ └── ref.md │ ├── lifetime.md │ ├── lifetime │ │ ├── elision.md │ │ ├── explicit.md │ │ ├── fn.md │ │ ├── lifetime_bounds.md │ │ ├── lifetime_coercion.md │ │ ├── methods.md │ │ ├── static_lifetime.md │ │ ├── struct.md │ │ └── trait.md │ ├── move.md │ ├── move │ │ ├── mut.md │ │ └── partial_move.md │ └── raii.md ├── std.md ├── std │ ├── arc.md │ ├── box.md │ ├── hash.md │ ├── hash │ │ ├── alt_key_types.md │ │ └── hashset.md │ ├── option.md │ ├── panic.md │ ├── rc.md │ ├── result.md │ ├── result │ │ └── question_mark.md │ ├── str.md │ └── vec.md ├── std_misc.md ├── std_misc │ ├── arg.md │ ├── arg │ │ └── matching.md │ ├── channels.md │ ├── ffi.md │ ├── file.md │ ├── file │ │ ├── create.md │ │ ├── open.md │ │ └── read_lines.md │ ├── fs.md │ ├── path.md │ ├── process.md │ ├── process │ │ ├── pipe.md │ │ └── wait.md │ ├── threads.md │ └── threads │ │ └── testcase_mapreduce.md ├── testing.md ├── testing │ ├── dev_dependencies.md │ ├── doc_testing.md │ ├── integration_testing.md │ └── unit_testing.md ├── trait.md ├── trait │ ├── clone.md │ ├── derive.md │ ├── disambiguating.md │ ├── drop.md │ ├── dyn.md │ ├── impl_trait.md │ ├── iter.md │ ├── ops.md │ └── supertraits.md ├── types.md ├── types │ ├── alias.md │ ├── cast.md │ ├── inference.md │ └── literals.md ├── unsafe.md ├── unsafe │ └── asm.md ├── variable_bindings.md └── variable_bindings │ ├── declare.md │ ├── freeze.md │ ├── mut.md │ └── scope.md ├── theme ├── css │ └── language-picker.css ├── head.hbs └── js │ └── language-picker.js └── triagebot.toml /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.github/workflows/rbe.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | 4 | env: 5 | # Update the language picker in index.hbs to link new languages. 6 | LANGUAGES: ja zh es 7 | 8 | jobs: 9 | test: 10 | name: Run tests 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | # We need the full history below. 16 | fetch-depth: 0 17 | 18 | - name: Update rustup 19 | run: rustup self update 20 | 21 | - name: Install Rust 22 | run: | 23 | rustup set profile minimal 24 | rustup toolchain install nightly -c rust-docs 25 | rustup default nightly 26 | 27 | - name: Install mdbook 28 | run: | 29 | mkdir bin 30 | curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.51/mdbook-v0.4.51-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=bin 31 | echo "$(pwd)/bin" >> ${GITHUB_PATH} 32 | 33 | - name: Install mdbook-i18n-helpers 34 | run: | 35 | cargo install mdbook-i18n-helpers --locked --version 0.3.4 36 | 37 | - name: Report versions 38 | run: | 39 | rustup --version 40 | rustc -Vv 41 | mdbook --version 42 | 43 | - name: Run tests 44 | run: mdbook test 45 | 46 | - name: Build HTML 47 | run: mdbook build 48 | 49 | - name: Check for broken links 50 | run: | 51 | curl -sSLo linkcheck.sh \ 52 | https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/linkcheck.sh 53 | sh linkcheck.sh --all rust-by-example 54 | 55 | - name: Build all translations 56 | run: | 57 | for po_lang in ${{ env.LANGUAGES }}; do 58 | echo "::group::Building $po_lang translation" 59 | # Set language and adjust site URL. Clear the redirects 60 | # since they are in sync with the source files, not the 61 | # translation. 62 | MDBOOK_BOOK__LANGUAGE=$po_lang \ 63 | mdbook build -d book/$po_lang 64 | echo "::endgroup::" 65 | done 66 | 67 | - name: Check all translations for broken links 68 | run: | 69 | for po_lang in ${{ env.LANGUAGES }}; do 70 | MDBOOK_BOOK__LANGUAGE=$po_lang \ 71 | sh linkcheck.sh --all rust-by-example 72 | done 73 | 74 | - name: Upload Artifact 75 | uses: actions/upload-artifact@v4 76 | with: 77 | name: rust-by-example 78 | path: book 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | 3 | po/messages.pot 4 | 5 | .vscode/ 6 | 7 | # Auto-generated files from macOS 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Jorge Aparicio 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /TRANSLATING_ZH.md: -------------------------------------------------------------------------------- 1 | # Rust by Example 中文版翻译指南 2 | 3 | Rust by Example 中文版的翻译在 https://github.com/rust-lang-cn/rust-by-example 仓库进行审核和校对。 4 | 5 | 如果您希望参与翻译,请按照以下流程操作: 6 | 7 | 1. 复刻(fork)https://github.com/rust-lang/rust-by-example 仓库。 8 | 9 | 2. 在 `po/zh.po` 文件中添加或修改译文。 10 | 11 | 3. 向 https://github.com/rust-lang-cn/rust-by-example 仓库的 `zh` 分支提交 PR(Pull Request)。 12 | - 先在 rust-lang-cn 仓库进行审校,而非直接向原始仓库提交 PR,这样可以更方便进行译文讨论。 13 | - 中文社区仓库的默认分支为 `zh`,因此正常创建 PR 时会自动指向该分支。 14 | 15 | rust-lang-cn 翻译组成员的维护流程: 16 | 17 | 1. 审核并校对提交的 PR,先合并到 `zh` 分支。 18 | 19 | 2. 向 https://github.com/rust-lang/rust-by-example 原始仓库提交 PR。 20 | 21 | ## 翻译规范 22 | 23 | ### 总体原则 24 | 25 | * 文风应保持正式、清晰、简洁 26 | * 标点符号原则上使用全角(如括号"()"和冒号":"等) 27 | 28 | ### 术语翻译指南 29 | 30 | * 对于已经广泛接受的技术术语,保留英文或使用通用的中文翻译 31 | * 避免生硬的直译,优先考虑符合中文语境的自然表达 32 | * 保持术语翻译的一致性,可参考 [Rust 语言术语中英文对照表](https://github.com/rust-lang-cn/english-chinese-glossary-of-rust/blob/master/rust-glossary.md) 33 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | title = "Rust By Example" 3 | description = "Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust concepts and standard libraries." 4 | authors = ["The Rust Community"] 5 | 6 | [output.html.playpen] 7 | editable = true 8 | editor = "ace" 9 | line-numbers = true 10 | 11 | [output.html.fold] 12 | enable = true 13 | 14 | [output.html] 15 | git-repository-url = "https://github.com/rust-lang/rust-by-example" 16 | edit-url-template = "https://github.com/rust-lang/rust-by-example/edit/master/{path}" 17 | hash-files = true 18 | additional-css = [ 19 | "theme/css/language-picker.css", 20 | ] 21 | additional-js = ["theme/js/language-picker.js"] 22 | 23 | [rust] 24 | edition = "2021" 25 | 26 | [build] 27 | extra-watch-dirs = ["po"] 28 | 29 | [preprocessor.gettext] 30 | after = ["links"] 31 | -------------------------------------------------------------------------------- /src/attribute.md: -------------------------------------------------------------------------------- 1 | # Attributes 2 | 3 | An attribute is metadata applied to some module, crate or item. This metadata 4 | can be used to/for: 5 | 6 | 7 | 8 | * [conditional compilation of code][cfg] 9 | * [set crate name, version and type (binary or library)][crate] 10 | * disable [lints][lint] (warnings) 11 | * enable compiler features (macros, glob imports, etc.) 12 | * link to a foreign library 13 | * mark functions as unit tests 14 | * mark functions that will be part of a benchmark 15 | * [attribute like macros][macros] 16 | 17 | Attributes look like `#[outer_attribute]` or `#![inner_attribute]`, 18 | with the difference between them being where they apply. 19 | 20 | * `#[outer_attribute]` applies to the [item][item] immediately 21 | following it. Some examples of items are: a function, a module 22 | declaration, a constant, a structure, an enum. Here is an example 23 | where attribute `#[derive(Debug)]` applies to the struct 24 | `Rectangle`: 25 | 26 | ```rust 27 | #[derive(Debug)] 28 | struct Rectangle { 29 | width: u32, 30 | height: u32, 31 | } 32 | ``` 33 | 34 | * `#![inner_attribute]` applies to the enclosing [item][item] (typically a 35 | module or a crate). In other words, this attribute is interpreted as 36 | applying to the entire scope in which it's placed. Here is an example 37 | where `#![allow(unused_variables)]` applies to the whole crate (if 38 | placed in `main.rs`): 39 | 40 | ```rust 41 | #![allow(unused_variables)] 42 | 43 | fn main() { 44 | let x = 3; // This would normally warn about an unused variable. 45 | } 46 | ``` 47 | 48 | Attributes can take arguments with different syntaxes: 49 | 50 | * `#[attribute = "value"]` 51 | * `#[attribute(key = "value")]` 52 | * `#[attribute(value)]` 53 | 54 | Attributes can have multiple values and can be separated over multiple lines, too: 55 | 56 | ```rust,ignore 57 | #[attribute(value, value2)] 58 | 59 | 60 | #[attribute(value, value2, value3, 61 | value4, value5)] 62 | ``` 63 | 64 | [cfg]: attribute/cfg.md 65 | [crate]: attribute/crate.md 66 | [item]: https://doc.rust-lang.org/stable/reference/items.html 67 | [lint]: https://en.wikipedia.org/wiki/Lint_%28software%29 68 | [macros]: https://doc.rust-lang.org/book/ch19-06-macros.html#attribute-like-macros 69 | -------------------------------------------------------------------------------- /src/attribute/cfg.md: -------------------------------------------------------------------------------- 1 | # `cfg` 2 | 3 | Configuration conditional checks are possible through two different operators: 4 | 5 | * the `cfg` attribute: `#[cfg(...)]` in attribute position 6 | * the `cfg!` macro: `cfg!(...)` in boolean expressions 7 | 8 | While the former enables conditional compilation, the latter conditionally 9 | evaluates to `true` or `false` literals allowing for checks at run-time. Both 10 | utilize identical argument syntax. 11 | 12 | `cfg!`, unlike `#[cfg]`, does not remove any code and only evaluates to true or false. For example, all blocks in an if/else expression need to be valid when `cfg!` is used for the condition, regardless of what `cfg!` is evaluating. 13 | 14 | ```rust,editable 15 | // This function only gets compiled if the target OS is linux 16 | #[cfg(target_os = "linux")] 17 | fn are_you_on_linux() { 18 | println!("You are running linux!"); 19 | } 20 | 21 | // And this function only gets compiled if the target OS is *not* linux 22 | #[cfg(not(target_os = "linux"))] 23 | fn are_you_on_linux() { 24 | println!("You are *not* running linux!"); 25 | } 26 | 27 | fn main() { 28 | are_you_on_linux(); 29 | 30 | println!("Are you sure?"); 31 | if cfg!(target_os = "linux") { 32 | println!("Yes. It's definitely linux!"); 33 | } else { 34 | println!("Yes. It's definitely *not* linux!"); 35 | } 36 | } 37 | ``` 38 | 39 | ### See also: 40 | 41 | [the reference][ref], [`cfg!`][cfg], and [macros][macros]. 42 | 43 | [cfg]: https://doc.rust-lang.org/std/macro.cfg!.html 44 | [macros]: ../macros.md 45 | [ref]: https://doc.rust-lang.org/reference/attributes.html#conditional-compilation 46 | -------------------------------------------------------------------------------- /src/attribute/cfg/custom.md: -------------------------------------------------------------------------------- 1 | # Custom 2 | 3 | Some conditionals like `target_os` are implicitly provided by `rustc`, but 4 | custom conditionals must be passed to `rustc` using the `--cfg` flag. 5 | 6 | ```rust,editable,ignore,mdbook-runnable 7 | #[cfg(some_condition)] 8 | fn conditional_function() { 9 | println!("condition met!"); 10 | } 11 | 12 | fn main() { 13 | conditional_function(); 14 | } 15 | ``` 16 | 17 | Try to run this to see what happens without the custom `cfg` flag. 18 | 19 | With the custom `cfg` flag: 20 | 21 | ```shell 22 | $ rustc --cfg some_condition custom.rs && ./custom 23 | condition met! 24 | ``` 25 | -------------------------------------------------------------------------------- /src/attribute/crate.md: -------------------------------------------------------------------------------- 1 | # Crates 2 | 3 | The `crate_type` attribute can be used to tell the compiler whether a crate is 4 | a binary or a library (and even which type of library), and the `crate_name` 5 | attribute can be used to set the name of the crate. 6 | 7 | However, it is important to note that both the `crate_type` and `crate_name` 8 | attributes have **no** effect whatsoever when using Cargo, the Rust package 9 | manager. Since Cargo is used for the majority of Rust projects, this means 10 | real-world uses of `crate_type` and `crate_name` are relatively limited. 11 | 12 | ```rust,editable 13 | // This crate is a library 14 | #![crate_type = "lib"] 15 | // The library is named "rary" 16 | #![crate_name = "rary"] 17 | 18 | pub fn public_function() { 19 | println!("called rary's `public_function()`"); 20 | } 21 | 22 | fn private_function() { 23 | println!("called rary's `private_function()`"); 24 | } 25 | 26 | pub fn indirect_access() { 27 | print!("called rary's `indirect_access()`, that\n> "); 28 | 29 | private_function(); 30 | } 31 | ``` 32 | 33 | When the `crate_type` attribute is used, we no longer need to pass the 34 | `--crate-type` flag to `rustc`. 35 | 36 | ```shell 37 | $ rustc lib.rs 38 | $ ls lib* 39 | library.rlib 40 | ``` 41 | -------------------------------------------------------------------------------- /src/attribute/unused.md: -------------------------------------------------------------------------------- 1 | # `dead_code` 2 | 3 | The compiler provides a `dead_code` 4 | [*lint*][lint] that will warn 5 | about unused functions. An *attribute* can be used to disable the lint. 6 | 7 | ```rust,editable 8 | fn used_function() {} 9 | 10 | // `#[allow(dead_code)]` is an attribute that disables the `dead_code` lint 11 | #[allow(dead_code)] 12 | fn unused_function() {} 13 | 14 | fn noisy_unused_function() {} 15 | // FIXME ^ Add an attribute to suppress the warning 16 | 17 | fn main() { 18 | used_function(); 19 | } 20 | ``` 21 | 22 | Note that in real programs, you should eliminate dead code. In these examples 23 | we'll allow dead code in some places because of the interactive nature of the 24 | examples. 25 | 26 | [lint]: https://en.wikipedia.org/wiki/Lint_%28software%29 27 | -------------------------------------------------------------------------------- /src/cargo.md: -------------------------------------------------------------------------------- 1 | # Cargo 2 | 3 | `cargo` is the official Rust package management tool. It has lots of really 4 | useful features to improve code quality and developer velocity! These include 5 | 6 | - Dependency management and integration with [crates.io](https://crates.io) (the 7 | official Rust package registry) 8 | - Awareness of unit tests 9 | - Awareness of benchmarks 10 | 11 | This chapter will go through some quick basics, but you can find the 12 | comprehensive docs in [The Cargo Book](https://doc.rust-lang.org/cargo/). 13 | -------------------------------------------------------------------------------- /src/cargo/build_scripts.md: -------------------------------------------------------------------------------- 1 | # Build Scripts 2 | 3 | Sometimes a normal build from `cargo` is not enough. Perhaps your crate needs 4 | some pre-requisites before `cargo` will successfully compile, things like code 5 | generation, or some native code that needs to be compiled. To solve this problem 6 | we have build scripts that Cargo can run. 7 | 8 | To add a build script to your package it can either be specified in the 9 | `Cargo.toml` as follows: 10 | 11 | ```toml 12 | [package] 13 | ... 14 | build = "build.rs" 15 | ``` 16 | 17 | Otherwise Cargo will look for a `build.rs` file in the project directory by 18 | default. 19 | 20 | ## How to use a build script 21 | 22 | The build script is simply another Rust file that will be compiled and invoked 23 | prior to compiling anything else in the package. Hence it can be used to fulfill 24 | pre-requisites of your crate. 25 | 26 | Cargo provides the script with inputs via environment variables [specified 27 | here] that can be used. 28 | 29 | The script provides output via stdout. All lines printed are written to 30 | `target/debug/build//output`. Further, lines prefixed with `cargo:` will be 31 | interpreted by Cargo directly and hence can be used to define parameters for the 32 | package's compilation. 33 | 34 | For further specification and examples have a read of the 35 | [Cargo specification][cargo_specification]. 36 | 37 | [specified here]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts 38 | 39 | [cargo_specification]: https://doc.rust-lang.org/cargo/reference/build-scripts.html 40 | -------------------------------------------------------------------------------- /src/cargo/conventions.md: -------------------------------------------------------------------------------- 1 | # Conventions 2 | 3 | In the previous chapter, we saw the following directory hierarchy: 4 | 5 | ```txt 6 | foo 7 | ├── Cargo.toml 8 | └── src 9 | └── main.rs 10 | ``` 11 | 12 | Suppose that we wanted to have two binaries in the same project, though. What 13 | then? 14 | 15 | It turns out that `cargo` supports this. The default binary name is `main`, as 16 | we saw before, but you can add additional binaries by placing them in a `bin/` 17 | directory: 18 | 19 | ```txt 20 | foo 21 | ├── Cargo.toml 22 | └── src 23 | ├── main.rs 24 | └── bin 25 | └── my_other_bin.rs 26 | ``` 27 | 28 | To tell `cargo` to only compile or run this binary, we just pass `cargo` the 29 | `--bin my_other_bin` flag, where `my_other_bin` is the name of the binary we 30 | want to work with. 31 | 32 | In addition to extra binaries, `cargo` supports [more features] such as 33 | benchmarks, tests, and examples. 34 | 35 | In the next chapter, we will look more closely at tests. 36 | 37 | [more features]: https://doc.rust-lang.org/cargo/guide/project-layout.html 38 | -------------------------------------------------------------------------------- /src/compatibility.md: -------------------------------------------------------------------------------- 1 | # Compatibility 2 | 3 | The Rust language is evolving rapidly, and because of this certain compatibility 4 | issues can arise, despite efforts to ensure forwards-compatibility wherever 5 | possible. 6 | 7 | * [Raw identifiers](compatibility/raw_identifiers.md) 8 | -------------------------------------------------------------------------------- /src/compatibility/raw_identifiers.md: -------------------------------------------------------------------------------- 1 | # Raw identifiers 2 | 3 | Rust, like many programming languages, has the concept of "keywords". 4 | These identifiers mean something to the language, and so you cannot use them in 5 | places like variable names, function names, and other places. 6 | Raw identifiers let you use keywords where they would not normally be allowed. 7 | This is particularly useful when Rust introduces new keywords, and a library 8 | using an older edition of Rust has a variable or function with the same name 9 | as a keyword introduced in a newer edition. 10 | 11 | For example, consider a crate `foo` compiled with the 2015 edition of Rust that 12 | exports a function named `try`. This keyword is reserved for a new feature in 13 | the 2018 edition, so without raw identifiers, we would have no way to name the 14 | function. 15 | 16 | ```rust,ignore 17 | extern crate foo; 18 | 19 | fn main() { 20 | foo::try(); 21 | } 22 | ``` 23 | 24 | You'll get this error: 25 | 26 | ```text 27 | error: expected identifier, found keyword `try` 28 | --> src/main.rs:4:4 29 | | 30 | 4 | foo::try(); 31 | | ^^^ expected identifier, found keyword 32 | ``` 33 | 34 | You can write this with a raw identifier: 35 | 36 | ```rust,ignore 37 | extern crate foo; 38 | 39 | fn main() { 40 | foo::r#try(); 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /src/conversion.md: -------------------------------------------------------------------------------- 1 | # Conversion 2 | 3 | Primitive types can be converted to each other through [casting]. 4 | 5 | Rust addresses conversion between custom types (i.e., `struct` and `enum`) 6 | by the use of [traits]. The generic 7 | conversions will use the [`From`] and [`Into`] traits. However there are more 8 | specific ones for the more common cases, in particular when converting to and 9 | from `String`s. 10 | 11 | [casting]: types/cast.md 12 | [traits]: trait.md 13 | [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html 14 | [`Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html 15 | -------------------------------------------------------------------------------- /src/conversion/try_from_try_into.md: -------------------------------------------------------------------------------- 1 | # `TryFrom` and `TryInto` 2 | 3 | Similar to [`From` and `Into`][from-into], [`TryFrom`] and [`TryInto`] are 4 | generic traits for converting between types. Unlike `From`/`Into`, the 5 | `TryFrom`/`TryInto` traits are used for fallible conversions, and as such, 6 | return [`Result`]s. 7 | 8 | [from-into]: from_into.html 9 | [`TryFrom`]: https://doc.rust-lang.org/std/convert/trait.TryFrom.html 10 | [`TryInto`]: https://doc.rust-lang.org/std/convert/trait.TryInto.html 11 | [`Result`]: https://doc.rust-lang.org/std/result/enum.Result.html 12 | 13 | ```rust,editable 14 | use std::convert::TryFrom; 15 | use std::convert::TryInto; 16 | 17 | #[derive(Debug, PartialEq)] 18 | struct EvenNumber(i32); 19 | 20 | impl TryFrom for EvenNumber { 21 | type Error = (); 22 | 23 | fn try_from(value: i32) -> Result { 24 | if value % 2 == 0 { 25 | Ok(EvenNumber(value)) 26 | } else { 27 | Err(()) 28 | } 29 | } 30 | } 31 | 32 | fn main() { 33 | // TryFrom 34 | 35 | assert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8))); 36 | assert_eq!(EvenNumber::try_from(5), Err(())); 37 | 38 | // TryInto 39 | 40 | let result: Result = 8i32.try_into(); 41 | assert_eq!(result, Ok(EvenNumber(8))); 42 | let result: Result = 5i32.try_into(); 43 | assert_eq!(result, Err(())); 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /src/crates.md: -------------------------------------------------------------------------------- 1 | # Crates 2 | 3 | A crate is a compilation unit in Rust. Whenever `rustc some_file.rs` is called, 4 | `some_file.rs` is treated as the *crate file*. If `some_file.rs` has `mod` 5 | declarations in it, then the contents of the module files would be inserted in 6 | places where `mod` declarations in the crate file are found, *before* running 7 | the compiler over it. In other words, modules do *not* get compiled 8 | individually, only crates get compiled. 9 | 10 | A crate can be compiled into a binary or into a library. By default, `rustc` 11 | will produce a binary from a crate. This behavior can be overridden by passing 12 | the `--crate-type` flag to `lib`. 13 | -------------------------------------------------------------------------------- /src/crates/lib.md: -------------------------------------------------------------------------------- 1 | # Creating a Library 2 | 3 | Let's create a library, and then see how to link it to another crate. 4 | 5 | In `rary.rs`: 6 | 7 | ```rust,ignore 8 | pub fn public_function() { 9 | println!("called rary's `public_function()`"); 10 | } 11 | 12 | fn private_function() { 13 | println!("called rary's `private_function()`"); 14 | } 15 | 16 | pub fn indirect_access() { 17 | print!("called rary's `indirect_access()`, that\n> "); 18 | 19 | private_function(); 20 | } 21 | ``` 22 | 23 | ```shell 24 | $ rustc --crate-type=lib rary.rs 25 | $ ls lib* 26 | library.rlib 27 | ``` 28 | 29 | Libraries get prefixed with "lib", and by default they get named after their 30 | crate file, but this default name can be overridden by passing 31 | the `--crate-name` option to `rustc` or by using the [`crate_name` 32 | attribute][crate-name]. 33 | 34 | [crate-name]: ../attribute/crate.md 35 | -------------------------------------------------------------------------------- /src/crates/using_lib.md: -------------------------------------------------------------------------------- 1 | # Using a Library 2 | 3 | To link a crate to this new library you may use `rustc`'s `--extern` flag. All 4 | of its items will then be imported under a module named the same as the library. 5 | This module generally behaves the same way as any other module. 6 | 7 | ```rust,ignore 8 | // extern crate rary; // May be required for Rust 2015 edition or earlier 9 | 10 | fn main() { 11 | rary::public_function(); 12 | 13 | // Error! `private_function` is private 14 | //rary::private_function(); 15 | 16 | rary::indirect_access(); 17 | } 18 | ``` 19 | 20 | ```txt 21 | # Where library.rlib is the path to the compiled library, assumed that it's 22 | # in the same directory here: 23 | $ rustc executable.rs --extern rary=library.rlib && ./executable 24 | called rary's `public_function()` 25 | called rary's `indirect_access()`, that 26 | > called rary's `private_function()` 27 | ``` 28 | -------------------------------------------------------------------------------- /src/custom_types.md: -------------------------------------------------------------------------------- 1 | # Custom Types 2 | 3 | Rust custom data types are formed mainly through the two keywords: 4 | 5 | * `struct`: define a structure 6 | * `enum`: define an enumeration 7 | 8 | Constants can also be created via the `const` and `static` keywords. 9 | -------------------------------------------------------------------------------- /src/custom_types/constants.md: -------------------------------------------------------------------------------- 1 | # constants 2 | 3 | Rust has two different types of constants which can be declared in any scope 4 | including global. Both require explicit type annotation: 5 | 6 | * `const`: An unchangeable value (the common case). 7 | * `static`: A possibly mutable variable with [`'static`][static] lifetime. 8 | The static lifetime is inferred and does not have to be specified. 9 | Accessing or modifying a mutable static variable is [`unsafe`][unsafe]. 10 | 11 | ```rust,editable,ignore,mdbook-runnable 12 | // Globals are declared outside all other scopes. 13 | static LANGUAGE: &str = "Rust"; 14 | const THRESHOLD: i32 = 10; 15 | 16 | fn is_big(n: i32) -> bool { 17 | // Access constant in some function 18 | n > THRESHOLD 19 | } 20 | 21 | fn main() { 22 | let n = 16; 23 | 24 | // Access constant in the main thread 25 | println!("This is {}", LANGUAGE); 26 | println!("The threshold is {}", THRESHOLD); 27 | println!("{} is {}", n, if is_big(n) { "big" } else { "small" }); 28 | 29 | // Error! Cannot modify a `const`. 30 | THRESHOLD = 5; 31 | // FIXME ^ Comment out this line 32 | } 33 | ``` 34 | 35 | ### See also: 36 | 37 | [The `const`/`static` RFC]( 38 | https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md), 39 | [`'static` lifetime][static] 40 | 41 | [static]: ../scope/lifetime/static_lifetime.md 42 | [unsafe]: ../unsafe.md 43 | -------------------------------------------------------------------------------- /src/custom_types/enum/c_like.md: -------------------------------------------------------------------------------- 1 | # C-like 2 | 3 | `enum` can also be used as C-like enums. 4 | 5 | ```rust,editable 6 | // An attribute to hide warnings for unused code. 7 | #![allow(dead_code)] 8 | 9 | // enum with implicit discriminator (starts at 0) 10 | enum Number { 11 | Zero, 12 | One, 13 | Two, 14 | } 15 | 16 | // enum with explicit discriminator 17 | enum Color { 18 | Red = 0xff0000, 19 | Green = 0x00ff00, 20 | Blue = 0x0000ff, 21 | } 22 | 23 | fn main() { 24 | // `enums` can be cast as integers. 25 | println!("zero is {}", Number::Zero as i32); 26 | println!("one is {}", Number::One as i32); 27 | 28 | println!("roses are #{:06x}", Color::Red as i32); 29 | println!("violets are #{:06x}", Color::Blue as i32); 30 | } 31 | ``` 32 | 33 | ### See also: 34 | 35 | [casting][cast] 36 | 37 | [cast]: ../../types/cast.md 38 | -------------------------------------------------------------------------------- /src/custom_types/enum/enum_use.md: -------------------------------------------------------------------------------- 1 | # use 2 | 3 | The `use` declaration can be used so manual scoping isn't needed: 4 | 5 | ```rust,editable 6 | // An attribute to hide warnings for unused code. 7 | #![allow(dead_code)] 8 | 9 | enum Stage { 10 | Beginner, 11 | Advanced, 12 | } 13 | 14 | enum Role { 15 | Student, 16 | Teacher, 17 | } 18 | 19 | fn main() { 20 | // Explicitly `use` each name so they are available without 21 | // manual scoping. 22 | use crate::Stage::{Beginner, Advanced}; 23 | // Automatically `use` each name inside `Role`. 24 | use crate::Role::*; 25 | 26 | // Equivalent to `Stage::Beginner`. 27 | let stage = Beginner; 28 | // Equivalent to `Role::Student`. 29 | let role = Student; 30 | 31 | match stage { 32 | // Note the lack of scoping because of the explicit `use` above. 33 | Beginner => println!("Beginners are starting their learning journey!"), 34 | Advanced => println!("Advanced learners are mastering their subjects..."), 35 | } 36 | 37 | match role { 38 | // Note again the lack of scoping. 39 | Student => println!("Students are acquiring knowledge!"), 40 | Teacher => println!("Teachers are spreading knowledge!"), 41 | } 42 | } 43 | ``` 44 | 45 | ### See also: 46 | 47 | [`match`][match] and [`use`][use] 48 | 49 | [use]: ../../mod/use.md 50 | [match]: ../../flow_control/match.md 51 | -------------------------------------------------------------------------------- /src/error.md: -------------------------------------------------------------------------------- 1 | # Error handling 2 | 3 | Error handling is the process of handling the possibility of failure. For 4 | example, failing to read a file and then continuing to use that *bad* input 5 | would clearly be problematic. Noticing and explicitly managing those errors 6 | saves the rest of the program from various pitfalls. 7 | 8 | There are various ways to deal with errors in Rust, which are described in the 9 | following subchapters. They all have more or less subtle differences and different 10 | use cases. As a rule of thumb: 11 | 12 | An explicit `panic` is mainly useful for tests and dealing with unrecoverable errors. 13 | For prototyping it can be useful, for example when dealing with functions that 14 | haven't been implemented yet, but in those cases the more descriptive `unimplemented` 15 | is better. In tests `panic` is a reasonable way to explicitly fail. 16 | 17 | The `Option` type is for when a value is optional or when the lack of a value is 18 | not an error condition. For example the parent of a directory - `/` and `C:` don't 19 | have one. When dealing with `Option`s, `unwrap` is fine for prototyping and cases 20 | where it's absolutely certain that there is guaranteed to be a value. However `expect` 21 | is more useful since it lets you specify an error message in case something goes 22 | wrong anyway. 23 | 24 | When there is a chance that things do go wrong and the caller has to deal with the 25 | problem, use `Result`. You can `unwrap` and `expect` them as well (please don't 26 | do that unless it's a test or quick prototype). 27 | 28 | For a more rigorous discussion of error handling, refer to the error 29 | handling section in the [official book][book]. 30 | 31 | [book]: https://doc.rust-lang.org/book/ch09-00-error-handling.html 32 | -------------------------------------------------------------------------------- /src/error/abort_unwind.md: -------------------------------------------------------------------------------- 1 | # `abort` and `unwind` 2 | 3 | The previous section illustrates the error handling mechanism `panic`. Different code paths can be conditionally compiled based on the panic setting. The current values available are `unwind` and `abort`. 4 | 5 | Building on the prior lemonade example, we explicitly use the panic strategy to exercise different lines of code. 6 | 7 | ```rust,editable,mdbook-runnable 8 | fn drink(beverage: &str) { 9 | // You shouldn't drink too much sugary beverages. 10 | if beverage == "lemonade" { 11 | if cfg!(panic = "abort") { 12 | println!("This is not your party. Run!!!!"); 13 | } else { 14 | println!("Spit it out!!!!"); 15 | } 16 | } else { 17 | println!("Some refreshing {} is all I need.", beverage); 18 | } 19 | } 20 | 21 | fn main() { 22 | drink("water"); 23 | drink("lemonade"); 24 | } 25 | ``` 26 | 27 | Here is another example focusing on rewriting `drink()` and explicitly use the `unwind` keyword. 28 | 29 | ```rust,editable 30 | #[cfg(panic = "unwind")] 31 | fn ah() { 32 | println!("Spit it out!!!!"); 33 | } 34 | 35 | #[cfg(not(panic = "unwind"))] 36 | fn ah() { 37 | println!("This is not your party. Run!!!!"); 38 | } 39 | 40 | fn drink(beverage: &str) { 41 | if beverage == "lemonade" { 42 | ah(); 43 | } else { 44 | println!("Some refreshing {} is all I need.", beverage); 45 | } 46 | } 47 | 48 | fn main() { 49 | drink("water"); 50 | drink("lemonade"); 51 | } 52 | ``` 53 | 54 | The panic strategy can be set from the command line by using `abort` or `unwind`. 55 | 56 | ```console 57 | rustc lemonade.rs -C panic=abort 58 | ``` 59 | -------------------------------------------------------------------------------- /src/error/multiple_error_types.md: -------------------------------------------------------------------------------- 1 | # Multiple error types 2 | 3 | The previous examples have always been very convenient; `Result`s interact 4 | with other `Result`s and `Option`s interact with other `Option`s. 5 | 6 | Sometimes an `Option` needs to interact with a `Result`, or a 7 | `Result` needs to interact with a `Result`. In those 8 | cases, we want to manage our different error types in a way that makes them 9 | composable and easy to interact with. 10 | 11 | In the following code, two instances of `unwrap` generate different error 12 | types. `Vec::first` returns an `Option`, while `parse::` returns a 13 | `Result`: 14 | 15 | ```rust,editable,ignore,mdbook-runnable 16 | fn double_first(vec: Vec<&str>) -> i32 { 17 | let first = vec.first().unwrap(); // Generate error 1 18 | 2 * first.parse::().unwrap() // Generate error 2 19 | } 20 | 21 | fn main() { 22 | let numbers = vec!["42", "93", "18"]; 23 | let empty = vec![]; 24 | let strings = vec!["tofu", "93", "18"]; 25 | 26 | println!("The first doubled is {}", double_first(numbers)); 27 | 28 | println!("The first doubled is {}", double_first(empty)); 29 | // Error 1: the input vector is empty 30 | 31 | println!("The first doubled is {}", double_first(strings)); 32 | // Error 2: the element doesn't parse to a number 33 | } 34 | ``` 35 | 36 | Over the next sections, we'll see several strategies for handling these kind of problems. 37 | -------------------------------------------------------------------------------- /src/error/multiple_error_types/boxing_errors.md: -------------------------------------------------------------------------------- 1 | # `Box`ing errors 2 | 3 | A way to write simple code while preserving the original errors is to [`Box`][box] 4 | them. The drawback is that the underlying error type is only known at runtime and not 5 | [statically determined][dynamic_dispatch]. 6 | 7 | The stdlib helps in boxing our errors by having `Box` implement conversion from 8 | any type that implements the `Error` trait into the trait object `Box`, 9 | via [`From`][from]. 10 | 11 | ```rust,editable 12 | use std::error; 13 | use std::fmt; 14 | 15 | // Change the alias to use `Box`. 16 | type Result = std::result::Result>; 17 | 18 | #[derive(Debug, Clone)] 19 | struct EmptyVec; 20 | 21 | impl fmt::Display for EmptyVec { 22 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 23 | write!(f, "invalid first item to double") 24 | } 25 | } 26 | 27 | impl error::Error for EmptyVec {} 28 | 29 | fn double_first(vec: Vec<&str>) -> Result { 30 | vec.first() 31 | .ok_or_else(|| EmptyVec.into()) // Converts to Box 32 | .and_then(|s| { 33 | s.parse::() 34 | .map_err(|e| e.into()) // Converts to Box 35 | .map(|i| 2 * i) 36 | }) 37 | } 38 | 39 | fn print(result: Result) { 40 | match result { 41 | Ok(n) => println!("The first doubled is {}", n), 42 | Err(e) => println!("Error: {}", e), 43 | } 44 | } 45 | 46 | fn main() { 47 | let numbers = vec!["42", "93", "18"]; 48 | let empty = vec![]; 49 | let strings = vec!["tofu", "93", "18"]; 50 | 51 | print(double_first(numbers)); 52 | print(double_first(empty)); 53 | print(double_first(strings)); 54 | } 55 | ``` 56 | 57 | ### See also: 58 | 59 | [Dynamic dispatch][dynamic_dispatch] and [`Error` trait][error] 60 | 61 | [box]: https://doc.rust-lang.org/std/boxed/struct.Box.html 62 | [dynamic_dispatch]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch 63 | [error]: https://doc.rust-lang.org/std/error/trait.Error.html 64 | [from]: https://doc.rust-lang.org/std/convert/trait.From.html 65 | -------------------------------------------------------------------------------- /src/error/multiple_error_types/define_error_type.md: -------------------------------------------------------------------------------- 1 | # Defining an error type 2 | 3 | Sometimes it simplifies the code to mask all of the different errors with a 4 | single type of error. We'll show this with a custom error. 5 | 6 | Rust allows us to define our own error types. In general, a "good" error type: 7 | 8 | * Represents different errors with the same type 9 | * Presents nice error messages to the user 10 | * Is easy to compare with other types 11 | * Good: `Err(EmptyVec)` 12 | * Bad: `Err("Please use a vector with at least one element".to_owned())` 13 | * Can hold information about the error 14 | * Good: `Err(BadChar(c, position))` 15 | * Bad: `Err("+ cannot be used here".to_owned())` 16 | * Composes well with other errors 17 | 18 | ```rust,editable 19 | use std::fmt; 20 | 21 | type Result = std::result::Result; 22 | 23 | // Define our error types. These may be customized for our error handling cases. 24 | // Now we will be able to write our own errors, defer to an underlying error 25 | // implementation, or do something in between. 26 | #[derive(Debug, Clone)] 27 | struct DoubleError; 28 | 29 | // Generation of an error is completely separate from how it is displayed. 30 | // There's no need to be concerned about cluttering complex logic with the display style. 31 | // 32 | // Note that we don't store any extra info about the errors. This means we can't state 33 | // which string failed to parse without modifying our types to carry that information. 34 | impl fmt::Display for DoubleError { 35 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 36 | write!(f, "invalid first item to double") 37 | } 38 | } 39 | 40 | fn double_first(vec: Vec<&str>) -> Result { 41 | vec.first() 42 | // Change the error to our new type. 43 | .ok_or(DoubleError) 44 | .and_then(|s| { 45 | s.parse::() 46 | // Update to the new error type here also. 47 | .map_err(|_| DoubleError) 48 | .map(|i| 2 * i) 49 | }) 50 | } 51 | 52 | fn print(result: Result) { 53 | match result { 54 | Ok(n) => println!("The first doubled is {}", n), 55 | Err(e) => println!("Error: {}", e), 56 | } 57 | } 58 | 59 | fn main() { 60 | let numbers = vec!["42", "93", "18"]; 61 | let empty = vec![]; 62 | let strings = vec!["tofu", "93", "18"]; 63 | 64 | print(double_first(numbers)); 65 | print(double_first(empty)); 66 | print(double_first(strings)); 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /src/error/multiple_error_types/option_result.md: -------------------------------------------------------------------------------- 1 | # Pulling `Result`s out of `Option`s 2 | 3 | The most basic way of handling mixed error types is to just embed them in each 4 | other. 5 | 6 | ```rust,editable 7 | use std::num::ParseIntError; 8 | 9 | fn double_first(vec: Vec<&str>) -> Option> { 10 | vec.first().map(|first| { 11 | first.parse::().map(|n| 2 * n) 12 | }) 13 | } 14 | 15 | fn main() { 16 | let numbers = vec!["42", "93", "18"]; 17 | let empty = vec![]; 18 | let strings = vec!["tofu", "93", "18"]; 19 | 20 | println!("The first doubled is {:?}", double_first(numbers)); 21 | 22 | println!("The first doubled is {:?}", double_first(empty)); 23 | // Error 1: the input vector is empty 24 | 25 | println!("The first doubled is {:?}", double_first(strings)); 26 | // Error 2: the element doesn't parse to a number 27 | } 28 | ``` 29 | 30 | There are times when we'll want to stop processing on errors (like with 31 | [`?`][enter_question_mark]) but keep going when the `Option` is `None`. The `transpose` function comes in handy to swap the `Result` and `Option`. 32 | 33 | ```rust,editable 34 | use std::num::ParseIntError; 35 | 36 | fn double_first(vec: Vec<&str>) -> Result, ParseIntError> { 37 | let opt = vec.first().map(|first| { 38 | first.parse::().map(|n| 2 * n) 39 | }); 40 | 41 | opt.transpose() 42 | } 43 | 44 | fn main() { 45 | let numbers = vec!["42", "93", "18"]; 46 | let empty = vec![]; 47 | let strings = vec!["tofu", "93", "18"]; 48 | 49 | println!("The first doubled is {:?}", double_first(numbers)); 50 | println!("The first doubled is {:?}", double_first(empty)); 51 | println!("The first doubled is {:?}", double_first(strings)); 52 | } 53 | ``` 54 | 55 | [enter_question_mark]: ../result/enter_question_mark.md 56 | -------------------------------------------------------------------------------- /src/error/option_unwrap.md: -------------------------------------------------------------------------------- 1 | # `Option` & `unwrap` 2 | 3 | In the last example, we showed that we can induce program failure at will. 4 | We told our program to `panic` if we drink a sugary lemonade. 5 | But what if we expect _some_ drink but don't receive one? 6 | That case would be just as bad, so it needs to be handled! 7 | 8 | We _could_ test this against the null string (`""`) as we do with a lemonade. 9 | Since we're using Rust, let's instead have the compiler point out cases 10 | where there's no drink. 11 | 12 | An `enum` called `Option` in the `std` library is used when absence is a 13 | possibility. It manifests itself as one of two "options": 14 | 15 | * `Some(T)`: An element of type `T` was found 16 | * `None`: No element was found 17 | 18 | These cases can either be explicitly handled via `match` or implicitly with 19 | `unwrap`. Implicit handling will either return the inner element or `panic`. 20 | 21 | Note that it's possible to manually customize `panic` with [expect][expect], 22 | but `unwrap` otherwise leaves us with a less meaningful output than explicit 23 | handling. In the following example, explicit handling yields a more 24 | controlled result while retaining the option to `panic` if desired. 25 | 26 | ```rust,editable,ignore,mdbook-runnable 27 | // The adult has seen it all, and can handle any drink well. 28 | // All drinks are handled explicitly using `match`. 29 | fn give_adult(drink: Option<&str>) { 30 | // Specify a course of action for each case. 31 | match drink { 32 | Some("lemonade") => println!("Yuck! Too sugary."), 33 | Some(inner) => println!("{}? How nice.", inner), 34 | None => println!("No drink? Oh well."), 35 | } 36 | } 37 | 38 | // Others will `panic` before drinking sugary drinks. 39 | // All drinks are handled implicitly using `unwrap`. 40 | fn drink(drink: Option<&str>) { 41 | // `unwrap` returns a `panic` when it receives a `None`. 42 | let inside = drink.unwrap(); 43 | if inside == "lemonade" { panic!("AAAaaaaa!!!!"); } 44 | 45 | println!("I love {}s!!!!!", inside); 46 | } 47 | 48 | fn main() { 49 | let water = Some("water"); 50 | let lemonade = Some("lemonade"); 51 | let void = None; 52 | 53 | give_adult(water); 54 | give_adult(lemonade); 55 | give_adult(void); 56 | 57 | let coffee = Some("coffee"); 58 | let nothing = None; 59 | 60 | drink(coffee); 61 | drink(nothing); 62 | } 63 | ``` 64 | 65 | [expect]: https://doc.rust-lang.org/std/option/enum.Option.html#method.expect 66 | -------------------------------------------------------------------------------- /src/error/option_unwrap/question_mark.md: -------------------------------------------------------------------------------- 1 | # Unpacking options with `?` 2 | 3 | You can unpack `Option`s by using `match` statements, but it's often easier to 4 | use the `?` operator. If `x` is an `Option`, then evaluating `x?` will return 5 | the underlying value if `x` is `Some`, otherwise it will terminate whatever 6 | function is being executed and return `None`. 7 | 8 | ```rust,ignore 9 | fn next_birthday(current_age: Option) -> Option { 10 | // If `current_age` is `None`, this returns `None`. 11 | // If `current_age` is `Some`, the inner `u8` value + 1 12 | // gets assigned to `next_age` 13 | let next_age: u8 = current_age? + 1; 14 | Some(format!("Next year I will be {}", next_age)) 15 | } 16 | ``` 17 | 18 | You can chain many `?`s together to make your code much more readable. 19 | 20 | ```rust,editable 21 | struct Person { 22 | job: Option, 23 | } 24 | 25 | #[derive(Clone, Copy)] 26 | struct Job { 27 | phone_number: Option, 28 | } 29 | 30 | #[derive(Clone, Copy)] 31 | struct PhoneNumber { 32 | area_code: Option, 33 | number: u32, 34 | } 35 | 36 | impl Person { 37 | 38 | // Gets the area code of the phone number of the person's job, if it exists. 39 | fn work_phone_area_code(&self) -> Option { 40 | // This would need many nested `match` statements without the `?` operator. 41 | // It would take a lot more code - try writing it yourself and see which 42 | // is easier. 43 | self.job?.phone_number?.area_code 44 | } 45 | } 46 | 47 | fn main() { 48 | let p = Person { 49 | job: Some(Job { 50 | phone_number: Some(PhoneNumber { 51 | area_code: Some(61), 52 | number: 439222222, 53 | }), 54 | }), 55 | }; 56 | 57 | assert_eq!(p.work_phone_area_code(), Some(61)); 58 | } 59 | ``` 60 | -------------------------------------------------------------------------------- /src/error/panic.md: -------------------------------------------------------------------------------- 1 | # `panic` 2 | 3 | The simplest error handling mechanism we will see is `panic`. It prints an 4 | error message, starts unwinding the stack, and usually exits the program. 5 | Here, we explicitly call `panic` on our error condition: 6 | 7 | ```rust,editable,ignore,mdbook-runnable 8 | fn drink(beverage: &str) { 9 | // You shouldn't drink too many sugary beverages. 10 | if beverage == "lemonade" { panic!("AAAaaaaa!!!!"); } 11 | 12 | println!("Some refreshing {} is all I need.", beverage); 13 | } 14 | 15 | fn main() { 16 | drink("water"); 17 | drink("lemonade"); 18 | drink("still water"); 19 | } 20 | ``` 21 | 22 | The first call to `drink` works. The second panics and thus the third is never called. 23 | -------------------------------------------------------------------------------- /src/error/result/early_returns.md: -------------------------------------------------------------------------------- 1 | # Early returns 2 | 3 | In the previous example, we explicitly handled the errors using combinators. 4 | Another way to deal with this case analysis is to use a combination of 5 | `match` statements and *early returns*. 6 | 7 | That is, we can simply stop executing the function and return the error if 8 | one occurs. For some, this form of code can be easier to both read and 9 | write. Consider this version of the previous example, rewritten using early returns: 10 | 11 | ```rust,editable 12 | use std::num::ParseIntError; 13 | 14 | fn multiply(first_number_str: &str, second_number_str: &str) -> Result { 15 | let first_number = match first_number_str.parse::() { 16 | Ok(first_number) => first_number, 17 | Err(e) => return Err(e), 18 | }; 19 | 20 | let second_number = match second_number_str.parse::() { 21 | Ok(second_number) => second_number, 22 | Err(e) => return Err(e), 23 | }; 24 | 25 | Ok(first_number * second_number) 26 | } 27 | 28 | fn print(result: Result) { 29 | match result { 30 | Ok(n) => println!("n is {}", n), 31 | Err(e) => println!("Error: {}", e), 32 | } 33 | } 34 | 35 | fn main() { 36 | print(multiply("10", "2")); 37 | print(multiply("t", "2")); 38 | } 39 | ``` 40 | 41 | At this point, we've learned to explicitly handle errors using combinators 42 | and early returns. While we generally want to avoid panicking, explicitly 43 | handling all of our errors is cumbersome. 44 | 45 | In the next section, we'll introduce `?` for the cases where we simply 46 | need to `unwrap` without possibly inducing `panic`. 47 | -------------------------------------------------------------------------------- /src/error/result/result_alias.md: -------------------------------------------------------------------------------- 1 | # aliases for `Result` 2 | 3 | How about when we want to reuse a specific `Result` type many times? 4 | Recall that Rust allows us to create [aliases][typealias]. Conveniently, 5 | we can define one for the specific `Result` in question. 6 | 7 | At a module level, creating aliases can be particularly helpful. Errors 8 | found in a specific module often have the same `Err` type, so a single alias 9 | can succinctly define *all* associated `Results`. This is so useful that the 10 | `std` library even supplies one: [`io::Result`][io_result]! 11 | 12 | Here's a quick example to show off the syntax: 13 | 14 | ```rust,editable 15 | use std::num::ParseIntError; 16 | 17 | // Define a generic alias for a `Result` with the error type `ParseIntError`. 18 | type AliasedResult = Result; 19 | 20 | // Use the above alias to refer to our specific `Result` type. 21 | fn multiply(first_number_str: &str, second_number_str: &str) -> AliasedResult { 22 | first_number_str.parse::().and_then(|first_number| { 23 | second_number_str.parse::().map(|second_number| first_number * second_number) 24 | }) 25 | } 26 | 27 | // Here, the alias again allows us to save some space. 28 | fn print(result: AliasedResult) { 29 | match result { 30 | Ok(n) => println!("n is {}", n), 31 | Err(e) => println!("Error: {}", e), 32 | } 33 | } 34 | 35 | fn main() { 36 | print(multiply("10", "2")); 37 | print(multiply("t", "2")); 38 | } 39 | ``` 40 | 41 | ### See also: 42 | 43 | [`io::Result`][io_result] 44 | 45 | [typealias]: ../../types/alias.md 46 | [io_result]: https://doc.rust-lang.org/std/io/type.Result.html 47 | -------------------------------------------------------------------------------- /src/expression.md: -------------------------------------------------------------------------------- 1 | # Expressions 2 | 3 | A Rust program is (mostly) made up of a series of statements: 4 | 5 | ```rust,editable 6 | fn main() { 7 | // statement 8 | // statement 9 | // statement 10 | } 11 | ``` 12 | 13 | There are a few kinds of statements in Rust. The most common two are declaring 14 | a variable binding, and using a `;` with an expression: 15 | 16 | ```rust,editable 17 | fn main() { 18 | // variable binding 19 | let x = 5; 20 | 21 | // expression; 22 | x; 23 | x + 1; 24 | 15; 25 | } 26 | ``` 27 | 28 | Blocks are expressions too, so they can be used as values in 29 | assignments. The last expression in the block will be assigned to the 30 | place expression such as a local variable. However, if the last expression of the block ends with a 31 | semicolon, the return value will be `()`. 32 | 33 | ```rust,editable 34 | fn main() { 35 | let x = 5u32; 36 | 37 | let y = { 38 | let x_squared = x * x; 39 | let x_cube = x_squared * x; 40 | 41 | // This expression will be assigned to `y` 42 | x_cube + x_squared + x 43 | }; 44 | 45 | let z = { 46 | // The semicolon suppresses this expression and `()` is assigned to `z` 47 | 2 * x; 48 | }; 49 | 50 | println!("x is {:?}", x); 51 | println!("y is {:?}", y); 52 | println!("z is {:?}", z); 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /src/flow_control.md: -------------------------------------------------------------------------------- 1 | # Flow of Control 2 | 3 | An integral part of any programming language are ways to modify control flow: 4 | `if`/`else`, `for`, and others. Let's talk about them in Rust. 5 | -------------------------------------------------------------------------------- /src/flow_control/if_else.md: -------------------------------------------------------------------------------- 1 | # if/else 2 | 3 | Branching with `if`-`else` is similar to other languages. Unlike many of them, 4 | the boolean condition doesn't need to be surrounded by parentheses, and each 5 | condition is followed by a block. `if`-`else` conditionals are expressions, 6 | and, all branches must return the same type. 7 | 8 | ```rust,editable 9 | fn main() { 10 | let n = 5; 11 | 12 | if n < 0 { 13 | print!("{} is negative", n); 14 | } else if n > 0 { 15 | print!("{} is positive", n); 16 | } else { 17 | print!("{} is zero", n); 18 | } 19 | 20 | let big_n = 21 | if n < 10 && n > -10 { 22 | println!(", and is a small number, increase ten-fold"); 23 | 24 | // This expression returns an `i32`. 25 | 10 * n 26 | } else { 27 | println!(", and is a big number, halve the number"); 28 | 29 | // This expression must return an `i32` as well. 30 | n / 2 31 | // TODO ^ Try suppressing this expression with a semicolon. 32 | }; 33 | // ^ Don't forget to put a semicolon here! All `let` bindings need it. 34 | 35 | println!("{} -> {}", n, big_n); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /src/flow_control/let_else.md: -------------------------------------------------------------------------------- 1 | # let-else 2 | 3 | > 🛈 stable since: rust 1.65 4 | > 5 | > 🛈 you can target specific edition by compiling like this 6 | > `rustc --edition=2021 main.rs` 7 | 8 | With `let`-`else`, a refutable pattern can match and bind variables 9 | in the surrounding scope like a normal `let`, or else diverge (e.g. `break`, 10 | `return`, `panic!`) when the pattern doesn't match. 11 | 12 | ```rust 13 | use std::str::FromStr; 14 | 15 | fn get_count_item(s: &str) -> (u64, &str) { 16 | let mut it = s.split(' '); 17 | let (Some(count_str), Some(item)) = (it.next(), it.next()) else { 18 | panic!("Can't segment count item pair: '{s}'"); 19 | }; 20 | let Ok(count) = u64::from_str(count_str) else { 21 | panic!("Can't parse integer: '{count_str}'"); 22 | }; 23 | (count, item) 24 | } 25 | 26 | fn main() { 27 | assert_eq!(get_count_item("3 chairs"), (3, "chairs")); 28 | } 29 | ``` 30 | 31 | The scope of name bindings is the main thing that makes this different from 32 | `match` or `if let`-`else` expressions. You could previously approximate these 33 | patterns with an unfortunate bit of repetition and an outer `let`: 34 | 35 | ```rust 36 | # use std::str::FromStr; 37 | # 38 | # fn get_count_item(s: &str) -> (u64, &str) { 39 | # let mut it = s.split(' '); 40 | let (count_str, item) = match (it.next(), it.next()) { 41 | (Some(count_str), Some(item)) => (count_str, item), 42 | _ => panic!("Can't segment count item pair: '{s}'"), 43 | }; 44 | let count = if let Ok(count) = u64::from_str(count_str) { 45 | count 46 | } else { 47 | panic!("Can't parse integer: '{count_str}'"); 48 | }; 49 | # (count, item) 50 | # } 51 | # 52 | # assert_eq!(get_count_item("3 chairs"), (3, "chairs")); 53 | ``` 54 | 55 | ### See also: 56 | 57 | [option][option], [match][match], [if let][if_let] and the [let-else RFC][let_else_rfc]. 58 | 59 | [match]: ./match.md 60 | [if_let]: ./if_let.md 61 | [let_else_rfc]: https://rust-lang.github.io/rfcs/3137-let-else.html 62 | [option]: ../std/option.md 63 | -------------------------------------------------------------------------------- /src/flow_control/loop.md: -------------------------------------------------------------------------------- 1 | # loop 2 | 3 | Rust provides a `loop` keyword to indicate an infinite loop. 4 | 5 | The `break` statement can be used to exit a loop at anytime, whereas the 6 | `continue` statement can be used to skip the rest of the iteration and start a 7 | new one. 8 | 9 | ```rust,editable 10 | fn main() { 11 | let mut count = 0u32; 12 | 13 | println!("Let's count until infinity!"); 14 | 15 | // Infinite loop 16 | loop { 17 | count += 1; 18 | 19 | if count == 3 { 20 | println!("three"); 21 | 22 | // Skip the rest of this iteration 23 | continue; 24 | } 25 | 26 | println!("{}", count); 27 | 28 | if count == 5 { 29 | println!("OK, that's enough"); 30 | 31 | // Exit this loop 32 | break; 33 | } 34 | } 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /src/flow_control/loop/nested.md: -------------------------------------------------------------------------------- 1 | # Nesting and labels 2 | 3 | It's possible to `break` or `continue` outer loops when dealing with nested 4 | loops. In these cases, the loops must be annotated with some `'label`, and the 5 | label must be passed to the `break`/`continue` statement. 6 | 7 | ```rust,editable 8 | #![allow(unreachable_code, unused_labels)] 9 | 10 | fn main() { 11 | 'outer: loop { 12 | println!("Entered the outer loop"); 13 | 14 | 'inner: loop { 15 | println!("Entered the inner loop"); 16 | 17 | // This would break only the inner loop 18 | //break; 19 | 20 | // This breaks the outer loop 21 | break 'outer; 22 | } 23 | 24 | println!("This point will never be reached"); 25 | } 26 | 27 | println!("Exited the outer loop"); 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /src/flow_control/loop/return.md: -------------------------------------------------------------------------------- 1 | # Returning from loops 2 | 3 | One of the uses of a `loop` is to retry an operation until it succeeds. If the 4 | operation returns a value though, you might need to pass it to the rest of the 5 | code: put it after the `break`, and it will be returned by the `loop` 6 | expression. 7 | 8 | ```rust,editable 9 | fn main() { 10 | let mut counter = 0; 11 | 12 | let result = loop { 13 | counter += 1; 14 | 15 | if counter == 10 { 16 | break counter * 2; 17 | } 18 | }; 19 | 20 | assert_eq!(result, 20); 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /src/flow_control/match.md: -------------------------------------------------------------------------------- 1 | # match 2 | 3 | Rust provides pattern matching via the `match` keyword, which can be used like 4 | a C `switch`. The first matching arm is evaluated and all possible values must be 5 | covered. 6 | 7 | ```rust,editable 8 | fn main() { 9 | let number = 13; 10 | // TODO ^ Try different values for `number` 11 | 12 | println!("Tell me about {}", number); 13 | match number { 14 | // Match a single value 15 | 1 => println!("One!"), 16 | // Match several values 17 | 2 | 3 | 5 | 7 | 11 => println!("This is a prime"), 18 | // TODO ^ Try adding 13 to the list of prime values 19 | // Match an inclusive range 20 | 13..=19 => println!("A teen"), 21 | // Handle the rest of cases 22 | _ => println!("Ain't special"), 23 | // TODO ^ Try commenting out this catch-all arm 24 | } 25 | 26 | let boolean = true; 27 | // Match is an expression too 28 | let binary = match boolean { 29 | // The arms of a match must cover all the possible values 30 | false => 0, 31 | true => 1, 32 | // TODO ^ Try commenting out one of these arms 33 | }; 34 | 35 | println!("{} -> {}", boolean, binary); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /src/flow_control/match/binding.md: -------------------------------------------------------------------------------- 1 | # Binding 2 | 3 | Indirectly accessing a variable makes it impossible to branch and use that 4 | variable without re-binding. `match` provides the `@` sigil for binding values to 5 | names: 6 | 7 | ```rust,editable 8 | // A function `age` which returns a `u32`. 9 | fn age() -> u32 { 10 | 15 11 | } 12 | 13 | fn main() { 14 | println!("Tell me what type of person you are"); 15 | 16 | match age() { 17 | 0 => println!("I haven't celebrated my first birthday yet"), 18 | // Could `match` 1 ..= 12 directly but then what age 19 | // would the child be? Instead, bind to `n` for the 20 | // sequence of 1 ..= 12. Now the age can be reported. 21 | n @ 1 ..= 12 => println!("I'm a child of age {:?}", n), 22 | n @ 13 ..= 19 => println!("I'm a teen of age {:?}", n), 23 | // Nothing bound. Return the result. 24 | n => println!("I'm an old person of age {:?}", n), 25 | } 26 | } 27 | ``` 28 | 29 | You can also use binding to "destructure" `enum` variants, such as `Option`: 30 | 31 | ```rust,editable 32 | fn some_number() -> Option { 33 | Some(42) 34 | } 35 | 36 | fn main() { 37 | match some_number() { 38 | // Got `Some` variant, match if its value, bound to `n`, 39 | // is equal to 42. 40 | Some(n @ 42) => println!("The Answer: {}!", n), 41 | // Match any other number. 42 | Some(n) => println!("Not interesting... {}", n), 43 | // Match anything else (`None` variant). 44 | _ => (), 45 | } 46 | } 47 | ``` 48 | 49 | ### See also: 50 | 51 | [`functions`][functions], [`enums`][enums] and [`Option`][option] 52 | 53 | [functions]: ../../fn.md 54 | [enums]: ../../custom_types/enum.md 55 | [option]: ../../std/option.md 56 | -------------------------------------------------------------------------------- /src/flow_control/match/destructuring.md: -------------------------------------------------------------------------------- 1 | # Destructuring 2 | 3 | A `match` block can destructure items in a variety of ways. 4 | 5 | * [Destructuring Tuples][tuple] 6 | * [Destructuring Arrays and Slices][slice] 7 | * [Destructuring Enums][enum] 8 | * [Destructuring Pointers][refs] 9 | * [Destructuring Structures][struct] 10 | 11 | [enum]: destructuring/destructure_enum.md 12 | [refs]: destructuring/destructure_pointers.md 13 | [struct]: destructuring/destructure_structures.md 14 | [tuple]: destructuring/destructure_tuple.md 15 | [slice]: destructuring/destructure_slice.md 16 | -------------------------------------------------------------------------------- /src/flow_control/match/destructuring/destructure_enum.md: -------------------------------------------------------------------------------- 1 | # enums 2 | 3 | An `enum` is destructured similarly: 4 | 5 | ```rust,editable 6 | // `allow` required to silence warnings because only 7 | // one variant is used. 8 | #[allow(dead_code)] 9 | enum Color { 10 | // These 3 are specified solely by their name. 11 | Red, 12 | Blue, 13 | Green, 14 | // These likewise tie `u32` tuples to different names: color models. 15 | RGB(u32, u32, u32), 16 | HSV(u32, u32, u32), 17 | HSL(u32, u32, u32), 18 | CMY(u32, u32, u32), 19 | CMYK(u32, u32, u32, u32), 20 | } 21 | 22 | fn main() { 23 | let color = Color::RGB(122, 17, 40); 24 | // TODO ^ Try different variants for `color` 25 | 26 | println!("What color is it?"); 27 | // An `enum` can be destructured using a `match`. 28 | match color { 29 | Color::Red => println!("The color is Red!"), 30 | Color::Blue => println!("The color is Blue!"), 31 | Color::Green => println!("The color is Green!"), 32 | Color::RGB(r, g, b) => 33 | println!("Red: {}, green: {}, and blue: {}!", r, g, b), 34 | Color::HSV(h, s, v) => 35 | println!("Hue: {}, saturation: {}, value: {}!", h, s, v), 36 | Color::HSL(h, s, l) => 37 | println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l), 38 | Color::CMY(c, m, y) => 39 | println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y), 40 | Color::CMYK(c, m, y, k) => 41 | println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!", 42 | c, m, y, k), 43 | // Don't need another arm because all variants have been examined 44 | } 45 | } 46 | ``` 47 | 48 | ### See also: 49 | 50 | [`#[allow(...)]`][allow], [color models][color_models] and [`enum`][enum] 51 | 52 | [allow]: ../../../attribute/unused.md 53 | [color_models]: https://en.wikipedia.org/wiki/Color_model 54 | [enum]: ../../../custom_types/enum.md 55 | -------------------------------------------------------------------------------- /src/flow_control/match/destructuring/destructure_pointers.md: -------------------------------------------------------------------------------- 1 | # pointers/ref 2 | 3 | For pointers, a distinction needs to be made between destructuring 4 | and dereferencing as they are different concepts which are used 5 | differently from languages like C/C++. 6 | 7 | * Dereferencing uses `*` 8 | * Destructuring uses `&`, `ref`, and `ref mut` 9 | 10 | ```rust,editable 11 | fn main() { 12 | // Assign a reference of type `i32`. The `&` signifies there 13 | // is a reference being assigned. 14 | let reference = &4; 15 | 16 | match reference { 17 | // If `reference` is pattern matched against `&val`, it results 18 | // in a comparison like: 19 | // `&i32` 20 | // `&val` 21 | // ^ We see that if the matching `&`s are dropped, then the `i32` 22 | // should be assigned to `val`. 23 | &val => println!("Got a value via destructuring: {:?}", val), 24 | } 25 | 26 | // To avoid the `&`, you dereference before matching. 27 | match *reference { 28 | val => println!("Got a value via dereferencing: {:?}", val), 29 | } 30 | 31 | // What if you don't start with a reference? `reference` was a `&` 32 | // because the right side was already a reference. This is not 33 | // a reference because the right side is not one. 34 | let _not_a_reference = 3; 35 | 36 | // Rust provides `ref` for exactly this purpose. It modifies the 37 | // assignment so that a reference is created for the element; this 38 | // reference is assigned. 39 | let ref _is_a_reference = 3; 40 | 41 | // Accordingly, by defining 2 values without references, references 42 | // can be retrieved via `ref` and `ref mut`. 43 | let value = 5; 44 | let mut mut_value = 6; 45 | 46 | // Use `ref` keyword to create a reference. 47 | match value { 48 | ref r => println!("Got a reference to a value: {:?}", r), 49 | } 50 | 51 | // Use `ref mut` similarly. 52 | match mut_value { 53 | ref mut m => { 54 | // Got a reference. Gotta dereference it before we can 55 | // add anything to it. 56 | *m += 10; 57 | println!("We added 10. `mut_value`: {:?}", m); 58 | }, 59 | } 60 | } 61 | ``` 62 | 63 | ### See also: 64 | 65 | [The ref pattern](../../../scope/borrow/ref.md) 66 | -------------------------------------------------------------------------------- /src/flow_control/match/destructuring/destructure_slice.md: -------------------------------------------------------------------------------- 1 | # arrays/slices 2 | 3 | Like tuples, arrays and slices can be destructured this way: 4 | 5 | ```rust,editable 6 | fn main() { 7 | // Try changing the values in the array, or make it a slice! 8 | let array = [1, -2, 6]; 9 | 10 | match array { 11 | // Binds the second and the third elements to the respective variables 12 | [0, second, third] => 13 | println!("array[0] = 0, array[1] = {}, array[2] = {}", second, third), 14 | 15 | // Single values can be ignored with _ 16 | [1, _, third] => println!( 17 | "array[0] = 1, array[2] = {} and array[1] was ignored", 18 | third 19 | ), 20 | 21 | // You can also bind some and ignore the rest 22 | [-1, second, ..] => println!( 23 | "array[0] = -1, array[1] = {} and all the other ones were ignored", 24 | second 25 | ), 26 | // The code below would not compile 27 | // [-1, second] => ... 28 | 29 | // Or store them in another array/slice (the type depends on 30 | // that of the value that is being matched against) 31 | [3, second, tail @ ..] => println!( 32 | "array[0] = 3, array[1] = {} and the other elements were {:?}", 33 | second, tail 34 | ), 35 | 36 | // Combining these patterns, we can, for example, bind the first and 37 | // last values, and store the rest of them in a single array 38 | [first, middle @ .., last] => println!( 39 | "array[0] = {}, middle = {:?}, array[2] = {}", 40 | first, middle, last 41 | ), 42 | } 43 | } 44 | ``` 45 | 46 | ### See also: 47 | 48 | [Arrays and Slices](../../../primitives/array.md) and [Binding](../binding.md) for `@` sigil 49 | -------------------------------------------------------------------------------- /src/flow_control/match/destructuring/destructure_structures.md: -------------------------------------------------------------------------------- 1 | # structs 2 | 3 | Similarly, a `struct` can be destructured as shown: 4 | 5 | ```rust,editable 6 | fn main() { 7 | struct Foo { 8 | x: (u32, u32), 9 | y: u32, 10 | } 11 | 12 | // Try changing the values in the struct to see what happens 13 | let foo = Foo { x: (1, 2), y: 3 }; 14 | 15 | match foo { 16 | Foo { x: (1, b), y } => println!("First of x is 1, b = {}, y = {} ", b, y), 17 | 18 | // you can destructure structs and rename the variables, 19 | // the order is not important 20 | Foo { y: 2, x: i } => println!("y is 2, i = {:?}", i), 21 | 22 | // and you can also ignore some variables: 23 | Foo { y, .. } => println!("y = {}, we don't care about x", y), 24 | // this will give an error: pattern does not mention field `x` 25 | //Foo { y } => println!("y = {}", y), 26 | } 27 | 28 | let faa = Foo { x: (1, 2), y: 3 }; 29 | 30 | // You do not need a match block to destructure structs: 31 | let Foo { x : x0, y: y0 } = faa; 32 | println!("Outside: x0 = {x0:?}, y0 = {y0}"); 33 | 34 | // Destructuring works with nested structs as well: 35 | struct Bar { 36 | foo: Foo, 37 | } 38 | 39 | let bar = Bar { foo: faa }; 40 | let Bar { foo: Foo { x: nested_x, y: nested_y } } = bar; 41 | println!("Nested: nested_x = {nested_x:?}, nested_y = {nested_y:?}"); 42 | } 43 | ``` 44 | 45 | ### See also: 46 | 47 | [Structs](../../../custom_types/structs.md) 48 | -------------------------------------------------------------------------------- /src/flow_control/match/destructuring/destructure_tuple.md: -------------------------------------------------------------------------------- 1 | # tuples 2 | 3 | Tuples can be destructured in a `match` as follows: 4 | 5 | ```rust,editable 6 | fn main() { 7 | let triple = (0, -2, 3); 8 | // TODO ^ Try different values for `triple` 9 | 10 | println!("Tell me about {:?}", triple); 11 | // Match can be used to destructure a tuple 12 | match triple { 13 | // Destructure the second and third elements 14 | (0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z), 15 | (1, ..) => println!("First is `1` and the rest doesn't matter"), 16 | (.., 2) => println!("last is `2` and the rest doesn't matter"), 17 | (3, .., 4) => println!("First is `3`, last is `4`, and the rest doesn't matter"), 18 | // `..` can be used to ignore the rest of the tuple 19 | _ => println!("It doesn't matter what they are"), 20 | // `_` means don't bind the value to a variable 21 | } 22 | } 23 | ``` 24 | 25 | ### See also: 26 | 27 | [Tuples](../../../primitives/tuples.md) 28 | -------------------------------------------------------------------------------- /src/flow_control/match/guard.md: -------------------------------------------------------------------------------- 1 | # Guards 2 | 3 | A `match` *guard* can be added to filter the arm. 4 | 5 | ```rust,editable 6 | #[allow(dead_code)] 7 | enum Temperature { 8 | Celsius(i32), 9 | Fahrenheit(i32), 10 | } 11 | 12 | fn main() { 13 | let temperature = Temperature::Celsius(35); 14 | // ^ TODO try different values for `temperature` 15 | 16 | match temperature { 17 | Temperature::Celsius(t) if t > 30 => println!("{}C is above 30 Celsius", t), 18 | // The `if condition` part ^ is a guard 19 | Temperature::Celsius(t) => println!("{}C is equal to or below 30 Celsius", t), 20 | 21 | Temperature::Fahrenheit(t) if t > 86 => println!("{}F is above 86 Fahrenheit", t), 22 | Temperature::Fahrenheit(t) => println!("{}F is equal to or below 86 Fahrenheit", t), 23 | } 24 | } 25 | ``` 26 | 27 | Note that the compiler won't take guard conditions into account when checking 28 | if all patterns are covered by the match expression. 29 | 30 | ```rust,editable,ignore,mdbook-runnable 31 | fn main() { 32 | let number: u8 = 4; 33 | 34 | match number { 35 | i if i == 0 => println!("Zero"), 36 | i if i > 0 => println!("Greater than zero"), 37 | // _ => unreachable!("Should never happen."), 38 | // TODO ^ uncomment to fix compilation 39 | } 40 | } 41 | ``` 42 | 43 | ### See also: 44 | 45 | [Tuples](../../primitives/tuples.md) 46 | [Enums](../../custom_types/enum.md) 47 | -------------------------------------------------------------------------------- /src/flow_control/while.md: -------------------------------------------------------------------------------- 1 | # while 2 | 3 | The `while` keyword can be used to run a loop while a condition is true. 4 | 5 | Let's write the infamous [FizzBuzz][fizzbuzz] using a `while` loop. 6 | 7 | ```rust,editable 8 | fn main() { 9 | // A counter variable 10 | let mut n = 1; 11 | 12 | // Loop while `n` is less than 101 13 | while n < 101 { 14 | if n % 15 == 0 { 15 | println!("fizzbuzz"); 16 | } else if n % 3 == 0 { 17 | println!("fizz"); 18 | } else if n % 5 == 0 { 19 | println!("buzz"); 20 | } else { 21 | println!("{}", n); 22 | } 23 | 24 | // Increment counter 25 | n += 1; 26 | } 27 | } 28 | ``` 29 | 30 | [fizzbuzz]: https://en.wikipedia.org/wiki/Fizz_buzz 31 | -------------------------------------------------------------------------------- /src/flow_control/while_let.md: -------------------------------------------------------------------------------- 1 | # while let 2 | 3 | Similar to `if let`, `while let` can make awkward `match` sequences 4 | more tolerable. Consider the following sequence that increments `i`: 5 | 6 | ```rust 7 | // Make `optional` of type `Option` 8 | let mut optional = Some(0); 9 | 10 | // Repeatedly try this test. 11 | loop { 12 | match optional { 13 | // If `optional` destructures, evaluate the block. 14 | Some(i) => { 15 | if i > 9 { 16 | println!("Greater than 9, quit!"); 17 | optional = None; 18 | } else { 19 | println!("`i` is `{:?}`. Try again.", i); 20 | optional = Some(i + 1); 21 | } 22 | // ^ Requires 3 indentations! 23 | }, 24 | // Quit the loop when the destructure fails: 25 | _ => { break; } 26 | // ^ Why should this be required? There must be a better way! 27 | } 28 | } 29 | ``` 30 | 31 | Using `while let` makes this sequence much nicer: 32 | 33 | ```rust,editable 34 | fn main() { 35 | // Make `optional` of type `Option` 36 | let mut optional = Some(0); 37 | 38 | // This reads: "while `let` destructures `optional` into 39 | // `Some(i)`, evaluate the block (`{}`). Else `break`. 40 | while let Some(i) = optional { 41 | if i > 9 { 42 | println!("Greater than 9, quit!"); 43 | optional = None; 44 | } else { 45 | println!("`i` is `{:?}`. Try again.", i); 46 | optional = Some(i + 1); 47 | } 48 | // ^ Less rightward drift and doesn't require 49 | // explicitly handling the failing case. 50 | } 51 | // ^ `if let` had additional optional `else`/`else if` 52 | // clauses. `while let` does not have these. 53 | } 54 | ``` 55 | 56 | ### See also: 57 | 58 | [`enum`][enum], [`Option`][option], and the [RFC][while_let_rfc] 59 | 60 | [enum]: ../custom_types/enum.md 61 | [option]: ../std/option.md 62 | [while_let_rfc]: https://github.com/rust-lang/rfcs/pull/214 63 | -------------------------------------------------------------------------------- /src/fn.md: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 | Functions are declared using the `fn` keyword. Its arguments are type 4 | annotated, just like variables, and, if the function returns a value, the 5 | return type must be specified after an arrow `->`. 6 | 7 | The final expression in the function will be used as return value. 8 | Alternatively, the `return` statement can be used to return a value earlier 9 | from within the function, even from inside loops or `if` statements. 10 | 11 | Let's rewrite FizzBuzz using functions! 12 | 13 | ```rust,editable 14 | // Unlike C/C++, there's no restriction on the order of function definitions 15 | fn main() { 16 | // We can use this function here, and define it somewhere later 17 | fizzbuzz_to(100); 18 | } 19 | 20 | // Function that returns a boolean value 21 | fn is_divisible_by(lhs: u32, rhs: u32) -> bool { 22 | // Corner case, early return 23 | if rhs == 0 { 24 | return false; 25 | } 26 | 27 | // This is an expression, the `return` keyword is not necessary here 28 | lhs % rhs == 0 29 | } 30 | 31 | // Functions that "don't" return a value, actually return the unit type `()` 32 | fn fizzbuzz(n: u32) -> () { 33 | if is_divisible_by(n, 15) { 34 | println!("fizzbuzz"); 35 | } else if is_divisible_by(n, 3) { 36 | println!("fizz"); 37 | } else if is_divisible_by(n, 5) { 38 | println!("buzz"); 39 | } else { 40 | println!("{}", n); 41 | } 42 | } 43 | 44 | // When a function returns `()`, the return type can be omitted from the 45 | // signature 46 | fn fizzbuzz_to(n: u32) { 47 | for n in 1..=n { 48 | fizzbuzz(n); 49 | } 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /src/fn/closures.md: -------------------------------------------------------------------------------- 1 | # Closures 2 | 3 | Closures are functions that can capture the enclosing environment. For 4 | example, a closure that captures the `x` variable: 5 | 6 | ```Rust 7 | |val| val + x 8 | ``` 9 | 10 | The syntax and capabilities of closures make them very convenient for 11 | on the fly usage. Calling a closure is exactly like calling a function. 12 | However, both input and return types *can* be inferred and input 13 | variable names *must* be specified. 14 | 15 | Other characteristics of closures include: 16 | 17 | * using `||` instead of `()` around input variables. 18 | * optional body delimitation (`{}`) for a single line expression (mandatory otherwise). 19 | * the ability to capture the outer environment variables. 20 | 21 | ```rust,editable 22 | fn main() { 23 | let outer_var = 42; 24 | 25 | // A regular function can't refer to variables in the enclosing environment 26 | //fn function(i: i32) -> i32 { i + outer_var } 27 | // TODO: uncomment the line above and see the compiler error. The compiler 28 | // suggests that we define a closure instead. 29 | 30 | // Closures are anonymous, here we are binding them to references. 31 | // Annotation is identical to function annotation but is optional 32 | // as are the `{}` wrapping the body. These nameless functions 33 | // are assigned to appropriately named variables. 34 | let closure_annotated = |i: i32| -> i32 { i + outer_var }; 35 | let closure_inferred = |i | i + outer_var ; 36 | 37 | // Call the closures. 38 | println!("closure_annotated: {}", closure_annotated(1)); 39 | println!("closure_inferred: {}", closure_inferred(1)); 40 | // Once closure's type has been inferred, it cannot be inferred again with another type. 41 | //println!("cannot reuse closure_inferred with another type: {}", closure_inferred(42i64)); 42 | // TODO: uncomment the line above and see the compiler error. 43 | 44 | // A closure taking no arguments which returns an `i32`. 45 | // The return type is inferred. 46 | let one = || 1; 47 | println!("closure returning one: {}", one()); 48 | 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /src/fn/closures/anonymity.md: -------------------------------------------------------------------------------- 1 | # Type anonymity 2 | 3 | Closures succinctly capture variables from enclosing scopes. Does this have 4 | any consequences? It surely does. Observe how using a closure as a function 5 | parameter requires [generics], which is necessary because of how they are 6 | defined: 7 | 8 | ```rust 9 | // `F` must be generic. 10 | fn apply(f: F) where 11 | F: FnOnce() { 12 | f(); 13 | } 14 | ``` 15 | 16 | When a closure is defined, the compiler implicitly creates a new 17 | anonymous structure to store the captured variables inside, meanwhile 18 | implementing the functionality via one of the `traits`: `Fn`, `FnMut`, or 19 | `FnOnce` for this unknown type. This type is assigned to the variable which 20 | is stored until calling. 21 | 22 | Since this new type is of unknown type, any usage in a function will require 23 | generics. However, an unbounded type parameter `` would still be ambiguous 24 | and not be allowed. Thus, bounding by one of the `traits`: `Fn`, `FnMut`, or 25 | `FnOnce` (which it implements) is sufficient to specify its type. 26 | 27 | ```rust,editable 28 | // `F` must implement `Fn` for a closure which takes no 29 | // inputs and returns nothing - exactly what is required 30 | // for `print`. 31 | fn apply(f: F) where 32 | F: Fn() { 33 | f(); 34 | } 35 | 36 | fn main() { 37 | let x = 7; 38 | 39 | // Capture `x` into an anonymous type and implement 40 | // `Fn` for it. Store it in `print`. 41 | let print = || println!("{}", x); 42 | 43 | apply(print); 44 | } 45 | ``` 46 | 47 | ### See also: 48 | 49 | [A thorough analysis][thorough_analysis], [`Fn`][fn], [`FnMut`][fn_mut], 50 | and [`FnOnce`][fn_once] 51 | 52 | [generics]: ../../generics.md 53 | [fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html 54 | [fn_mut]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 55 | [fn_once]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 56 | [thorough_analysis]: https://huonw.github.io/blog/2015/05/finding-closure-in-rust/ 57 | -------------------------------------------------------------------------------- /src/fn/closures/closure_examples.md: -------------------------------------------------------------------------------- 1 | # Examples in `std` 2 | 3 | This section contains a few examples of using closures from the `std` library. 4 | -------------------------------------------------------------------------------- /src/fn/closures/closure_examples/iter_any.md: -------------------------------------------------------------------------------- 1 | # Iterator::any 2 | 3 | `Iterator::any` is a function which when passed an iterator, will return 4 | `true` if any element satisfies the predicate. Otherwise `false`. Its 5 | signature: 6 | 7 | ```rust,ignore 8 | pub trait Iterator { 9 | // The type being iterated over. 10 | type Item; 11 | 12 | // `any` takes `&mut self` meaning the caller may be borrowed 13 | // and modified, but not consumed. 14 | fn any(&mut self, f: F) -> bool where 15 | // `FnMut` meaning any captured variable may at most be 16 | // modified, not consumed. `Self::Item` states it takes 17 | // arguments to the closure by value. 18 | F: FnMut(Self::Item) -> bool; 19 | } 20 | ``` 21 | 22 | ```rust,editable 23 | fn main() { 24 | let vec1 = vec![1, 2, 3]; 25 | let vec2 = vec![4, 5, 6]; 26 | 27 | // `iter()` for vecs yields `&i32`. Destructure to `i32`. 28 | println!("2 in vec1: {}", vec1.iter() .any(|&x| x == 2)); 29 | // `into_iter()` for vecs yields `i32`. No destructuring required. 30 | println!("2 in vec2: {}", vec2.into_iter().any(|x| x == 2)); 31 | 32 | // `iter()` only borrows `vec1` and its elements, so they can be used again 33 | println!("vec1 len: {}", vec1.len()); 34 | println!("First element of vec1 is: {}", vec1[0]); 35 | // `into_iter()` does move `vec2` and its elements, so they cannot be used again 36 | // println!("First element of vec2 is: {}", vec2[0]); 37 | // println!("vec2 len: {}", vec2.len()); 38 | // TODO: uncomment two lines above and see compiler errors. 39 | 40 | let array1 = [1, 2, 3]; 41 | let array2 = [4, 5, 6]; 42 | 43 | // `iter()` for arrays yields `&i32`. 44 | println!("2 in array1: {}", array1.iter() .any(|&x| x == 2)); 45 | // `into_iter()` for arrays yields `i32`. 46 | println!("2 in array2: {}", array2.into_iter().any(|x| x == 2)); 47 | } 48 | ``` 49 | 50 | ### See also: 51 | 52 | [`std::iter::Iterator::any`][any] 53 | 54 | [any]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.any 55 | -------------------------------------------------------------------------------- /src/fn/closures/input_functions.md: -------------------------------------------------------------------------------- 1 | # Input functions 2 | 3 | Since closures may be used as arguments, you might wonder if the same can be said 4 | about functions. And indeed they can! If you declare a function that takes a 5 | closure as parameter, then any function that satisfies the trait bound of that 6 | closure can be passed as a parameter. 7 | 8 | ```rust,editable 9 | // Define a function which takes a generic `F` argument 10 | // bounded by `Fn`, and calls it 11 | fn call_me(f: F) { 12 | f(); 13 | } 14 | 15 | // Define a wrapper function satisfying the `Fn` bound 16 | fn function() { 17 | println!("I'm a function!"); 18 | } 19 | 20 | fn main() { 21 | // Define a closure satisfying the `Fn` bound 22 | let closure = || println!("I'm a closure!"); 23 | 24 | call_me(closure); 25 | call_me(function); 26 | } 27 | ``` 28 | 29 | As an additional note, the `Fn`, `FnMut`, and `FnOnce` `traits` dictate how 30 | a closure captures variables from the enclosing scope. 31 | 32 | ### See also: 33 | 34 | [`Fn`][fn], [`FnMut`][fn_mut], and [`FnOnce`][fn_once] 35 | 36 | [fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html 37 | [fn_mut]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 38 | [fn_once]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html 39 | -------------------------------------------------------------------------------- /src/fn/closures/output_parameters.md: -------------------------------------------------------------------------------- 1 | # As output parameters 2 | 3 | Closures as input parameters are possible, so returning closures as 4 | output parameters should also be possible. However, anonymous 5 | closure types are, by definition, unknown, so we have to use 6 | `impl Trait` to return them. 7 | 8 | The valid traits for returning a closure are: 9 | 10 | * `Fn` 11 | * `FnMut` 12 | * `FnOnce` 13 | 14 | Beyond this, the `move` keyword must be used, which signals that all captures 15 | occur by value. This is required because any captures by reference would be 16 | dropped as soon as the function exited, leaving invalid references in the 17 | closure. 18 | 19 | ```rust,editable 20 | fn create_fn() -> impl Fn() { 21 | let text = "Fn".to_owned(); 22 | 23 | move || println!("This is a: {}", text) 24 | } 25 | 26 | fn create_fnmut() -> impl FnMut() { 27 | let text = "FnMut".to_owned(); 28 | 29 | move || println!("This is a: {}", text) 30 | } 31 | 32 | fn create_fnonce() -> impl FnOnce() { 33 | let text = "FnOnce".to_owned(); 34 | 35 | move || println!("This is a: {}", text) 36 | } 37 | 38 | fn main() { 39 | let fn_plain = create_fn(); 40 | let mut fn_mut = create_fnmut(); 41 | let fn_once = create_fnonce(); 42 | 43 | fn_plain(); 44 | fn_mut(); 45 | fn_once(); 46 | } 47 | ``` 48 | 49 | ### See also: 50 | 51 | [`Fn`][fn], [`FnMut`][fnmut], [Generics][generics] and [impl Trait][impltrait]. 52 | 53 | [fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html 54 | [fnmut]: https://doc.rust-lang.org/std/ops/trait.FnMut.html 55 | [generics]: ../../generics.md 56 | [impltrait]: ../../trait/impl_trait.md 57 | -------------------------------------------------------------------------------- /src/fn/diverging.md: -------------------------------------------------------------------------------- 1 | # Diverging functions 2 | 3 | Diverging functions never return. They are marked using `!`, which is an empty type. 4 | 5 | ```rust 6 | fn foo() -> ! { 7 | panic!("This call never returns."); 8 | } 9 | ``` 10 | 11 | As opposed to all the other types, this one cannot be instantiated, because the 12 | set of all possible values this type can have is empty. Note that, it is 13 | different from the `()` type, which has exactly one possible value. 14 | 15 | For example, this function returns as usual, although there is no information 16 | in the return value. 17 | 18 | ```rust 19 | fn some_fn() { 20 | () 21 | } 22 | 23 | fn main() { 24 | let _a: () = some_fn(); 25 | println!("This function returns and you can see this line."); 26 | } 27 | ``` 28 | 29 | As opposed to this function, which will never return the control back to the caller. 30 | 31 | ```rust,ignore 32 | #![feature(never_type)] 33 | 34 | fn main() { 35 | let x: ! = panic!("This call never returns."); 36 | println!("You will never see this line!"); 37 | } 38 | ``` 39 | 40 | Although this might seem like an abstract concept, it is actually very useful and 41 | often handy. The main advantage of this type is that it can be cast to any other 42 | type, making it versatile in situations where an exact type is required, such as 43 | in match branches. This flexibility allows us to write code like this: 44 | 45 | ```rust 46 | fn main() { 47 | fn sum_odd_numbers(up_to: u32) -> u32 { 48 | let mut acc = 0; 49 | for i in 0..up_to { 50 | // Notice that the return type of this match expression must be u32 51 | // because of the type of the "addition" variable. 52 | let addition: u32 = match i%2 == 1 { 53 | // The "i" variable is of type u32, which is perfectly fine. 54 | true => i, 55 | // On the other hand, the "continue" expression does not return 56 | // u32, but it is still fine, because it never returns and therefore 57 | // does not violate the type requirements of the match expression. 58 | false => continue, 59 | }; 60 | acc += addition; 61 | } 62 | acc 63 | } 64 | println!("Sum of odd numbers up to 9 (excluding): {}", sum_odd_numbers(9)); 65 | } 66 | ``` 67 | 68 | It is also the return type of functions that loop forever (e.g. `loop {}`) like 69 | network servers or functions that terminate the process (e.g. `exit()`). 70 | -------------------------------------------------------------------------------- /src/fn/hof.md: -------------------------------------------------------------------------------- 1 | # Higher Order Functions 2 | 3 | Rust provides Higher Order Functions (HOF). These are functions that 4 | take one or more functions and/or produce a more useful function. HOFs 5 | and lazy iterators give Rust its functional flavor. 6 | 7 | ```rust,editable 8 | fn is_odd(n: u32) -> bool { 9 | n % 2 == 1 10 | } 11 | 12 | fn main() { 13 | println!("Find the sum of all the numbers with odd squares under 1000"); 14 | let upper = 1000; 15 | 16 | // Imperative approach 17 | // Declare accumulator variable 18 | let mut acc = 0; 19 | // Iterate: 0, 1, 2, ... to infinity 20 | for n in 0.. { 21 | // Square the number 22 | let n_squared = n * n; 23 | 24 | if n_squared >= upper { 25 | // Break loop if exceeded the upper limit 26 | break; 27 | } else if is_odd(n_squared) { 28 | // Accumulate value, if it's odd 29 | acc += n_squared; 30 | } 31 | } 32 | println!("imperative style: {}", acc); 33 | 34 | // Functional approach 35 | let sum_of_squared_odd_numbers: u32 = 36 | (0..).map(|n| n * n) // All natural numbers squared 37 | .take_while(|&n_squared| n_squared < upper) // Below upper limit 38 | .filter(|&n_squared| is_odd(n_squared)) // That are odd 39 | .sum(); // Sum them 40 | println!("functional style: {}", sum_of_squared_odd_numbers); 41 | } 42 | ``` 43 | 44 | [Option][option] 45 | and 46 | [Iterator][iter] 47 | implement their fair share of HOFs. 48 | 49 | [option]: https://doc.rust-lang.org/core/option/enum.Option.html 50 | [iter]: https://doc.rust-lang.org/core/iter/trait.Iterator.html 51 | -------------------------------------------------------------------------------- /src/generics/assoc_items.md: -------------------------------------------------------------------------------- 1 | # Associated items 2 | 3 | "Associated Items" refers to a set of rules pertaining to [`item`][items]s 4 | of various types. It is an extension to `trait` generics, and allows 5 | `trait`s to internally define new items. 6 | 7 | One such item is called an *associated type*, providing simpler usage 8 | patterns when the `trait` is generic over its container type. 9 | 10 | ### See also: 11 | 12 | [RFC][RFC] 13 | 14 | [items]: https://doc.rust-lang.org/reference/items.html 15 | [RFC]: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md 16 | -------------------------------------------------------------------------------- /src/generics/assoc_items/the_problem.md: -------------------------------------------------------------------------------- 1 | # The Problem 2 | 3 | A `trait` that is generic over its container type has type specification 4 | requirements - users of the `trait` *must* specify all of its generic types. 5 | 6 | In the example below, the `Contains` `trait` allows the use of the generic 7 | types `A` and `B`. The trait is then implemented for the `Container` type, 8 | specifying `i32` for `A` and `B` so that it can be used with `fn difference()`. 9 | 10 | Because `Contains` is generic, we are forced to explicitly state *all* of the 11 | generic types for `fn difference()`. In practice, we want a way to express that 12 | `A` and `B` are determined by the *input* `C`. As you will see in the next 13 | section, associated types provide exactly that capability. 14 | 15 | ```rust,editable 16 | struct Container(i32, i32); 17 | 18 | // A trait which checks if 2 items are stored inside of container. 19 | // Also retrieves first or last value. 20 | trait Contains { 21 | fn contains(&self, _: &A, _: &B) -> bool; // Explicitly requires `A` and `B`. 22 | fn first(&self) -> i32; // Doesn't explicitly require `A` or `B`. 23 | fn last(&self) -> i32; // Doesn't explicitly require `A` or `B`. 24 | } 25 | 26 | impl Contains for Container { 27 | // True if the numbers stored are equal. 28 | fn contains(&self, number_1: &i32, number_2: &i32) -> bool { 29 | (&self.0 == number_1) && (&self.1 == number_2) 30 | } 31 | 32 | // Grab the first number. 33 | fn first(&self) -> i32 { self.0 } 34 | 35 | // Grab the last number. 36 | fn last(&self) -> i32 { self.1 } 37 | } 38 | 39 | // `C` contains `A` and `B`. In light of that, having to express `A` and 40 | // `B` again is a nuisance. 41 | fn difference(container: &C) -> i32 where 42 | C: Contains { 43 | container.last() - container.first() 44 | } 45 | 46 | fn main() { 47 | let number_1 = 3; 48 | let number_2 = 10; 49 | 50 | let container = Container(number_1, number_2); 51 | 52 | println!("Does container contain {} and {}: {}", 53 | &number_1, &number_2, 54 | container.contains(&number_1, &number_2)); 55 | println!("First number: {}", container.first()); 56 | println!("Last number: {}", container.last()); 57 | 58 | println!("The difference is: {}", difference(&container)); 59 | } 60 | ``` 61 | 62 | ### See also: 63 | 64 | [`struct`s][structs], and [`trait`s][traits] 65 | 66 | [structs]: ../../custom_types/structs.md 67 | [traits]: ../../trait.md 68 | -------------------------------------------------------------------------------- /src/generics/bounds/testcase_empty.md: -------------------------------------------------------------------------------- 1 | # Testcase: empty bounds 2 | 3 | A consequence of how bounds work is that even if a `trait` doesn't 4 | include any functionality, you can still use it as a bound. `Eq` and 5 | `Copy` are examples of such `trait`s from the `std` library. 6 | 7 | ```rust,editable 8 | struct Cardinal; 9 | struct BlueJay; 10 | struct Turkey; 11 | 12 | trait Red {} 13 | trait Blue {} 14 | 15 | impl Red for Cardinal {} 16 | impl Blue for BlueJay {} 17 | 18 | // These functions are only valid for types which implement these 19 | // traits. The fact that the traits are empty is irrelevant. 20 | fn red(_: &T) -> &'static str { "red" } 21 | fn blue(_: &T) -> &'static str { "blue" } 22 | 23 | fn main() { 24 | let cardinal = Cardinal; 25 | let blue_jay = BlueJay; 26 | let _turkey = Turkey; 27 | 28 | // `red()` won't work on a blue jay nor vice versa 29 | // because of the bounds. 30 | println!("A cardinal is {}", red(&cardinal)); 31 | println!("A blue jay is {}", blue(&blue_jay)); 32 | //println!("A turkey is {}", red(&_turkey)); 33 | // ^ TODO: Try uncommenting this line. 34 | } 35 | ``` 36 | 37 | ### See also: 38 | 39 | [`std::cmp::Eq`][eq], [`std::marker::Copy`][copy], and [`trait`s][traits] 40 | 41 | [eq]: https://doc.rust-lang.org/std/cmp/trait.Eq.html 42 | [copy]: https://doc.rust-lang.org/std/marker/trait.Copy.html 43 | [traits]: ../../trait.md 44 | -------------------------------------------------------------------------------- /src/generics/gen_fn.md: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 | The same set of rules can be applied to functions: a type `T` becomes 4 | generic when preceded by ``. 5 | 6 | Using generic functions sometimes requires explicitly specifying type 7 | parameters. This may be the case if the function is called where the return type 8 | is generic, or if the compiler doesn't have enough information to infer 9 | the necessary type parameters. 10 | 11 | A function call with explicitly specified type parameters looks like: 12 | `fun::()`. 13 | 14 | ```rust,editable 15 | struct A; // Concrete type `A`. 16 | struct S(A); // Concrete type `S`. 17 | struct SGen(T); // Generic type `SGen`. 18 | 19 | // The following functions all take ownership of the variable passed into 20 | // them and immediately go out of scope, freeing the variable. 21 | 22 | // Define a function `reg_fn` that takes an argument `_s` of type `S`. 23 | // This has no `` so this is not a generic function. 24 | fn reg_fn(_s: S) {} 25 | 26 | // Define a function `gen_spec_t` that takes an argument `_s` of type `SGen`. 27 | // It has been explicitly given the type parameter `A`, but because `A` has not 28 | // been specified as a generic type parameter for `gen_spec_t`, it is not generic. 29 | fn gen_spec_t(_s: SGen) {} 30 | 31 | // Define a function `gen_spec_i32` that takes an argument `_s` of type `SGen`. 32 | // It has been explicitly given the type parameter `i32`, which is a specific type. 33 | // Because `i32` is not a generic type, this function is also not generic. 34 | fn gen_spec_i32(_s: SGen) {} 35 | 36 | // Define a function `generic` that takes an argument `_s` of type `SGen`. 37 | // Because `SGen` is preceded by ``, this function is generic over `T`. 38 | fn generic(_s: SGen) {} 39 | 40 | fn main() { 41 | // Using the non-generic functions 42 | reg_fn(S(A)); // Concrete type. 43 | gen_spec_t(SGen(A)); // Implicitly specified type parameter `A`. 44 | gen_spec_i32(SGen(6)); // Implicitly specified type parameter `i32`. 45 | 46 | // Explicitly specified type parameter `char` to `generic()`. 47 | generic::(SGen('a')); 48 | 49 | // Implicitly specified type parameter `char` to `generic()`. 50 | generic(SGen('c')); 51 | } 52 | ``` 53 | 54 | ### See also: 55 | 56 | [functions][fn] and [`struct`s][structs] 57 | 58 | [fn]: ../fn.md 59 | [structs]: ../custom_types/structs.md 60 | -------------------------------------------------------------------------------- /src/generics/gen_trait.md: -------------------------------------------------------------------------------- 1 | # Traits 2 | 3 | Of course `trait`s can also be generic. Here we define one which reimplements 4 | the `Drop` `trait` as a generic method to `drop` itself and an input. 5 | 6 | ```rust,editable 7 | // Non-copyable types. 8 | struct Empty; 9 | struct Null; 10 | 11 | // A trait generic over `T`. 12 | trait DoubleDrop { 13 | // Define a method on the caller type which takes an 14 | // additional single parameter `T` and does nothing with it. 15 | fn double_drop(self, _: T); 16 | } 17 | 18 | // Implement `DoubleDrop` for any generic parameter `T` and 19 | // caller `U`. 20 | impl DoubleDrop for U { 21 | // This method takes ownership of both passed arguments, 22 | // deallocating both. 23 | fn double_drop(self, _: T) {} 24 | } 25 | 26 | fn main() { 27 | let empty = Empty; 28 | let null = Null; 29 | 30 | // Deallocate `empty` and `null`. 31 | empty.double_drop(null); 32 | 33 | //empty; 34 | //null; 35 | // ^ TODO: Try uncommenting these lines. 36 | } 37 | ``` 38 | 39 | ### See also: 40 | 41 | [`Drop`][Drop], [`struct`][structs], and [`trait`][traits] 42 | 43 | [Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html 44 | [structs]: ../custom_types/structs.md 45 | [traits]: ../trait.md 46 | -------------------------------------------------------------------------------- /src/generics/impl.md: -------------------------------------------------------------------------------- 1 | # Implementation 2 | 3 | Similar to functions, implementations require care to remain generic. 4 | 5 | ```rust 6 | struct S; // Concrete type `S` 7 | struct GenericVal(T); // Generic type `GenericVal` 8 | 9 | // impl of GenericVal where we explicitly specify type parameters: 10 | impl GenericVal {} // Specify `f32` 11 | impl GenericVal {} // Specify `S` as defined above 12 | 13 | // `` Must precede the type to remain generic 14 | impl GenericVal {} 15 | ``` 16 | 17 | ```rust,editable 18 | struct Val { 19 | val: f64, 20 | } 21 | 22 | struct GenVal { 23 | gen_val: T, 24 | } 25 | 26 | // impl of Val 27 | impl Val { 28 | fn value(&self) -> &f64 { 29 | &self.val 30 | } 31 | } 32 | 33 | // impl of GenVal for a generic type `T` 34 | impl GenVal { 35 | fn value(&self) -> &T { 36 | &self.gen_val 37 | } 38 | } 39 | 40 | fn main() { 41 | let x = Val { val: 3.0 }; 42 | let y = GenVal { gen_val: 3i32 }; 43 | 44 | println!("{}, {}", x.value(), y.value()); 45 | } 46 | ``` 47 | 48 | ### See also: 49 | 50 | [functions returning references][fn], [`impl`][methods], and [`struct`][structs] 51 | 52 | [fn]: ../scope/lifetime/fn.md 53 | [methods]: ../fn/methods.md 54 | [specialization_plans]: https://blog.rust-lang.org/2015/05/11/traits.html#the-future 55 | [structs]: ../custom_types/structs.md 56 | -------------------------------------------------------------------------------- /src/generics/multi_bounds.md: -------------------------------------------------------------------------------- 1 | # Multiple bounds 2 | 3 | Multiple bounds for a single type can be applied with a `+`. Like normal, different types are 4 | separated with `,`. 5 | 6 | ```rust,editable 7 | use std::fmt::{Debug, Display}; 8 | 9 | fn compare_prints(t: &T) { 10 | println!("Debug: `{:?}`", t); 11 | println!("Display: `{}`", t); 12 | } 13 | 14 | fn compare_types(t: &T, u: &U) { 15 | println!("t: `{:?}`", t); 16 | println!("u: `{:?}`", u); 17 | } 18 | 19 | fn main() { 20 | let string = "words"; 21 | let array = [1, 2, 3]; 22 | let vec = vec![1, 2, 3]; 23 | 24 | compare_prints(&string); 25 | //compare_prints(&array); 26 | // TODO ^ Try uncommenting this. 27 | 28 | compare_types(&array, &vec); 29 | } 30 | ``` 31 | 32 | ### See also: 33 | 34 | [`std::fmt`][fmt] and [`trait`s][traits] 35 | 36 | [fmt]: ../hello/print.md 37 | [traits]: ../trait.md 38 | -------------------------------------------------------------------------------- /src/generics/new_types.md: -------------------------------------------------------------------------------- 1 | # New Type Idiom 2 | 3 | The `newtype` idiom gives compile time guarantees that the right type of value is supplied 4 | to a program. 5 | 6 | For example, an age verification function that checks age in years, *must* be given 7 | a value of type `Years`. 8 | 9 | ```rust, editable 10 | struct Years(i64); 11 | 12 | struct Days(i64); 13 | 14 | impl Years { 15 | pub fn to_days(&self) -> Days { 16 | Days(self.0 * 365) 17 | } 18 | } 19 | 20 | impl Days { 21 | /// truncates partial years 22 | pub fn to_years(&self) -> Years { 23 | Years(self.0 / 365) 24 | } 25 | } 26 | 27 | fn is_adult(age: &Years) -> bool { 28 | age.0 >= 18 29 | } 30 | 31 | fn main() { 32 | let age = Years(25); 33 | let age_days = age.to_days(); 34 | println!("Is an adult? {}", is_adult(&age)); 35 | println!("Is an adult? {}", is_adult(&age_days.to_years())); 36 | // println!("Is an adult? {}", is_adult(&age_days)); 37 | } 38 | ``` 39 | 40 | Uncomment the last print statement to observe that the type supplied must be `Years`. 41 | 42 | To obtain the `newtype`'s value as the base type, you may use the tuple or destructuring syntax like so: 43 | 44 | ```rust, editable 45 | struct Years(i64); 46 | 47 | fn main() { 48 | let years = Years(42); 49 | let years_as_primitive_1: i64 = years.0; // Tuple 50 | let Years(years_as_primitive_2) = years; // Destructuring 51 | } 52 | ``` 53 | 54 | ### See also: 55 | 56 | [`structs`][struct] 57 | 58 | [struct]: ../custom_types/structs.md 59 | -------------------------------------------------------------------------------- /src/generics/where.md: -------------------------------------------------------------------------------- 1 | # Where clauses 2 | 3 | A bound can also be expressed using a `where` clause immediately 4 | before the opening `{`, rather than at the type's first mention. 5 | Additionally, `where` clauses can apply bounds to arbitrary types, 6 | rather than just to type parameters. 7 | 8 | Some cases that a `where` clause is useful: 9 | 10 | * When specifying generic types and bounds separately is clearer: 11 | 12 | ```rust,ignore 13 | impl MyTrait for YourType {} 14 | 15 | // Expressing bounds with a `where` clause 16 | impl MyTrait for YourType where 17 | A: TraitB + TraitC, 18 | D: TraitE + TraitF {} 19 | ``` 20 | 21 | * When using a `where` clause is more expressive than using normal syntax. 22 | The `impl` in this example cannot be directly expressed without a `where` clause: 23 | 24 | ```rust,editable 25 | use std::fmt::Debug; 26 | 27 | trait PrintInOption { 28 | fn print_in_option(self); 29 | } 30 | 31 | // Because we would otherwise have to express this as `T: Debug` or 32 | // use another method of indirect approach, this requires a `where` clause: 33 | impl PrintInOption for T where 34 | Option: Debug { 35 | // We want `Option: Debug` as our bound because that is what's 36 | // being printed. Doing otherwise would be using the wrong bound. 37 | fn print_in_option(self) { 38 | println!("{:?}", Some(self)); 39 | } 40 | } 41 | 42 | fn main() { 43 | let vec = vec![1, 2, 3]; 44 | 45 | vec.print_in_option(); 46 | } 47 | ``` 48 | 49 | ### See also: 50 | 51 | [RFC][where], [`struct`][struct], and [`trait`][trait] 52 | 53 | [struct]: ../custom_types/structs.md 54 | [trait]: ../trait.md 55 | [where]: https://github.com/rust-lang/rfcs/blob/master/text/0135-where.md 56 | -------------------------------------------------------------------------------- /src/hello.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | 3 | This is the source code of the traditional Hello World program. 4 | 5 | ```rust,editable 6 | // This is a comment, and is ignored by the compiler. 7 | // You can test this code by clicking the "Run" button over there -> 8 | // or if you prefer to use your keyboard, you can use the "Ctrl + Enter" 9 | // shortcut. 10 | 11 | // This code is editable, feel free to hack it! 12 | // You can always return to the original code by clicking the "Reset" button -> 13 | 14 | // This is the main function. 15 | fn main() { 16 | // Statements here are executed when the compiled binary is called. 17 | 18 | // Print text to the console. 19 | println!("Hello World!"); 20 | } 21 | ``` 22 | 23 | `println!` is a [*macro*][macros] that prints text to the 24 | console. 25 | 26 | A binary can be generated using the Rust compiler: `rustc`. 27 | 28 | ```bash 29 | $ rustc hello.rs 30 | ``` 31 | 32 | `rustc` will produce a `hello` binary that can be executed. 33 | 34 | ```bash 35 | $ ./hello 36 | Hello World! 37 | ``` 38 | 39 | ### Activity 40 | 41 | Click 'Run' above to see the expected output. Next, add a new 42 | line with a second `println!` macro so that the output shows: 43 | 44 | ```text 45 | Hello World! 46 | I'm a Rustacean! 47 | ``` 48 | 49 | [macros]: macros.md 50 | -------------------------------------------------------------------------------- /src/hello/comment.md: -------------------------------------------------------------------------------- 1 | # Comments 2 | 3 | Any program requires comments, and Rust supports 4 | a few different varieties: 5 | 6 | * *Regular comments* which are ignored by the compiler: 7 | * `// Line comments which go to the end of the line.` 8 | * `/* Block comments which go to the closing delimiter. */` 9 | * *Doc comments* which are parsed into HTML library [documentation][docs]: 10 | * `/// Generate library docs for the following item.` 11 | * `//! Generate library docs for the enclosing item.` 12 | 13 | ```rust,editable 14 | fn main() { 15 | // This is an example of a line comment. 16 | // There are two slashes at the beginning of the line. 17 | // And nothing written after these will be read by the compiler. 18 | 19 | // println!("Hello, world!"); 20 | 21 | // Run it. See? Now try deleting the two slashes, and run it again. 22 | 23 | /* 24 | * This is another type of comment, a block comment. In general, 25 | * line comments are the recommended comment style. But block comments 26 | * are extremely useful for temporarily disabling chunks of code. 27 | * /* Block comments can be /* nested, */ */ so it takes only a few 28 | * keystrokes to comment out everything in this main() function. 29 | * /*/*/* Try it yourself! */*/*/ 30 | */ 31 | 32 | /* 33 | Note: The previous column of `*` was entirely for style. There's 34 | no actual need for it. 35 | */ 36 | 37 | // Here's another powerful use of block comments: you can uncomment 38 | // and comment a whole block by simply adding or removing a single 39 | // '/' character: 40 | 41 | /* <- add another '/' before the 1st one to uncomment the whole block 42 | 43 | println!("Now"); 44 | println!("everything"); 45 | println!("executes!"); 46 | // line comments inside are not affected by either state 47 | 48 | // */ 49 | 50 | // You can manipulate expressions more easily with block comments 51 | // than with line comments. Try deleting the comment delimiters 52 | // to change the result: 53 | let x = 5 + /* 90 + */ 5; 54 | println!("Is `x` 10 or 100? x = {}", x); 55 | } 56 | ``` 57 | 58 | ### See also: 59 | 60 | [Library documentation][docs] 61 | 62 | [docs]: ../meta/doc.md 63 | -------------------------------------------------------------------------------- /src/hello/print/print_display/testcase_list.md: -------------------------------------------------------------------------------- 1 | # Testcase: List 2 | 3 | Implementing `fmt::Display` for a structure where the elements must each be 4 | handled sequentially is tricky. The problem is that each `write!` generates a 5 | `fmt::Result`. Proper handling of this requires dealing with *all* the 6 | results. Rust provides the `?` operator for exactly this purpose. 7 | 8 | Using `?` on `write!` looks like this: 9 | 10 | ```rust,ignore 11 | // Try `write!` to see if it errors. If it errors, return 12 | // the error. Otherwise continue. 13 | write!(f, "{}", value)?; 14 | ``` 15 | 16 | With `?` available, implementing `fmt::Display` for a `Vec` is 17 | straightforward: 18 | 19 | ```rust,editable 20 | use std::fmt; // Import the `fmt` module. 21 | 22 | // Define a structure named `List` containing a `Vec`. 23 | struct List(Vec); 24 | 25 | impl fmt::Display for List { 26 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 27 | // Extract the value using tuple indexing, 28 | // and create a reference to `vec`. 29 | let vec = &self.0; 30 | 31 | write!(f, "[")?; 32 | 33 | // Iterate over `v` in `vec` while enumerating the iteration 34 | // index in `index`. 35 | for (index, v) in vec.iter().enumerate() { 36 | // For every element except the first, add a comma. 37 | // Use the ? operator to return on errors. 38 | if index != 0 { write!(f, ", ")?; } 39 | write!(f, "{}", v)?; 40 | } 41 | 42 | // Close the opened bracket and return a fmt::Result value. 43 | write!(f, "]") 44 | } 45 | } 46 | 47 | fn main() { 48 | let v = List(vec![1, 2, 3]); 49 | println!("{}", v); 50 | } 51 | ``` 52 | 53 | ### Activity 54 | 55 | Try changing the program so that the index of each element in the vector is also 56 | printed. The new output should look like this: 57 | 58 | ```rust,ignore 59 | [0: 1, 1: 2, 2: 3] 60 | ``` 61 | 62 | ### See also: 63 | 64 | [`for`][for], [`ref`][ref], [`Result`][result], [`struct`][struct], 65 | [`?`][q_mark], and [`vec!`][vec] 66 | 67 | [for]: ../../../flow_control/for.md 68 | [result]: ../../../std/result.md 69 | [ref]: ../../../scope/borrow/ref.md 70 | [struct]: ../../../custom_types/structs.md 71 | [q_mark]: ../../../std/result/question_mark.md 72 | [vec]: ../../../std/vec.md 73 | -------------------------------------------------------------------------------- /src/macros.md: -------------------------------------------------------------------------------- 1 | # `macro_rules!` 2 | 3 | Rust provides a powerful macro system that allows metaprogramming. As you've 4 | seen in previous chapters, macros look like functions, except that their name 5 | ends with a bang `!`, but instead of generating a function call, macros are 6 | expanded into source code that gets compiled with the rest of the program. 7 | However, unlike macros in C and other languages, Rust macros are expanded into 8 | abstract syntax trees, rather than string preprocessing, so you don't get 9 | unexpected precedence bugs. 10 | 11 | Macros are created using the `macro_rules!` macro. 12 | 13 | ```rust,editable 14 | // This is a simple macro named `say_hello`. 15 | macro_rules! say_hello { 16 | // `()` indicates that the macro takes no argument. 17 | () => { 18 | // The macro will expand into the contents of this block. 19 | println!("Hello!") 20 | }; 21 | } 22 | 23 | fn main() { 24 | // This call will expand into `println!("Hello!")` 25 | say_hello!() 26 | } 27 | ``` 28 | 29 | So why are macros useful? 30 | 31 | 1. Don't repeat yourself. There are many cases where you may need similar 32 | functionality in multiple places but with different types. Often, writing a 33 | macro is a useful way to avoid repeating code. (More on this later) 34 | 35 | 2. Domain-specific languages. Macros allow you to define special syntax for a 36 | specific purpose. (More on this later) 37 | 38 | 3. Variadic interfaces. Sometimes you want to define an interface that takes a 39 | variable number of arguments. An example is `println!` which could take any 40 | number of arguments, depending on the format string. (More on this later) 41 | -------------------------------------------------------------------------------- /src/macros/designators.md: -------------------------------------------------------------------------------- 1 | # Designators 2 | 3 | The arguments of a macro are prefixed by a dollar sign `$` and type annotated 4 | with a *designator*: 5 | 6 | ```rust,editable 7 | macro_rules! create_function { 8 | // This macro takes an argument of designator `ident` and 9 | // creates a function named `$func_name`. 10 | // The `ident` designator is used for variable/function names. 11 | ($func_name:ident) => { 12 | fn $func_name() { 13 | // The `stringify!` macro converts an `ident` into a string. 14 | println!("You called {:?}()", 15 | stringify!($func_name)); 16 | } 17 | }; 18 | } 19 | 20 | // Create functions named `foo` and `bar` with the above macro. 21 | create_function!(foo); 22 | create_function!(bar); 23 | 24 | macro_rules! print_result { 25 | // This macro takes an expression of type `expr` and prints 26 | // it as a string along with its result. 27 | // The `expr` designator is used for expressions. 28 | ($expression:expr) => { 29 | // `stringify!` will convert the expression *as it is* into a string. 30 | println!("{:?} = {:?}", 31 | stringify!($expression), 32 | $expression); 33 | }; 34 | } 35 | 36 | fn main() { 37 | foo(); 38 | bar(); 39 | 40 | print_result!(1u32 + 1); 41 | 42 | // Recall that blocks are expressions too! 43 | print_result!({ 44 | let x = 1u32; 45 | 46 | x * x + 2 * x - 1 47 | }); 48 | } 49 | ``` 50 | 51 | These are some of the available designators: 52 | 53 | * `block` 54 | * `expr` is used for expressions 55 | * `ident` is used for variable/function names 56 | * `item` 57 | * `literal` is used for literal constants 58 | * `pat` (*pattern*) 59 | * `path` 60 | * `stmt` (*statement*) 61 | * `tt` (*token tree*) 62 | * `ty` (*type*) 63 | * `vis` (*visibility qualifier*) 64 | 65 | For a complete list, see the [Rust Reference]. 66 | 67 | [Rust Reference]: https://doc.rust-lang.org/reference/macros-by-example.html 68 | -------------------------------------------------------------------------------- /src/macros/dry.md: -------------------------------------------------------------------------------- 1 | # DRY (Don't Repeat Yourself) 2 | 3 | Macros allow writing DRY code by factoring out the common parts of functions 4 | and/or test suites. Here is an example that implements and tests the `+=`, `*=` 5 | and `-=` operators on `Vec`: 6 | 7 | ```rust,editable 8 | use std::ops::{Add, Mul, Sub}; 9 | 10 | macro_rules! assert_equal_len { 11 | // The `tt` (token tree) designator is used for 12 | // operators and tokens. 13 | ($a:expr, $b:expr, $func:ident, $op:tt) => { 14 | assert!($a.len() == $b.len(), 15 | "{:?}: dimension mismatch: {:?} {:?} {:?}", 16 | stringify!($func), 17 | ($a.len(),), 18 | stringify!($op), 19 | ($b.len(),)); 20 | }; 21 | } 22 | 23 | macro_rules! op { 24 | ($func:ident, $bound:ident, $op:tt, $method:ident) => { 25 | fn $func + Copy>(xs: &mut Vec, ys: &Vec) { 26 | assert_equal_len!(xs, ys, $func, $op); 27 | 28 | for (x, y) in xs.iter_mut().zip(ys.iter()) { 29 | *x = $bound::$method(*x, *y); 30 | // *x = x.$method(*y); 31 | } 32 | } 33 | }; 34 | } 35 | 36 | // Implement `add_assign`, `mul_assign`, and `sub_assign` functions. 37 | op!(add_assign, Add, +=, add); 38 | op!(mul_assign, Mul, *=, mul); 39 | op!(sub_assign, Sub, -=, sub); 40 | 41 | mod test { 42 | use std::iter; 43 | macro_rules! test { 44 | ($func:ident, $x:expr, $y:expr, $z:expr) => { 45 | #[test] 46 | fn $func() { 47 | for size in 0usize..10 { 48 | let mut x: Vec<_> = iter::repeat($x).take(size).collect(); 49 | let y: Vec<_> = iter::repeat($y).take(size).collect(); 50 | let z: Vec<_> = iter::repeat($z).take(size).collect(); 51 | 52 | super::$func(&mut x, &y); 53 | 54 | assert_eq!(x, z); 55 | } 56 | } 57 | }; 58 | } 59 | 60 | // Test `add_assign`, `mul_assign`, and `sub_assign`. 61 | test!(add_assign, 1u32, 2u32, 3u32); 62 | test!(mul_assign, 2u32, 3u32, 6u32); 63 | test!(sub_assign, 3u32, 2u32, 1u32); 64 | } 65 | ``` 66 | 67 | ```shell 68 | $ rustc --test dry.rs && ./dry 69 | running 3 tests 70 | test test::mul_assign ... ok 71 | test test::add_assign ... ok 72 | test test::sub_assign ... ok 73 | 74 | test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured 75 | ``` 76 | -------------------------------------------------------------------------------- /src/macros/dsl.md: -------------------------------------------------------------------------------- 1 | # Domain Specific Languages (DSLs) 2 | 3 | A DSL is a mini "language" embedded in a Rust macro. It is completely valid 4 | Rust because the macro system expands into normal Rust constructs, but it looks 5 | like a small language. This allows you to define concise or intuitive syntax for 6 | some special functionality (within bounds). 7 | 8 | Suppose that I want to define a little calculator API. I would like to supply 9 | an expression and have the output printed to console. 10 | 11 | ```rust,editable 12 | macro_rules! calculate { 13 | (eval $e:expr) => { 14 | { 15 | let val: usize = $e; // Force types to be unsigned integers 16 | println!("{} = {}", stringify!{$e}, val); 17 | } 18 | }; 19 | } 20 | 21 | fn main() { 22 | calculate! { 23 | eval 1 + 2 // hehehe `eval` is _not_ a Rust keyword! 24 | } 25 | 26 | calculate! { 27 | eval (1 + 2) * (3 / 4) 28 | } 29 | } 30 | ``` 31 | 32 | Output: 33 | 34 | ```txt 35 | 1 + 2 = 3 36 | (1 + 2) * (3 / 4) = 0 37 | ``` 38 | 39 | This was a very simple example, but much more complex interfaces have been 40 | developed, such as [`lazy_static`](https://crates.io/crates/lazy_static) or 41 | [`clap`](https://crates.io/crates/clap). 42 | 43 | Also, note the two pairs of braces in the macro. The outer ones are 44 | part of the syntax of `macro_rules!`, in addition to `()` or `[]`. 45 | -------------------------------------------------------------------------------- /src/macros/overload.md: -------------------------------------------------------------------------------- 1 | # Overload 2 | 3 | Macros can be overloaded to accept different combinations of arguments. 4 | In that regard, `macro_rules!` can work similarly to a match block: 5 | 6 | ```rust,editable 7 | // `test!` will compare `$left` and `$right` 8 | // in different ways depending on how you invoke it: 9 | macro_rules! test { 10 | // Arguments don't need to be separated by a comma. 11 | // Any template can be used! 12 | ($left:expr; and $right:expr) => { 13 | println!("{:?} and {:?} is {:?}", 14 | stringify!($left), 15 | stringify!($right), 16 | $left && $right) 17 | }; 18 | // ^ each arm must end with a semicolon. 19 | ($left:expr; or $right:expr) => { 20 | println!("{:?} or {:?} is {:?}", 21 | stringify!($left), 22 | stringify!($right), 23 | $left || $right) 24 | }; 25 | } 26 | 27 | fn main() { 28 | test!(1i32 + 1 == 2i32; and 2i32 * 2 == 4i32); 29 | test!(true; or false); 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /src/macros/repeat.md: -------------------------------------------------------------------------------- 1 | # Repeat 2 | 3 | Macros can use `+` in the argument list to indicate that an argument may 4 | repeat at least once, or `*`, to indicate that the argument may repeat zero or 5 | more times. 6 | 7 | In the following example, surrounding the matcher with `$(...),+` will 8 | match one or more expression, separated by commas. 9 | Also note that the semicolon is optional on the last case. 10 | 11 | ```rust,editable 12 | // `find_min!` will calculate the minimum of any number of arguments. 13 | macro_rules! find_min { 14 | // Base case: 15 | ($x:expr) => ($x); 16 | // `$x` followed by at least one `$y,` 17 | ($x:expr, $($y:expr),+) => ( 18 | // Call `find_min!` on the tail `$y` 19 | std::cmp::min($x, find_min!($($y),+)) 20 | ) 21 | } 22 | 23 | fn main() { 24 | println!("{}", find_min!(1)); 25 | println!("{}", find_min!(1 + 2, 2)); 26 | println!("{}", find_min!(5, 2 * 3, 4)); 27 | } 28 | ``` 29 | -------------------------------------------------------------------------------- /src/macros/syntax.md: -------------------------------------------------------------------------------- 1 | # Syntax 2 | 3 | In following subsections, we will show how to define macros in Rust. 4 | There are three basic ideas: 5 | 6 | - [Patterns and Designators][designators] 7 | - [Overloading][overloading] 8 | - [Repetition][repetition] 9 | 10 | [designators]: designators.md 11 | [overloading]: overload.md 12 | [repetition]: repeat.md 13 | -------------------------------------------------------------------------------- /src/macros/variadics.md: -------------------------------------------------------------------------------- 1 | # Variadic Interfaces 2 | 3 | A _variadic_ interface takes an arbitrary number of arguments. For example, 4 | `println!` can take an arbitrary number of arguments, as determined by the 5 | format string. 6 | 7 | We can extend our `calculate!` macro from the previous section to be variadic: 8 | 9 | ```rust,editable 10 | macro_rules! calculate { 11 | // The pattern for a single `eval` 12 | (eval $e:expr) => { 13 | { 14 | let val: usize = $e; // Force types to be integers 15 | println!("{} = {}", stringify!{$e}, val); 16 | } 17 | }; 18 | 19 | // Decompose multiple `eval`s recursively 20 | (eval $e:expr, $(eval $es:expr),+) => {{ 21 | calculate! { eval $e } 22 | calculate! { $(eval $es),+ } 23 | }}; 24 | } 25 | 26 | fn main() { 27 | calculate! { // Look ma! Variadic `calculate!`! 28 | eval 1 + 2, 29 | eval 3 + 4, 30 | eval (2 * 3) + 1 31 | } 32 | } 33 | ``` 34 | 35 | Output: 36 | 37 | ```txt 38 | 1 + 2 = 3 39 | 3 + 4 = 7 40 | (2 * 3) + 1 = 7 41 | ``` 42 | -------------------------------------------------------------------------------- /src/meta.md: -------------------------------------------------------------------------------- 1 | # Meta 2 | 3 | Some topics aren't exactly relevant to how you program runs but provide you 4 | tooling or infrastructure support which just makes things better for 5 | everyone. These topics include: 6 | 7 | - [Documentation][doc]: Generate library documentation for users via the included 8 | `rustdoc`. 9 | - [Playground][playground]: Integrate the Rust Playground in your documentation. 10 | 11 | [doc]: meta/doc.md 12 | [playground]: meta/playground.md 13 | -------------------------------------------------------------------------------- /src/meta/playground.md: -------------------------------------------------------------------------------- 1 | # Playground 2 | 3 | The [Rust Playground](https://play.rust-lang.org/) is a way to experiment with 4 | Rust code through a web interface. 5 | 6 | ## Using it with `mdbook` 7 | 8 | In [`mdbook`][mdbook], you can make code examples playable and editable. 9 | 10 | ```rust,editable 11 | fn main() { 12 | println!("Hello World!"); 13 | } 14 | ``` 15 | 16 | This allows the reader to both run your code sample, but also modify and tweak 17 | it. The key here is the adding of the word `editable` to your codefence block 18 | separated by a comma. 19 | 20 | ````markdown 21 | ```rust,editable 22 | //...place your code here 23 | ``` 24 | ```` 25 | 26 | Additionally, you can add `ignore` if you want `mdbook` to skip your code when 27 | it builds and tests. 28 | 29 | ````markdown 30 | ```rust,editable,ignore 31 | //...place your code here 32 | ``` 33 | ```` 34 | 35 | ## Using it with docs 36 | 37 | You may have noticed in some of the [official Rust docs][official-rust-docs] a 38 | button that says "Run", which opens the code sample up in a new tab in Rust 39 | Playground. This feature is enabled if you use the `#[doc]` attribute called 40 | [`html_playground_url`][html-playground-url]. 41 | 42 | ```text 43 | #![doc(html_playground_url = "https://play.rust-lang.org/")] 44 | //! ``` 45 | //! println!("Hello World"); 46 | //! ``` 47 | ``` 48 | 49 | ### See also: 50 | 51 | - [The Rust Playground][rust-playground] 52 | - [The Rust Playground On Github][rust-playground-github] 53 | - [The rustdoc Book][rustdoc-book] 54 | 55 | [rust-playground]: https://play.rust-lang.org/ 56 | [rust-playground-github]: https://github.com/integer32llc/rust-playground/ 57 | [mdbook]: https://github.com/rust-lang/mdBook 58 | [official-rust-docs]: https://doc.rust-lang.org/core/ 59 | [rustdoc-book]: https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html 60 | [html-playground-url]: https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html#html_playground_url 61 | -------------------------------------------------------------------------------- /src/mod.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | Rust provides a powerful module system that can be used to hierarchically split 4 | code in logical units (modules), and manage visibility (public/private) between 5 | them. 6 | 7 | A module is a collection of items: functions, structs, traits, `impl` blocks, 8 | and even other modules. 9 | -------------------------------------------------------------------------------- /src/mod/split.md: -------------------------------------------------------------------------------- 1 | # File hierarchy 2 | 3 | Modules can be mapped to a file/directory hierarchy. Let's break down the 4 | [visibility example][visibility] in files: 5 | 6 | ```shell 7 | $ tree . 8 | . 9 | ├── my 10 | │   ├── inaccessible.rs 11 | │   └── nested.rs 12 | ├── my.rs 13 | └── split.rs 14 | ``` 15 | 16 | In `split.rs`: 17 | 18 | ```rust,ignore 19 | // This declaration will look for a file named `my.rs` and will 20 | // insert its contents inside a module named `my` under this scope 21 | mod my; 22 | 23 | fn function() { 24 | println!("called `function()`"); 25 | } 26 | 27 | fn main() { 28 | my::function(); 29 | 30 | function(); 31 | 32 | my::indirect_access(); 33 | 34 | my::nested::function(); 35 | } 36 | 37 | ``` 38 | 39 | In `my.rs`: 40 | 41 | ```rust,ignore 42 | // Similarly `mod inaccessible` and `mod nested` will locate the `nested.rs` 43 | // and `inaccessible.rs` files and insert them here under their respective 44 | // modules 45 | mod inaccessible; 46 | pub mod nested; 47 | 48 | pub fn function() { 49 | println!("called `my::function()`"); 50 | } 51 | 52 | fn private_function() { 53 | println!("called `my::private_function()`"); 54 | } 55 | 56 | pub fn indirect_access() { 57 | print!("called `my::indirect_access()`, that\n> "); 58 | 59 | private_function(); 60 | } 61 | ``` 62 | 63 | In `my/nested.rs`: 64 | 65 | ```rust,ignore 66 | pub fn function() { 67 | println!("called `my::nested::function()`"); 68 | } 69 | 70 | #[allow(dead_code)] 71 | fn private_function() { 72 | println!("called `my::nested::private_function()`"); 73 | } 74 | ``` 75 | 76 | In `my/inaccessible.rs`: 77 | 78 | ```rust,ignore 79 | #[allow(dead_code)] 80 | pub fn public_function() { 81 | println!("called `my::inaccessible::public_function()`"); 82 | } 83 | ``` 84 | 85 | Let's check that things still work as before: 86 | 87 | ```shell 88 | $ rustc split.rs && ./split 89 | called `my::function()` 90 | called `function()` 91 | called `my::indirect_access()`, that 92 | > called `my::private_function()` 93 | called `my::nested::function()` 94 | ``` 95 | 96 | [visibility]: visibility.md 97 | -------------------------------------------------------------------------------- /src/mod/struct_visibility.md: -------------------------------------------------------------------------------- 1 | # Struct visibility 2 | 3 | Structs have an extra level of visibility with their fields. The visibility 4 | defaults to private, and can be overridden with the `pub` modifier. This 5 | visibility only matters when a struct is accessed from outside the module 6 | where it is defined, and has the goal of hiding information (encapsulation). 7 | 8 | ```rust,editable 9 | mod my { 10 | // A public struct with a public field of generic type `T` 11 | pub struct OpenBox { 12 | pub contents: T, 13 | } 14 | 15 | // A public struct with a private field of generic type `T` 16 | pub struct ClosedBox { 17 | contents: T, 18 | } 19 | 20 | impl ClosedBox { 21 | // A public constructor method 22 | pub fn new(contents: T) -> ClosedBox { 23 | ClosedBox { 24 | contents: contents, 25 | } 26 | } 27 | } 28 | } 29 | 30 | fn main() { 31 | // Public structs with public fields can be constructed as usual 32 | let open_box = my::OpenBox { contents: "public information" }; 33 | 34 | // and their fields can be normally accessed. 35 | println!("The open box contains: {}", open_box.contents); 36 | 37 | // Public structs with private fields cannot be constructed using field names. 38 | // Error! `ClosedBox` has private fields 39 | //let closed_box = my::ClosedBox { contents: "classified information" }; 40 | // TODO ^ Try uncommenting this line 41 | 42 | // However, structs with private fields can be created using 43 | // public constructors 44 | let _closed_box = my::ClosedBox::new("classified information"); 45 | 46 | // and the private fields of a public struct cannot be accessed. 47 | // Error! The `contents` field is private 48 | //println!("The closed box contains: {}", _closed_box.contents); 49 | // TODO ^ Try uncommenting this line 50 | } 51 | ``` 52 | 53 | ### See also: 54 | 55 | [generics][generics] and [methods][methods] 56 | 57 | [generics]: ../generics.md 58 | [methods]: ../fn/methods.md 59 | -------------------------------------------------------------------------------- /src/mod/super.md: -------------------------------------------------------------------------------- 1 | # `super` and `self` 2 | 3 | The `super` and `self` keywords can be used in the path to remove ambiguity 4 | when accessing items and to prevent unnecessary hardcoding of paths. 5 | 6 | ```rust,editable 7 | fn function() { 8 | println!("called `function()`"); 9 | } 10 | 11 | mod cool { 12 | pub fn function() { 13 | println!("called `cool::function()`"); 14 | } 15 | } 16 | 17 | mod my { 18 | fn function() { 19 | println!("called `my::function()`"); 20 | } 21 | 22 | mod cool { 23 | pub fn function() { 24 | println!("called `my::cool::function()`"); 25 | } 26 | } 27 | 28 | pub fn indirect_call() { 29 | // Let's access all the functions named `function` from this scope! 30 | print!("called `my::indirect_call()`, that\n> "); 31 | 32 | // The `self` keyword refers to the current module scope - in this case `my`. 33 | // Calling `self::function()` and calling `function()` directly both give 34 | // the same result, because they refer to the same function. 35 | self::function(); 36 | function(); 37 | 38 | // We can also use `self` to access another module inside `my`: 39 | self::cool::function(); 40 | 41 | // The `super` keyword refers to the parent scope (outside the `my` module). 42 | super::function(); 43 | 44 | // This will bind to the `cool::function` in the *crate* scope. 45 | // In this case the crate scope is the outermost scope. 46 | { 47 | use crate::cool::function as root_function; 48 | root_function(); 49 | } 50 | } 51 | } 52 | 53 | fn main() { 54 | my::indirect_call(); 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /src/mod/use.md: -------------------------------------------------------------------------------- 1 | # The `use` declaration 2 | 3 | The `use` declaration can be used to bind a full path to a new name, for easier 4 | access. It is often used like this: 5 | 6 | ```rust,editable,ignore 7 | use crate::deeply::nested::{ 8 | my_first_function, 9 | my_second_function, 10 | AndATraitType 11 | }; 12 | 13 | fn main() { 14 | my_first_function(); 15 | } 16 | ``` 17 | 18 | You can use the `as` keyword to bind imports to a different name: 19 | 20 | ```rust,editable 21 | // Bind the `deeply::nested::function` path to `other_function`. 22 | use deeply::nested::function as other_function; 23 | 24 | fn function() { 25 | println!("called `function()`"); 26 | } 27 | 28 | mod deeply { 29 | pub mod nested { 30 | pub fn function() { 31 | println!("called `deeply::nested::function()`"); 32 | } 33 | } 34 | } 35 | 36 | fn main() { 37 | // Easier access to `deeply::nested::function` 38 | other_function(); 39 | 40 | println!("Entering block"); 41 | { 42 | // This is equivalent to `use deeply::nested::function as function`. 43 | // This `function()` will shadow the outer one. 44 | use crate::deeply::nested::function; 45 | 46 | // `use` bindings have a local scope. In this case, the 47 | // shadowing of `function()` is only in this block. 48 | function(); 49 | 50 | println!("Leaving block"); 51 | } 52 | 53 | function(); 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /src/primitives/literals.md: -------------------------------------------------------------------------------- 1 | # Literals and operators 2 | 3 | Integers `1`, floats `1.2`, characters `'a'`, strings `"abc"`, booleans `true` 4 | and the unit type `()` can be expressed using literals. 5 | 6 | Integers can, alternatively, be expressed using hexadecimal, octal or binary 7 | notation using these prefixes respectively: `0x`, `0o` or `0b`. 8 | 9 | Underscores can be inserted in numeric literals to improve readability, e.g. 10 | `1_000` is the same as `1000`, and `0.000_001` is the same as `0.000001`. 11 | 12 | Rust also supports scientific [E-notation][enote], e.g. `1e6`, `7.6e-4`. The 13 | associated type is `f64`. 14 | 15 | We need to tell the compiler the type of the literals we use. For now, 16 | we'll use the `u32` suffix to indicate that the literal is an unsigned 32-bit 17 | integer, and the `i32` suffix to indicate that it's a signed 32-bit integer. 18 | 19 | The operators available and their precedence [in Rust][rust op-prec] are similar 20 | to other [C-like languages][op-prec]. 21 | 22 | ```rust,editable 23 | fn main() { 24 | // Integer addition 25 | println!("1 + 2 = {}", 1u32 + 2); 26 | 27 | // Integer subtraction 28 | println!("1 - 2 = {}", 1i32 - 2); 29 | // TODO ^ Try changing `1i32` to `1u32` to see why the type is important 30 | 31 | // Scientific notation 32 | println!("1e4 is {}, -2.5e-3 is {}", 1e4, -2.5e-3); 33 | 34 | // Short-circuiting boolean logic 35 | println!("true AND false is {}", true && false); 36 | println!("true OR false is {}", true || false); 37 | println!("NOT true is {}", !true); 38 | 39 | // Bitwise operations 40 | println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101); 41 | println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101); 42 | println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101); 43 | println!("1 << 5 is {}", 1u32 << 5); 44 | println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2); 45 | 46 | // Use underscores to improve readability! 47 | println!("One million is written as {}", 1_000_000u32); 48 | } 49 | ``` 50 | 51 | [enote]: https://en.wikipedia.org/wiki/Scientific_notation#E_notation 52 | [rust op-prec]: https://doc.rust-lang.org/reference/expressions.html#expression-precedence 53 | [op-prec]: https://en.wikipedia.org/wiki/Operator_precedence#Programming_languages 54 | -------------------------------------------------------------------------------- /src/scope.md: -------------------------------------------------------------------------------- 1 | # Scoping rules 2 | 3 | Scopes play an important part in ownership, borrowing, and lifetimes. 4 | That is, they indicate to the compiler when borrows are valid, when 5 | resources can be freed, and when variables are created or destroyed. 6 | -------------------------------------------------------------------------------- /src/scope/borrow.md: -------------------------------------------------------------------------------- 1 | # Borrowing 2 | 3 | Most of the time, we'd like to access data without taking ownership over 4 | it. To accomplish this, Rust uses a *borrowing* mechanism. Instead of 5 | passing objects by value (`T`), objects can be passed by reference (`&T`). 6 | 7 | The compiler statically guarantees (via its borrow checker) that references 8 | *always* point to valid objects. That is, while references to an object 9 | exist, the object cannot be destroyed. 10 | 11 | ```rust,editable,ignore,mdbook-runnable 12 | // This function takes ownership of a box and destroys it 13 | fn eat_box_i32(boxed_i32: Box) { 14 | println!("Destroying box that contains {}", boxed_i32); 15 | } 16 | 17 | // This function borrows an i32 18 | fn borrow_i32(borrowed_i32: &i32) { 19 | println!("This int is: {}", borrowed_i32); 20 | } 21 | 22 | fn main() { 23 | // Create a boxed i32 in the heap, and a i32 on the stack 24 | // Remember: numbers can have arbitrary underscores added for readability 25 | // 5_i32 is the same as 5i32 26 | let boxed_i32 = Box::new(5_i32); 27 | let stacked_i32 = 6_i32; 28 | 29 | // Borrow the contents of the box. Ownership is not taken, 30 | // so the contents can be borrowed again. 31 | borrow_i32(&boxed_i32); 32 | borrow_i32(&stacked_i32); 33 | 34 | { 35 | // Take a reference to the data contained inside the box 36 | let _ref_to_i32: &i32 = &boxed_i32; 37 | 38 | // Error! 39 | // Can't destroy `boxed_i32` while the inner value is borrowed later in scope. 40 | eat_box_i32(boxed_i32); 41 | // FIXME ^ Comment out this line 42 | 43 | // Attempt to borrow `_ref_to_i32` after inner value is destroyed 44 | borrow_i32(_ref_to_i32); 45 | // `_ref_to_i32` goes out of scope and is no longer borrowed. 46 | } 47 | 48 | // `boxed_i32` can now give up ownership to `eat_box_i32` and be destroyed 49 | eat_box_i32(boxed_i32); 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /src/scope/borrow/alias.md: -------------------------------------------------------------------------------- 1 | # Aliasing 2 | 3 | Data can be immutably borrowed any number of times, but while immutably 4 | borrowed, the original data can't be mutably borrowed. On the other hand, only 5 | *one* mutable borrow is allowed at a time. The original data can be borrowed 6 | again only *after* the mutable reference has been used for the last time. 7 | 8 | ```rust,editable 9 | struct Point { x: i32, y: i32, z: i32 } 10 | 11 | fn main() { 12 | let mut point = Point { x: 0, y: 0, z: 0 }; 13 | 14 | let borrowed_point = &point; 15 | let another_borrow = &point; 16 | 17 | // Data can be accessed via the references and the original owner 18 | println!("Point has coordinates: ({}, {}, {})", 19 | borrowed_point.x, another_borrow.y, point.z); 20 | 21 | // Error! Can't borrow `point` as mutable because it's currently 22 | // borrowed as immutable. 23 | // let mutable_borrow = &mut point; 24 | // TODO ^ Try uncommenting this line 25 | 26 | // The borrowed values are used again here 27 | println!("Point has coordinates: ({}, {}, {})", 28 | borrowed_point.x, another_borrow.y, point.z); 29 | 30 | // The immutable references are no longer used for the rest of the code so 31 | // it is possible to reborrow with a mutable reference. 32 | let mutable_borrow = &mut point; 33 | 34 | // Change data via mutable reference 35 | mutable_borrow.x = 5; 36 | mutable_borrow.y = 2; 37 | mutable_borrow.z = 1; 38 | 39 | // Error! Can't borrow `point` as immutable because it's currently 40 | // borrowed as mutable. 41 | // let y = &point.y; 42 | // TODO ^ Try uncommenting this line 43 | 44 | // Error! Can't print because `println!` takes an immutable reference. 45 | // println!("Point Z coordinate is {}", point.z); 46 | // TODO ^ Try uncommenting this line 47 | 48 | // Ok! Mutable references can be passed as immutable to `println!` 49 | println!("Point has coordinates: ({}, {}, {})", 50 | mutable_borrow.x, mutable_borrow.y, mutable_borrow.z); 51 | 52 | // The mutable reference is no longer used for the rest of the code so it 53 | // is possible to reborrow 54 | let new_borrowed_point = &point; 55 | println!("Point now has coordinates: ({}, {}, {})", 56 | new_borrowed_point.x, new_borrowed_point.y, new_borrowed_point.z); 57 | } 58 | ``` 59 | -------------------------------------------------------------------------------- /src/scope/borrow/mut.md: -------------------------------------------------------------------------------- 1 | # Mutability 2 | 3 | Mutable data can be mutably borrowed using `&mut T`. This is called 4 | a *mutable reference* and gives read/write access to the borrower. 5 | In contrast, `&T` borrows the data via an immutable reference, and 6 | the borrower can read the data but not modify it: 7 | 8 | ```rust,editable,ignore,mdbook-runnable 9 | #[allow(dead_code)] 10 | #[derive(Clone, Copy)] 11 | struct Book { 12 | // `&'static str` is a reference to a string allocated in read only memory 13 | author: &'static str, 14 | title: &'static str, 15 | year: u32, 16 | } 17 | 18 | // This function takes a reference to a book 19 | fn borrow_book(book: &Book) { 20 | println!("I immutably borrowed {} - {} edition", book.title, book.year); 21 | } 22 | 23 | // This function takes a reference to a mutable book and changes `year` to 2014 24 | fn new_edition(book: &mut Book) { 25 | book.year = 2014; 26 | println!("I mutably borrowed {} - {} edition", book.title, book.year); 27 | } 28 | 29 | fn main() { 30 | // Create an immutable Book named `immutabook` 31 | let immutabook = Book { 32 | // string literals have type `&'static str` 33 | author: "Douglas Hofstadter", 34 | title: "Gödel, Escher, Bach", 35 | year: 1979, 36 | }; 37 | 38 | // Create a mutable copy of `immutabook` and call it `mutabook` 39 | let mut mutabook = immutabook; 40 | 41 | // Immutably borrow an immutable object 42 | borrow_book(&immutabook); 43 | 44 | // Immutably borrow a mutable object 45 | borrow_book(&mutabook); 46 | 47 | // Borrow a mutable object as mutable 48 | new_edition(&mut mutabook); 49 | 50 | // Error! Cannot borrow an immutable object as mutable 51 | new_edition(&mut immutabook); 52 | // FIXME ^ Comment out this line 53 | } 54 | ``` 55 | 56 | ### See also: 57 | 58 | [`static`][static] 59 | 60 | [static]: ../lifetime/static_lifetime.md 61 | -------------------------------------------------------------------------------- /src/scope/borrow/ref.md: -------------------------------------------------------------------------------- 1 | # The ref pattern 2 | 3 | When doing pattern matching or destructuring via the `let` binding, the `ref` 4 | keyword can be used to take references to the fields of a struct/tuple. The 5 | example below shows a few instances where this can be useful: 6 | 7 | ```rust,editable 8 | #[derive(Clone, Copy)] 9 | struct Point { x: i32, y: i32 } 10 | 11 | fn main() { 12 | let c = 'Q'; 13 | 14 | // A `ref` borrow on the left side of an assignment is equivalent to 15 | // an `&` borrow on the right side. 16 | let ref ref_c1 = c; 17 | let ref_c2 = &c; 18 | 19 | println!("ref_c1 equals ref_c2: {}", *ref_c1 == *ref_c2); 20 | 21 | let point = Point { x: 0, y: 0 }; 22 | 23 | // `ref` is also valid when destructuring a struct. 24 | let _copy_of_x = { 25 | // `ref_to_x` is a reference to the `x` field of `point`. 26 | let Point { x: ref ref_to_x, y: _ } = point; 27 | 28 | // Return a copy of the `x` field of `point`. 29 | *ref_to_x 30 | }; 31 | 32 | // A mutable copy of `point` 33 | let mut mutable_point = point; 34 | 35 | { 36 | // `ref` can be paired with `mut` to take mutable references. 37 | let Point { x: _, y: ref mut mut_ref_to_y } = mutable_point; 38 | 39 | // Mutate the `y` field of `mutable_point` via a mutable reference. 40 | *mut_ref_to_y = 1; 41 | } 42 | 43 | println!("point is ({}, {})", point.x, point.y); 44 | println!("mutable_point is ({}, {})", mutable_point.x, mutable_point.y); 45 | 46 | // A mutable tuple that includes a pointer 47 | let mut mutable_tuple = (Box::new(5u32), 3u32); 48 | 49 | { 50 | // Destructure `mutable_tuple` to change the value of `last`. 51 | let (_, ref mut last) = mutable_tuple; 52 | *last = 2u32; 53 | } 54 | 55 | println!("tuple is {:?}", mutable_tuple); 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /src/scope/lifetime.md: -------------------------------------------------------------------------------- 1 | # Lifetimes 2 | 3 | A *lifetime* is a construct the compiler (or more specifically, its *borrow 4 | checker*) uses to ensure all borrows are valid. Specifically, a variable's 5 | lifetime begins when it is created and ends when it is destroyed. While 6 | lifetimes and scopes are often referred to together, they are not the same. 7 | 8 | Take, for example, the case where we borrow a variable via `&`. The 9 | borrow has a lifetime that is determined by where it is declared. As a result, 10 | the borrow is valid as long as it ends before the lender is destroyed. However, 11 | the scope of the borrow is determined by where the reference is used. 12 | 13 | In the following example and in the rest of this section, we will see how 14 | lifetimes relate to scopes, as well as how the two differ. 15 | 16 | ```rust,editable 17 | // Lifetimes are annotated below with lines denoting the creation 18 | // and destruction of each variable. 19 | // `i` has the longest lifetime because its scope entirely encloses 20 | // both `borrow1` and `borrow2`. The duration of `borrow1` compared 21 | // to `borrow2` is irrelevant since they are disjoint. 22 | fn main() { 23 | let i = 3; // Lifetime for `i` starts. ────────────────┐ 24 | // │ 25 | { // │ 26 | let borrow1 = &i; // `borrow1` lifetime starts. ──┐│ 27 | // ││ 28 | println!("borrow1: {}", borrow1); // ││ 29 | } // `borrow1` ends. ─────────────────────────────────┘│ 30 | // │ 31 | // │ 32 | { // │ 33 | let borrow2 = &i; // `borrow2` lifetime starts. ──┐│ 34 | // ││ 35 | println!("borrow2: {}", borrow2); // ││ 36 | } // `borrow2` ends. ─────────────────────────────────┘│ 37 | // │ 38 | } // Lifetime ends. ─────────────────────────────────────┘ 39 | ``` 40 | 41 | Note that no names or types are assigned to label lifetimes. 42 | This restricts how lifetimes will be able to be used as we will see. 43 | -------------------------------------------------------------------------------- /src/scope/lifetime/elision.md: -------------------------------------------------------------------------------- 1 | # Elision 2 | 3 | Some lifetime patterns are overwhelmingly common and so the borrow checker 4 | will allow you to omit them to save typing and to improve readability. 5 | This is known as elision. Elision exists in Rust solely because these patterns 6 | are common. 7 | 8 | The following code shows a few examples of elision. For a more comprehensive 9 | description of elision, see [lifetime elision][elision] in the book. 10 | 11 | ```rust,editable 12 | // `elided_input` and `annotated_input` essentially have identical signatures 13 | // because the lifetime of `elided_input` is inferred by the compiler: 14 | fn elided_input(x: &i32) { 15 | println!("`elided_input`: {}", x); 16 | } 17 | 18 | fn annotated_input<'a>(x: &'a i32) { 19 | println!("`annotated_input`: {}", x); 20 | } 21 | 22 | // Similarly, `elided_pass` and `annotated_pass` have identical signatures 23 | // because the lifetime is added implicitly to `elided_pass`: 24 | fn elided_pass(x: &i32) -> &i32 { x } 25 | 26 | fn annotated_pass<'a>(x: &'a i32) -> &'a i32 { x } 27 | 28 | fn main() { 29 | let x = 3; 30 | 31 | elided_input(&x); 32 | annotated_input(&x); 33 | 34 | println!("`elided_pass`: {}", elided_pass(&x)); 35 | println!("`annotated_pass`: {}", annotated_pass(&x)); 36 | } 37 | ``` 38 | 39 | ### See also: 40 | 41 | [elision][elision] 42 | 43 | [elision]: https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision 44 | -------------------------------------------------------------------------------- /src/scope/lifetime/fn.md: -------------------------------------------------------------------------------- 1 | # Functions 2 | 3 | Ignoring [elision], function signatures with lifetimes have a few constraints: 4 | 5 | * any reference *must* have an annotated lifetime. 6 | * any reference being returned *must* have the same lifetime as an input or 7 | be `static`. 8 | 9 | Additionally, note that returning references without input is banned if it 10 | would result in returning references to invalid data. The following example shows 11 | off some valid forms of functions with lifetimes: 12 | 13 | ```rust,editable 14 | // One input reference with lifetime `'a` which must live 15 | // at least as long as the function. 16 | fn print_one<'a>(x: &'a i32) { 17 | println!("`print_one`: x is {}", x); 18 | } 19 | 20 | // Mutable references are possible with lifetimes as well. 21 | fn add_one<'a>(x: &'a mut i32) { 22 | *x += 1; 23 | } 24 | 25 | // Multiple elements with different lifetimes. In this case, it 26 | // would be fine for both to have the same lifetime `'a`, but 27 | // in more complex cases, different lifetimes may be required. 28 | fn print_multi<'a, 'b>(x: &'a i32, y: &'b i32) { 29 | println!("`print_multi`: x is {}, y is {}", x, y); 30 | } 31 | 32 | // Returning references that have been passed in is acceptable. 33 | // However, the correct lifetime must be returned. 34 | fn pass_x<'a, 'b>(x: &'a i32, _: &'b i32) -> &'a i32 { x } 35 | 36 | //fn invalid_output<'a>() -> &'a String { &String::from("foo") } 37 | // The above is invalid: `'a` must live longer than the function. 38 | // Here, `&String::from("foo")` would create a `String`, followed by a 39 | // reference. Then the data is dropped upon exiting the scope, leaving 40 | // a reference to invalid data to be returned. 41 | 42 | fn main() { 43 | let x = 7; 44 | let y = 9; 45 | 46 | print_one(&x); 47 | print_multi(&x, &y); 48 | 49 | let z = pass_x(&x, &y); 50 | print_one(z); 51 | 52 | let mut t = 3; 53 | add_one(&mut t); 54 | print_one(&t); 55 | } 56 | ``` 57 | 58 | ### See also: 59 | 60 | [Functions][fn] 61 | 62 | [fn]: ../../fn.md 63 | 64 | [elision]: elision.md 65 | -------------------------------------------------------------------------------- /src/scope/lifetime/lifetime_bounds.md: -------------------------------------------------------------------------------- 1 | # Bounds 2 | 3 | Just like generic types can be bounded, lifetimes (themselves generic) 4 | use bounds as well. The `:` character has a slightly different meaning here, 5 | but `+` is the same. Note how the following read: 6 | 7 | 1. `T: 'a`: *All* references in `T` must outlive lifetime `'a`. 8 | 2. `T: Trait + 'a`: Type `T` must implement trait `Trait` and *all* references 9 | in `T` must outlive `'a`. 10 | 11 | The example below shows the above syntax in action used after keyword `where`: 12 | 13 | ```rust,editable 14 | use std::fmt::Debug; // Trait to bound with. 15 | 16 | #[derive(Debug)] 17 | struct Ref<'a, T: 'a>(&'a T); 18 | // `Ref` contains a reference to a generic type `T` that has 19 | // some lifetime `'a` unknown by `Ref`. `T` is bounded such that any 20 | // *references* in `T` must outlive `'a`. Additionally, the lifetime 21 | // of `Ref` may not exceed `'a`. 22 | 23 | // A generic function which prints using the `Debug` trait. 24 | fn print(t: T) where 25 | T: Debug { 26 | println!("`print`: t is {:?}", t); 27 | } 28 | 29 | // Here a reference to `T` is taken where `T` implements 30 | // `Debug` and all *references* in `T` outlive `'a`. In 31 | // addition, `'a` must outlive the function. 32 | fn print_ref<'a, T>(t: &'a T) where 33 | T: Debug + 'a { 34 | println!("`print_ref`: t is {:?}", t); 35 | } 36 | 37 | fn main() { 38 | let x = 7; 39 | let ref_x = Ref(&x); 40 | 41 | print_ref(&ref_x); 42 | print(ref_x); 43 | } 44 | ``` 45 | 46 | ### See also: 47 | 48 | [generics][generics], [bounds in generics][bounds], and 49 | [multiple bounds in generics][multibounds] 50 | 51 | [generics]: ../../generics.md 52 | [bounds]: ../../generics/bounds.md 53 | [multibounds]: ../../generics/multi_bounds.md 54 | -------------------------------------------------------------------------------- /src/scope/lifetime/lifetime_coercion.md: -------------------------------------------------------------------------------- 1 | # Coercion 2 | 3 | A longer lifetime can be coerced into a shorter one 4 | so that it works inside a scope it normally wouldn't work in. 5 | This comes in the form of inferred coercion by the Rust compiler, 6 | and also in the form of declaring a lifetime difference: 7 | 8 | ```rust,editable 9 | // Here, Rust infers a lifetime that is as short as possible. 10 | // The two references are then coerced to that lifetime. 11 | fn multiply<'a>(first: &'a i32, second: &'a i32) -> i32 { 12 | first * second 13 | } 14 | 15 | // `<'a: 'b, 'b>` reads as lifetime `'a` is at least as long as `'b`. 16 | // Here, we take in an `&'a i32` and return a `&'b i32` as a result of coercion. 17 | fn choose_first<'a: 'b, 'b>(first: &'a i32, _: &'b i32) -> &'b i32 { 18 | first 19 | } 20 | 21 | fn main() { 22 | let first = 2; // Longer lifetime 23 | 24 | { 25 | let second = 3; // Shorter lifetime 26 | 27 | println!("The product is {}", multiply(&first, &second)); 28 | println!("{} is the first", choose_first(&first, &second)); 29 | }; 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /src/scope/lifetime/methods.md: -------------------------------------------------------------------------------- 1 | # Methods 2 | 3 | Methods are annotated similarly to functions: 4 | 5 | ```rust,editable 6 | struct Owner(i32); 7 | 8 | impl Owner { 9 | // Annotate lifetimes as in a standalone function. 10 | fn add_one<'a>(&'a mut self) { self.0 += 1; } 11 | fn print<'a>(&'a self) { 12 | println!("`print`: {}", self.0); 13 | } 14 | } 15 | 16 | fn main() { 17 | let mut owner = Owner(18); 18 | 19 | owner.add_one(); 20 | owner.print(); 21 | } 22 | ``` 23 | 24 | ### See also: 25 | 26 | [methods] 27 | 28 | [methods]: ../../fn/methods.md 29 | -------------------------------------------------------------------------------- /src/scope/lifetime/struct.md: -------------------------------------------------------------------------------- 1 | # Structs 2 | 3 | Annotation of lifetimes in structures are also similar to functions: 4 | 5 | ```rust,editable 6 | // A type `Borrowed` which houses a reference to an 7 | // `i32`. The reference to `i32` must outlive `Borrowed`. 8 | #[derive(Debug)] 9 | struct Borrowed<'a>(&'a i32); 10 | 11 | // Similarly, both references here must outlive this structure. 12 | #[derive(Debug)] 13 | struct NamedBorrowed<'a> { 14 | x: &'a i32, 15 | y: &'a i32, 16 | } 17 | 18 | // An enum which is either an `i32` or a reference to one. 19 | #[derive(Debug)] 20 | enum Either<'a> { 21 | Num(i32), 22 | Ref(&'a i32), 23 | } 24 | 25 | fn main() { 26 | let x = 18; 27 | let y = 15; 28 | 29 | let single = Borrowed(&x); 30 | let double = NamedBorrowed { x: &x, y: &y }; 31 | let reference = Either::Ref(&x); 32 | let number = Either::Num(y); 33 | 34 | println!("x is borrowed in {:?}", single); 35 | println!("x and y are borrowed in {:?}", double); 36 | println!("x is borrowed in {:?}", reference); 37 | println!("y is *not* borrowed in {:?}", number); 38 | } 39 | ``` 40 | 41 | ### See also: 42 | 43 | [`struct`s][structs] 44 | 45 | [structs]: ../../custom_types/structs.md 46 | -------------------------------------------------------------------------------- /src/scope/lifetime/trait.md: -------------------------------------------------------------------------------- 1 | # Traits 2 | 3 | Annotation of lifetimes in trait methods basically are similar to functions. 4 | Note that `impl` may have annotation of lifetimes too. 5 | 6 | ```rust,editable 7 | // A struct with annotation of lifetimes. 8 | #[derive(Debug)] 9 | struct Borrowed<'a> { 10 | x: &'a i32, 11 | } 12 | 13 | // Annotate lifetimes to impl. 14 | impl<'a> Default for Borrowed<'a> { 15 | fn default() -> Self { 16 | Self { 17 | x: &10, 18 | } 19 | } 20 | } 21 | 22 | fn main() { 23 | let b: Borrowed = Default::default(); 24 | println!("b is {:?}", b); 25 | } 26 | ``` 27 | 28 | ### See also: 29 | 30 | [`trait`s][trait] 31 | 32 | [trait]: ../../trait.md 33 | -------------------------------------------------------------------------------- /src/scope/move.md: -------------------------------------------------------------------------------- 1 | # Ownership and moves 2 | 3 | Because variables are in charge of freeing their own resources, 4 | **resources can only have one owner**. This prevents resources 5 | from being freed more than once. Note that not all variables own 6 | resources (e.g. [references]). 7 | 8 | When doing assignments (`let x = y`) or passing function arguments by value 9 | (`foo(x)`), the *ownership* of the resources is transferred. In Rust-speak, 10 | this is known as a *move*. 11 | 12 | After moving resources, the previous owner can no longer be used. This avoids 13 | creating dangling pointers. 14 | 15 | ```rust,editable 16 | // This function takes ownership of the heap allocated memory 17 | fn destroy_box(c: Box) { 18 | println!("Destroying a box that contains {}", c); 19 | 20 | // `c` is destroyed and the memory freed 21 | } 22 | 23 | fn main() { 24 | // _Stack_ allocated integer 25 | let x = 5u32; 26 | 27 | // *Copy* `x` into `y` - no resources are moved 28 | let y = x; 29 | 30 | // Both values can be independently used 31 | println!("x is {}, and y is {}", x, y); 32 | 33 | // `a` is a pointer to a _heap_ allocated integer 34 | let a = Box::new(5i32); 35 | 36 | println!("a contains: {}", a); 37 | 38 | // *Move* `a` into `b` 39 | let b = a; 40 | // The pointer address of `a` is copied (not the data) into `b`. 41 | // Both are now pointers to the same heap allocated data, but 42 | // `b` now owns it. 43 | 44 | // Error! `a` can no longer access the data, because it no longer owns the 45 | // heap memory 46 | //println!("a contains: {}", a); 47 | // TODO ^ Try uncommenting this line 48 | 49 | // This function takes ownership of the heap allocated memory from `b` 50 | destroy_box(b); 51 | 52 | // Since the heap memory has been freed at this point, this action would 53 | // result in dereferencing freed memory, but it's forbidden by the compiler 54 | // Error! Same reason as the previous Error 55 | //println!("b contains: {}", b); 56 | // TODO ^ Try uncommenting this line 57 | } 58 | ``` 59 | 60 | [references]: ../flow_control/match/destructuring/destructure_pointers.md 61 | -------------------------------------------------------------------------------- /src/scope/move/mut.md: -------------------------------------------------------------------------------- 1 | # Mutability 2 | 3 | Mutability of data can be changed when ownership is transferred. 4 | 5 | ```rust,editable 6 | fn main() { 7 | let immutable_box = Box::new(5u32); 8 | 9 | println!("immutable_box contains {}", immutable_box); 10 | 11 | // Mutability error 12 | //*immutable_box = 4; 13 | 14 | // *Move* the box, changing the ownership (and mutability) 15 | let mut mutable_box = immutable_box; 16 | 17 | println!("mutable_box contains {}", mutable_box); 18 | 19 | // Modify the contents of the box 20 | *mutable_box = 4; 21 | 22 | println!("mutable_box now contains {}", mutable_box); 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /src/scope/move/partial_move.md: -------------------------------------------------------------------------------- 1 | # Partial moves 2 | 3 | Within the [destructuring] of a single variable, both `by-move` and 4 | `by-reference` pattern bindings can be used at the same time. Doing 5 | this will result in a _partial move_ of the variable, which means 6 | that parts of the variable will be moved while other parts stay. In 7 | such a case, the parent variable cannot be used afterwards as a 8 | whole, however the parts that are only referenced (and not moved) 9 | can still be used. Note that types that implement the 10 | [`Drop` trait][droptrait] cannot be partially moved from, because 11 | its `drop` method would use it afterwards as a whole. 12 | 13 | 14 | ```rust,editable 15 | fn main() { 16 | #[derive(Debug)] 17 | struct Person { 18 | name: String, 19 | age: Box, 20 | } 21 | 22 | // Error! cannot move out of a type which implements the `Drop` trait 23 | //impl Drop for Person { 24 | // fn drop(&mut self) { 25 | // println!("Dropping the person struct {:?}", self) 26 | // } 27 | //} 28 | // TODO ^ Try uncommenting these lines 29 | 30 | let person = Person { 31 | name: String::from("Alice"), 32 | age: Box::new(20), 33 | }; 34 | 35 | // `name` is moved out of person, but `age` is referenced 36 | let Person { name, ref age } = person; 37 | 38 | println!("The person's age is {}", age); 39 | 40 | println!("The person's name is {}", name); 41 | 42 | // Error! borrow of partially moved value: `person` partial move occurs 43 | //println!("The person struct is {:?}", person); 44 | 45 | // `person` cannot be used but `person.age` can be used as it is not moved 46 | println!("The person's age from person struct is {}", person.age); 47 | } 48 | ``` 49 | 50 | (In this example, we store the `age` variable on the heap to 51 | illustrate the partial move: deleting `ref` in the above code would 52 | give an error as the ownership of `person.age` would be moved to the 53 | variable `age`. If `Person.age` were stored on the stack, `ref` would 54 | not be required as the definition of `age` would copy the data from 55 | `person.age` without moving it.) 56 | 57 | ### See also: 58 | 59 | [destructuring][destructuring] 60 | 61 | [droptrait]: ../../trait/drop.md 62 | [destructuring]: ../../flow_control/match/destructuring.md 63 | -------------------------------------------------------------------------------- /src/std.md: -------------------------------------------------------------------------------- 1 | # Std library types 2 | 3 | The `std` library provides many custom types which expands drastically on 4 | the `primitives`. Some of these include: 5 | 6 | * growable `String`s like: `"hello world"` 7 | * growable vectors: `[1, 2, 3]` 8 | * optional types: `Option` 9 | * error handling types: `Result` 10 | * heap allocated pointers: `Box` 11 | 12 | ### See also: 13 | 14 | [primitives] and [the std library][std] 15 | 16 | [primitives]: primitives.md 17 | [std]: https://doc.rust-lang.org/std/ 18 | -------------------------------------------------------------------------------- /src/std/arc.md: -------------------------------------------------------------------------------- 1 | # Arc 2 | 3 | When shared ownership between threads is needed, `Arc`(Atomically Reference 4 | Counted) can be used. This struct, via the `Clone` implementation can create 5 | a reference pointer for the location of a value in the memory heap while 6 | increasing the reference counter. As it shares ownership between threads, when 7 | the last reference pointer to a value is out of scope, the variable is dropped. 8 | 9 | ```rust,editable 10 | use std::time::Duration; 11 | use std::sync::Arc; 12 | use std::thread; 13 | 14 | fn main() { 15 | // This variable declaration is where its value is specified. 16 | let apple = Arc::new("the same apple"); 17 | 18 | for _ in 0..10 { 19 | // Here there is no value specification as it is a pointer to a 20 | // reference in the memory heap. 21 | let apple = Arc::clone(&apple); 22 | 23 | thread::spawn(move || { 24 | // As Arc was used, threads can be spawned using the value allocated 25 | // in the Arc variable pointer's location. 26 | println!("{:?}", apple); 27 | }); 28 | } 29 | 30 | // Make sure all Arc instances are printed from spawned threads. 31 | thread::sleep(Duration::from_secs(1)); 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /src/std/hash.md: -------------------------------------------------------------------------------- 1 | # HashMap 2 | 3 | Where vectors store values by an integer index, `HashMap`s store values by key. 4 | `HashMap` keys can be booleans, integers, strings, 5 | or any other type that implements the `Eq` and `Hash` traits. 6 | More on this in the next section. 7 | 8 | Like vectors, `HashMap`s are growable, but HashMaps can also shrink themselves 9 | when they have excess space. 10 | You can create a HashMap with a certain starting capacity using 11 | `HashMap::with_capacity(uint)`, or use `HashMap::new()` to get a HashMap 12 | with a default initial capacity (recommended). 13 | 14 | ```rust,editable 15 | use std::collections::HashMap; 16 | 17 | fn call(number: &str) -> &str { 18 | match number { 19 | "798-1364" => "We're sorry, the call cannot be completed as dialed. 20 | Please hang up and try again.", 21 | "645-7689" => "Hello, this is Mr. Awesome's Pizza. My name is Fred. 22 | What can I get for you today?", 23 | _ => "Hi! Who is this again?" 24 | } 25 | } 26 | 27 | fn main() { 28 | let mut contacts = HashMap::new(); 29 | 30 | contacts.insert("Daniel", "798-1364"); 31 | contacts.insert("Ashley", "645-7689"); 32 | contacts.insert("Katie", "435-8291"); 33 | contacts.insert("Robert", "956-1745"); 34 | 35 | // Takes a reference and returns Option<&V> 36 | match contacts.get(&"Daniel") { 37 | Some(&number) => println!("Calling Daniel: {}", call(number)), 38 | _ => println!("Don't have Daniel's number."), 39 | } 40 | 41 | // `HashMap::insert()` returns `None` 42 | // if the inserted value is new, `Some(value)` otherwise 43 | contacts.insert("Daniel", "164-6743"); 44 | 45 | match contacts.get(&"Ashley") { 46 | Some(&number) => println!("Calling Ashley: {}", call(number)), 47 | _ => println!("Don't have Ashley's number."), 48 | } 49 | 50 | contacts.remove(&"Ashley"); 51 | 52 | // `HashMap::iter()` returns an iterator that yields 53 | // (&'a key, &'a value) pairs in arbitrary order. 54 | for (contact, &number) in contacts.iter() { 55 | println!("Calling {}: {}", contact, call(number)); 56 | } 57 | } 58 | ``` 59 | 60 | For more information on how hashing and hash maps 61 | (sometimes called hash tables) work, have a look at 62 | [Hash Table Wikipedia][wiki-hash] 63 | 64 | [wiki-hash]: https://en.wikipedia.org/wiki/Hash_table 65 | -------------------------------------------------------------------------------- /src/std/option.md: -------------------------------------------------------------------------------- 1 | # `Option` 2 | 3 | Sometimes it's desirable to catch the failure of some parts of a program 4 | instead of calling `panic!`; this can be accomplished using the `Option` enum. 5 | 6 | The `Option` enum has two variants: 7 | 8 | * `None`, to indicate failure or lack of value, and 9 | * `Some(value)`, a tuple struct that wraps a `value` with type `T`. 10 | 11 | ```rust,editable,ignore,mdbook-runnable 12 | // An integer division that doesn't `panic!` 13 | fn checked_division(dividend: i32, divisor: i32) -> Option { 14 | if divisor == 0 { 15 | // Failure is represented as the `None` variant 16 | None 17 | } else { 18 | // Result is wrapped in a `Some` variant 19 | Some(dividend / divisor) 20 | } 21 | } 22 | 23 | // This function handles a division that may not succeed 24 | fn try_division(dividend: i32, divisor: i32) { 25 | // `Option` values can be pattern matched, just like other enums 26 | match checked_division(dividend, divisor) { 27 | None => println!("{} / {} failed!", dividend, divisor), 28 | Some(quotient) => { 29 | println!("{} / {} = {}", dividend, divisor, quotient) 30 | }, 31 | } 32 | } 33 | 34 | fn main() { 35 | try_division(4, 2); 36 | try_division(1, 0); 37 | 38 | // Binding `None` to a variable needs to be type annotated 39 | let none: Option = None; 40 | let _equivalent_none = None::; 41 | 42 | let optional_float = Some(0f32); 43 | 44 | // Unwrapping a `Some` variant will extract the value wrapped. 45 | println!("{:?} unwraps to {:?}", optional_float, optional_float.unwrap()); 46 | 47 | // Unwrapping a `None` variant will `panic!` 48 | println!("{:?} unwraps to {:?}", none, none.unwrap()); 49 | } 50 | ``` 51 | -------------------------------------------------------------------------------- /src/std/panic.md: -------------------------------------------------------------------------------- 1 | # `panic!` 2 | 3 | The `panic!` macro can be used to generate a panic and start unwinding 4 | its stack. While unwinding, the runtime will take care of freeing all the 5 | resources *owned* by the thread by calling the destructor of all its objects. 6 | 7 | Since we are dealing with programs with only one thread, `panic!` will cause the 8 | program to report the panic message and exit. 9 | 10 | ```rust,editable,ignore,mdbook-runnable 11 | // Re-implementation of integer division (/) 12 | fn division(dividend: i32, divisor: i32) -> i32 { 13 | if divisor == 0 { 14 | // Division by zero triggers a panic 15 | panic!("division by zero"); 16 | } else { 17 | dividend / divisor 18 | } 19 | } 20 | 21 | // The `main` task 22 | fn main() { 23 | // Heap allocated integer 24 | let _x = Box::new(0i32); 25 | 26 | // This operation will trigger a task failure 27 | division(3, 0); 28 | 29 | println!("This point won't be reached!"); 30 | 31 | // `_x` should get destroyed at this point 32 | } 33 | ``` 34 | 35 | Let's check that `panic!` doesn't leak memory. 36 | 37 | 38 | 39 | ```shell 40 | $ rustc panic.rs && valgrind ./panic 41 | ==4401== Memcheck, a memory error detector 42 | ==4401== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 43 | ==4401== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info 44 | ==4401== Command: ./panic 45 | ==4401== 46 | thread '
' panicked at 'division by zero', panic.rs:5 47 | ==4401== 48 | ==4401== HEAP SUMMARY: 49 | ==4401== in use at exit: 0 bytes in 0 blocks 50 | ==4401== total heap usage: 18 allocs, 18 frees, 1,648 bytes allocated 51 | ==4401== 52 | ==4401== All heap blocks were freed -- no leaks are possible 53 | ==4401== 54 | ==4401== For counts of detected and suppressed errors, rerun with: -v 55 | ==4401== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /src/std/rc.md: -------------------------------------------------------------------------------- 1 | # `Rc` 2 | 3 | When multiple ownership is needed, `Rc`(Reference Counting) can be used. `Rc` 4 | keeps track of the number of the references which means the number of owners of 5 | the value wrapped inside an `Rc`. 6 | 7 | Reference count of an `Rc` increases by 1 whenever an `Rc` is cloned, and 8 | decreases by 1 whenever one cloned `Rc` is dropped out of the scope. When an 9 | `Rc`'s reference count becomes zero (which means there are no remaining owners), 10 | both the `Rc` and the value are all dropped. 11 | 12 | Cloning an `Rc` never performs a deep copy. Cloning creates just another pointer 13 | to the wrapped value, and increments the count. 14 | 15 | ```rust,editable 16 | use std::rc::Rc; 17 | 18 | fn main() { 19 | let rc_examples = "Rc examples".to_string(); 20 | { 21 | println!("--- rc_a is created ---"); 22 | 23 | let rc_a: Rc = Rc::new(rc_examples); 24 | println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); 25 | 26 | { 27 | println!("--- rc_a is cloned to rc_b ---"); 28 | 29 | let rc_b: Rc = Rc::clone(&rc_a); 30 | println!("Reference Count of rc_b: {}", Rc::strong_count(&rc_b)); 31 | println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); 32 | 33 | // Two `Rc`s are equal if their inner values are equal 34 | println!("rc_a and rc_b are equal: {}", rc_a.eq(&rc_b)); 35 | 36 | // We can use methods of a value directly 37 | println!("Length of the value inside rc_a: {}", rc_a.len()); 38 | println!("Value of rc_b: {}", rc_b); 39 | 40 | println!("--- rc_b is dropped out of scope ---"); 41 | } 42 | 43 | println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); 44 | 45 | println!("--- rc_a is dropped out of scope ---"); 46 | } 47 | 48 | // Error! `rc_examples` already moved into `rc_a` 49 | // And when `rc_a` is dropped, `rc_examples` is dropped together 50 | // println!("rc_examples: {}", rc_examples); 51 | // TODO ^ Try uncommenting this line 52 | } 53 | ``` 54 | 55 | ### See also: 56 | 57 | [std::rc][1] and [std::sync::arc][2]. 58 | 59 | [1]: https://doc.rust-lang.org/std/rc/index.html 60 | [2]: https://doc.rust-lang.org/std/sync/struct.Arc.html 61 | -------------------------------------------------------------------------------- /src/std/result.md: -------------------------------------------------------------------------------- 1 | # `Result` 2 | 3 | We've seen that the `Option` enum can be used as a return value from functions 4 | that may fail, where `None` can be returned to indicate failure. However, 5 | sometimes it is important to express *why* an operation failed. To do this we 6 | have the `Result` enum. 7 | 8 | The `Result` enum has two variants: 9 | 10 | * `Ok(value)` which indicates that the operation succeeded, and wraps the 11 | `value` returned by the operation. (`value` has type `T`) 12 | * `Err(why)`, which indicates that the operation failed, and wraps `why`, 13 | which (hopefully) explains the cause of the failure. (`why` has type `E`) 14 | 15 | ```rust,editable,ignore,mdbook-runnable 16 | mod checked { 17 | // Mathematical "errors" we want to catch 18 | #[derive(Debug)] 19 | pub enum MathError { 20 | DivisionByZero, 21 | NonPositiveLogarithm, 22 | NegativeSquareRoot, 23 | } 24 | 25 | pub type MathResult = Result; 26 | 27 | pub fn div(x: f64, y: f64) -> MathResult { 28 | if y == 0.0 { 29 | // This operation would `fail`, instead let's return the reason of 30 | // the failure wrapped in `Err` 31 | Err(MathError::DivisionByZero) 32 | } else { 33 | // This operation is valid, return the result wrapped in `Ok` 34 | Ok(x / y) 35 | } 36 | } 37 | 38 | pub fn sqrt(x: f64) -> MathResult { 39 | if x < 0.0 { 40 | Err(MathError::NegativeSquareRoot) 41 | } else { 42 | Ok(x.sqrt()) 43 | } 44 | } 45 | 46 | pub fn ln(x: f64) -> MathResult { 47 | if x <= 0.0 { 48 | Err(MathError::NonPositiveLogarithm) 49 | } else { 50 | Ok(x.ln()) 51 | } 52 | } 53 | } 54 | 55 | // `op(x, y)` === `sqrt(ln(x / y))` 56 | fn op(x: f64, y: f64) -> f64 { 57 | // This is a three level match pyramid! 58 | match checked::div(x, y) { 59 | Err(why) => panic!("{:?}", why), 60 | Ok(ratio) => match checked::ln(ratio) { 61 | Err(why) => panic!("{:?}", why), 62 | Ok(ln) => match checked::sqrt(ln) { 63 | Err(why) => panic!("{:?}", why), 64 | Ok(sqrt) => sqrt, 65 | }, 66 | }, 67 | } 68 | } 69 | 70 | fn main() { 71 | // Will this fail? 72 | println!("{}", op(1.0, 10.0)); 73 | } 74 | ``` 75 | -------------------------------------------------------------------------------- /src/std/result/question_mark.md: -------------------------------------------------------------------------------- 1 | # `?` 2 | 3 | Chaining results using match can get pretty untidy; luckily, the `?` operator 4 | can be used to make things pretty again. `?` is used at the end of an expression 5 | returning a `Result`, and is equivalent to a match expression, where the 6 | `Err(err)` branch expands to an early `return Err(From::from(err))`, and the `Ok(ok)` 7 | branch expands to an `ok` expression. 8 | 9 | ```rust,editable,ignore,mdbook-runnable 10 | mod checked { 11 | #[derive(Debug)] 12 | enum MathError { 13 | DivisionByZero, 14 | NonPositiveLogarithm, 15 | NegativeSquareRoot, 16 | } 17 | 18 | type MathResult = Result; 19 | 20 | fn div(x: f64, y: f64) -> MathResult { 21 | if y == 0.0 { 22 | Err(MathError::DivisionByZero) 23 | } else { 24 | Ok(x / y) 25 | } 26 | } 27 | 28 | fn sqrt(x: f64) -> MathResult { 29 | if x < 0.0 { 30 | Err(MathError::NegativeSquareRoot) 31 | } else { 32 | Ok(x.sqrt()) 33 | } 34 | } 35 | 36 | fn ln(x: f64) -> MathResult { 37 | if x <= 0.0 { 38 | Err(MathError::NonPositiveLogarithm) 39 | } else { 40 | Ok(x.ln()) 41 | } 42 | } 43 | 44 | // Intermediate function 45 | fn op_(x: f64, y: f64) -> MathResult { 46 | // if `div` "fails", then `DivisionByZero` will be `return`ed 47 | let ratio = div(x, y)?; 48 | 49 | // if `ln` "fails", then `NonPositiveLogarithm` will be `return`ed 50 | let ln = ln(ratio)?; 51 | 52 | sqrt(ln) 53 | } 54 | 55 | pub fn op(x: f64, y: f64) { 56 | match op_(x, y) { 57 | Err(why) => panic!("{}", match why { 58 | MathError::NonPositiveLogarithm 59 | => "logarithm of non-positive number", 60 | MathError::DivisionByZero 61 | => "division by zero", 62 | MathError::NegativeSquareRoot 63 | => "square root of negative number", 64 | }), 65 | Ok(value) => println!("{}", value), 66 | } 67 | } 68 | } 69 | 70 | fn main() { 71 | checked::op(1.0, 10.0); 72 | } 73 | ``` 74 | 75 | Be sure to check the [documentation][docs], 76 | as there are many methods to map/compose `Result`. 77 | 78 | [docs]: https://doc.rust-lang.org/std/result/index.html 79 | -------------------------------------------------------------------------------- /src/std_misc.md: -------------------------------------------------------------------------------- 1 | # Std misc 2 | 3 | Many other types are provided by the std library to support 4 | things such as: 5 | 6 | * Threads 7 | * Channels 8 | * File I/O 9 | 10 | These expand beyond what the [primitives] provide. 11 | 12 | ### See also: 13 | 14 | [primitives] and [the std library][std] 15 | 16 | [primitives]: primitives.md 17 | [std]: https://doc.rust-lang.org/std/ 18 | -------------------------------------------------------------------------------- /src/std_misc/arg.md: -------------------------------------------------------------------------------- 1 | # Program arguments 2 | 3 | ## Standard Library 4 | 5 | The command line arguments can be accessed using `std::env::args`, which 6 | returns an iterator that yields a `String` for each argument: 7 | 8 | ```rust,editable 9 | use std::env; 10 | 11 | fn main() { 12 | let args: Vec = env::args().collect(); 13 | 14 | // The first argument is the path that was used to call the program. 15 | println!("My path is {}.", args[0]); 16 | 17 | // The rest of the arguments are the passed command line parameters. 18 | // Call the program like this: 19 | // $ ./args arg1 arg2 20 | println!("I got {:?} arguments: {:?}.", args.len() - 1, &args[1..]); 21 | } 22 | ``` 23 | 24 | ```shell 25 | $ ./args 1 2 3 26 | My path is ./args. 27 | I got 3 arguments: ["1", "2", "3"]. 28 | ``` 29 | 30 | ## Crates 31 | 32 | Alternatively, there are numerous crates that can provide extra functionality 33 | when creating command-line applications. One of the more popular command line 34 | argument crates being [`clap`]. 35 | 36 | [`clap`]: https://rust-cli.github.io/book/tutorial/cli-args.html#parsing-cli-arguments-with-clap 37 | -------------------------------------------------------------------------------- /src/std_misc/channels.md: -------------------------------------------------------------------------------- 1 | # Channels 2 | 3 | Rust provides asynchronous `channels` for communication between threads. Channels 4 | allow a unidirectional flow of information between two end-points: the 5 | `Sender` and the `Receiver`. 6 | 7 | ```rust,editable 8 | use std::sync::mpsc::{Sender, Receiver}; 9 | use std::sync::mpsc; 10 | use std::thread; 11 | 12 | static NTHREADS: i32 = 3; 13 | 14 | fn main() { 15 | // Channels have two endpoints: the `Sender` and the `Receiver`, 16 | // where `T` is the type of the message to be transferred 17 | // (type annotation is superfluous) 18 | let (tx, rx): (Sender, Receiver) = mpsc::channel(); 19 | let mut children = Vec::new(); 20 | 21 | for id in 0..NTHREADS { 22 | // The sender endpoint can be copied 23 | let thread_tx = tx.clone(); 24 | 25 | // Each thread will send its id via the channel 26 | let child = thread::spawn(move || { 27 | // The thread takes ownership over `thread_tx` 28 | // Each thread queues a message in the channel 29 | thread_tx.send(id).unwrap(); 30 | 31 | // Sending is a non-blocking operation, the thread will continue 32 | // immediately after sending its message 33 | println!("thread {} finished", id); 34 | }); 35 | 36 | children.push(child); 37 | } 38 | 39 | // Here, all the messages are collected 40 | let mut ids = Vec::with_capacity(NTHREADS as usize); 41 | for _ in 0..NTHREADS { 42 | // The `recv` method picks a message from the channel 43 | // `recv` will block the current thread if there are no messages available 44 | ids.push(rx.recv()); 45 | } 46 | 47 | // Wait for the threads to complete any remaining work 48 | for child in children { 49 | child.join().expect("oops! the child thread panicked"); 50 | } 51 | 52 | // Show the order in which the messages were sent 53 | println!("{:?}", ids); 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /src/std_misc/ffi.md: -------------------------------------------------------------------------------- 1 | # Foreign Function Interface 2 | 3 | Rust provides a Foreign Function Interface (FFI) to C libraries. Foreign 4 | functions must be declared inside an `extern` block annotated with a `#[link]` 5 | attribute containing the name of the foreign library. 6 | 7 | ```rust,ignore 8 | use std::fmt; 9 | 10 | // this extern block links to the libm library 11 | #[cfg(target_family = "windows")] 12 | #[link(name = "msvcrt")] 13 | extern { 14 | // this is a foreign function 15 | // that computes the square root of a single precision complex number 16 | fn csqrtf(z: Complex) -> Complex; 17 | 18 | fn ccosf(z: Complex) -> Complex; 19 | } 20 | #[cfg(target_family = "unix")] 21 | #[link(name = "m")] 22 | extern { 23 | // this is a foreign function 24 | // that computes the square root of a single precision complex number 25 | fn csqrtf(z: Complex) -> Complex; 26 | 27 | fn ccosf(z: Complex) -> Complex; 28 | } 29 | 30 | // Since calling foreign functions is considered unsafe, 31 | // it's common to write safe wrappers around them. 32 | fn cos(z: Complex) -> Complex { 33 | unsafe { ccosf(z) } 34 | } 35 | 36 | fn main() { 37 | // z = -1 + 0i 38 | let z = Complex { re: -1., im: 0. }; 39 | 40 | // calling a foreign function is an unsafe operation 41 | let z_sqrt = unsafe { csqrtf(z) }; 42 | 43 | println!("the square root of {:?} is {:?}", z, z_sqrt); 44 | 45 | // calling safe API wrapped around unsafe operation 46 | println!("cos({:?}) = {:?}", z, cos(z)); 47 | } 48 | 49 | // Minimal implementation of single precision complex numbers 50 | #[repr(C)] 51 | #[derive(Clone, Copy)] 52 | struct Complex { 53 | re: f32, 54 | im: f32, 55 | } 56 | 57 | impl fmt::Debug for Complex { 58 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 59 | if self.im < 0. { 60 | write!(f, "{}-{}i", self.re, -self.im) 61 | } else { 62 | write!(f, "{}+{}i", self.re, self.im) 63 | } 64 | } 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /src/std_misc/file.md: -------------------------------------------------------------------------------- 1 | # File I/O 2 | 3 | The `File` struct represents a file that has been opened (it wraps a file 4 | descriptor), and gives read and/or write access to the underlying file. 5 | 6 | Since many things can go wrong when doing file I/O, all the `File` methods 7 | return the `io::Result` type, which is an alias for `Result`. 8 | 9 | This makes the failure of all I/O operations *explicit*. Thanks to this, the 10 | programmer can see all the failure paths, and is encouraged to handle them in 11 | a proactive manner. 12 | -------------------------------------------------------------------------------- /src/std_misc/file/create.md: -------------------------------------------------------------------------------- 1 | # `create` 2 | 3 | The `create` function opens a file in write-only mode. If the file 4 | already existed, the old content is destroyed. Otherwise, a new file is 5 | created. 6 | 7 | ```rust,ignore 8 | static LOREM_IPSUM: &str = 9 | "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 10 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 11 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 12 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 13 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 14 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 15 | "; 16 | 17 | use std::fs::File; 18 | use std::io::prelude::*; 19 | use std::path::Path; 20 | 21 | fn main() { 22 | let path = Path::new("lorem_ipsum.txt"); 23 | let display = path.display(); 24 | 25 | // Open a file in write-only mode, returns `io::Result` 26 | let mut file = match File::create(&path) { 27 | Err(why) => panic!("couldn't create {}: {}", display, why), 28 | Ok(file) => file, 29 | }; 30 | 31 | // Write the `LOREM_IPSUM` string to `file`, returns `io::Result<()>` 32 | match file.write_all(LOREM_IPSUM.as_bytes()) { 33 | Err(why) => panic!("couldn't write to {}: {}", display, why), 34 | Ok(_) => println!("successfully wrote to {}", display), 35 | } 36 | } 37 | ``` 38 | 39 | Here's the expected successful output: 40 | 41 | ```shell 42 | $ rustc create.rs && ./create 43 | successfully wrote to lorem_ipsum.txt 44 | 45 | $ cat lorem_ipsum.txt 46 | Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 47 | tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 48 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 49 | consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 50 | cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 51 | proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 52 | ``` 53 | 54 | (As in the previous example, you are encouraged to test this example under 55 | failure conditions.) 56 | 57 | The [`OpenOptions`] struct can be used to configure how a file is opened. 58 | 59 | [`OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html 60 | -------------------------------------------------------------------------------- /src/std_misc/file/open.md: -------------------------------------------------------------------------------- 1 | # `open` 2 | 3 | The `open` function can be used to open a file in read-only mode. 4 | 5 | A `File` owns a resource, the file descriptor and takes care of closing the 6 | file when it is `drop`ed. 7 | 8 | ```rust,editable,ignore 9 | use std::fs::File; 10 | use std::io::prelude::*; 11 | use std::path::Path; 12 | 13 | fn main() { 14 | // Create a path to the desired file 15 | let path = Path::new("hello.txt"); 16 | let display = path.display(); 17 | 18 | // Open the path in read-only mode, returns `io::Result` 19 | let mut file = match File::open(&path) { 20 | Err(why) => panic!("couldn't open {}: {}", display, why), 21 | Ok(file) => file, 22 | }; 23 | 24 | // Read the file contents into a string, returns `io::Result` 25 | let mut s = String::new(); 26 | match file.read_to_string(&mut s) { 27 | Err(why) => panic!("couldn't read {}: {}", display, why), 28 | Ok(_) => print!("{} contains:\n{}", display, s), 29 | } 30 | 31 | // `file` goes out of scope, and the "hello.txt" file gets closed 32 | } 33 | ``` 34 | 35 | Here's the expected successful output: 36 | 37 | ```shell 38 | $ echo "Hello World!" > hello.txt 39 | $ rustc open.rs && ./open 40 | hello.txt contains: 41 | Hello World! 42 | ``` 43 | 44 | (You are encouraged to test the previous example under different failure 45 | conditions: `hello.txt` doesn't exist, or `hello.txt` is not readable, 46 | etc.) 47 | -------------------------------------------------------------------------------- /src/std_misc/path.md: -------------------------------------------------------------------------------- 1 | # Path 2 | 3 | The `Path` struct represents file paths in the underlying filesystem. There are 4 | two flavors of `Path`: `posix::Path`, for UNIX-like systems, and 5 | `windows::Path`, for Windows. The prelude exports the appropriate 6 | platform-specific `Path` variant. 7 | 8 | A `Path` can be created from an `OsStr`, and provides several methods to get 9 | information from the file/directory the path points to. 10 | 11 | A `Path` is immutable. The owned version of `Path` is `PathBuf`. The relation 12 | between `Path` and `PathBuf` is similar to that of `str` and `String`: 13 | a `PathBuf` can be mutated in-place, and can be dereferenced to a `Path`. 14 | 15 | Note that a `Path` is *not* internally represented as an UTF-8 string, but 16 | instead is stored as an `OsString`. Therefore, converting a `Path` to a `&str` 17 | is *not* free and may fail (an `Option` is returned). However, a `Path` can be 18 | freely converted to an `OsString` or `&OsStr` using `into_os_string` and 19 | `as_os_str`, respectively. 20 | 21 | ```rust,editable 22 | use std::path::Path; 23 | 24 | fn main() { 25 | // Create a `Path` from an `&'static str` 26 | let path = Path::new("."); 27 | 28 | // The `display` method returns a `Display`able structure 29 | let _display = path.display(); 30 | 31 | // `join` merges a path with a byte container using the OS specific 32 | // separator, and returns a `PathBuf` 33 | let mut new_path = path.join("a").join("b"); 34 | 35 | // `push` extends the `PathBuf` with a `&Path` 36 | new_path.push("c"); 37 | new_path.push("myfile.tar.gz"); 38 | 39 | // `set_file_name` updates the file name of the `PathBuf` 40 | new_path.set_file_name("package.tgz"); 41 | 42 | // Convert the `PathBuf` into a string slice 43 | match new_path.to_str() { 44 | None => panic!("new path is not a valid UTF-8 sequence"), 45 | Some(s) => println!("new path is {}", s), 46 | } 47 | } 48 | 49 | ``` 50 | 51 | Be sure to check at other `Path` methods (`posix::Path` or `windows::Path`) and 52 | the `Metadata` struct. 53 | 54 | ### See also: 55 | 56 | [OsStr][1] and [Metadata][2]. 57 | 58 | [1]: https://doc.rust-lang.org/std/ffi/struct.OsStr.html 59 | [2]: https://doc.rust-lang.org/std/fs/struct.Metadata.html 60 | -------------------------------------------------------------------------------- /src/std_misc/process.md: -------------------------------------------------------------------------------- 1 | # Child processes 2 | 3 | The `process::Output` struct represents the output of a finished child process, 4 | and the `process::Command` struct is a process builder. 5 | 6 | ```rust,editable,ignore 7 | use std::process::Command; 8 | 9 | fn main() { 10 | let output = Command::new("rustc") 11 | .arg("--version") 12 | .output().unwrap_or_else(|e| { 13 | panic!("failed to execute process: {}", e) 14 | }); 15 | 16 | if output.status.success() { 17 | let s = String::from_utf8_lossy(&output.stdout); 18 | 19 | print!("rustc succeeded and stdout was:\n{}", s); 20 | } else { 21 | let s = String::from_utf8_lossy(&output.stderr); 22 | 23 | print!("rustc failed and stderr was:\n{}", s); 24 | } 25 | } 26 | ``` 27 | 28 | (You are encouraged to try the previous example with an incorrect flag passed 29 | to `rustc`) 30 | -------------------------------------------------------------------------------- /src/std_misc/process/pipe.md: -------------------------------------------------------------------------------- 1 | # Pipes 2 | 3 | The `std::process::Child` struct represents a child process, and exposes the 4 | `stdin`, `stdout` and `stderr` handles for interaction with the underlying 5 | process via pipes. 6 | 7 | ```rust,ignore 8 | use std::io::prelude::*; 9 | use std::process::{Command, Stdio}; 10 | 11 | static PANGRAM: &'static str = 12 | "the quick brown fox jumps over the lazy dog\n"; 13 | 14 | fn main() { 15 | // Spawn the `wc` command 16 | let mut cmd = if cfg!(target_family = "windows") { 17 | let mut cmd = Command::new("powershell"); 18 | cmd.arg("-Command").arg("$input | Measure-Object -Line -Word -Character"); 19 | cmd 20 | } else { 21 | Command::new("wc") 22 | }; 23 | let process = match cmd 24 | .stdin(Stdio::piped()) 25 | .stdout(Stdio::piped()) 26 | .spawn() { 27 | Err(why) => panic!("couldn't spawn wc: {}", why), 28 | Ok(process) => process, 29 | }; 30 | 31 | // Write a string to the `stdin` of `wc`. 32 | // 33 | // `stdin` has type `Option`, but since we know this instance 34 | // must have one, we can directly `unwrap` it. 35 | match process.stdin.unwrap().write_all(PANGRAM.as_bytes()) { 36 | Err(why) => panic!("couldn't write to wc stdin: {}", why), 37 | Ok(_) => println!("sent pangram to wc"), 38 | } 39 | 40 | // Because `stdin` does not live after the above calls, it is `drop`ed, 41 | // and the pipe is closed. 42 | // 43 | // This is very important, otherwise `wc` wouldn't start processing the 44 | // input we just sent. 45 | 46 | // The `stdout` field also has type `Option` so must be unwrapped. 47 | let mut s = String::new(); 48 | match process.stdout.unwrap().read_to_string(&mut s) { 49 | Err(why) => panic!("couldn't read wc stdout: {}", why), 50 | Ok(_) => print!("wc responded with:\n{}", s), 51 | } 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /src/std_misc/process/wait.md: -------------------------------------------------------------------------------- 1 | # Wait 2 | 3 | If you'd like to wait for a `process::Child` to finish, you must call 4 | `Child::wait`, which will return a `process::ExitStatus`. 5 | 6 | ```rust,ignore 7 | use std::process::Command; 8 | 9 | fn main() { 10 | let mut child = Command::new("sleep").arg("5").spawn().unwrap(); 11 | let _result = child.wait().unwrap(); 12 | 13 | println!("reached end of main"); 14 | } 15 | ``` 16 | 17 | ```bash 18 | $ rustc wait.rs && ./wait 19 | # `wait` keeps running for 5 seconds until the `sleep 5` command finishes 20 | reached end of main 21 | ``` 22 | -------------------------------------------------------------------------------- /src/std_misc/threads.md: -------------------------------------------------------------------------------- 1 | # Threads 2 | 3 | Rust provides a mechanism for spawning native OS threads via the `spawn` 4 | function, the argument of this function is a moving closure. 5 | 6 | ```rust,editable 7 | use std::thread; 8 | 9 | const NTHREADS: u32 = 10; 10 | 11 | // This is the `main` thread 12 | fn main() { 13 | // Make a vector to hold the children which are spawned. 14 | let mut children = vec![]; 15 | 16 | for i in 0..NTHREADS { 17 | // Spin up another thread 18 | children.push(thread::spawn(move || { 19 | println!("this is thread number {}", i); 20 | })); 21 | } 22 | 23 | for child in children { 24 | // Wait for the thread to finish. Returns a result. 25 | let _ = child.join(); 26 | } 27 | } 28 | ``` 29 | 30 | These threads will be scheduled by the OS. 31 | -------------------------------------------------------------------------------- /src/testing.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | 3 | Rust is a programming language that cares a lot about correctness and it 4 | includes support for writing software tests within the language itself. 5 | 6 | Testing comes in three styles: 7 | 8 | * [Unit][unit] testing. 9 | * [Doc][doc] testing. 10 | * [Integration][integration] testing. 11 | 12 | Also Rust has support for specifying additional dependencies for tests: 13 | 14 | * [Dev-dependencies][dev-dependencies] 15 | 16 | ## See Also 17 | 18 | * [The Book][doc-testing] chapter on testing 19 | * [API Guidelines][doc-nursery] on doc-testing 20 | 21 | [unit]: testing/unit_testing.md 22 | [doc]: testing/doc_testing.md 23 | [integration]: testing/integration_testing.md 24 | [dev-dependencies]: testing/dev_dependencies.md 25 | [doc-testing]: https://doc.rust-lang.org/book/ch11-00-testing.html 26 | [doc-nursery]: https://rust-lang-nursery.github.io/api-guidelines/documentation.html 27 | -------------------------------------------------------------------------------- /src/testing/dev_dependencies.md: -------------------------------------------------------------------------------- 1 | # Development dependencies 2 | 3 | Sometimes there is a need to have dependencies for tests (or examples, 4 | or benchmarks) only. Such dependencies are added to `Cargo.toml` in the 5 | `[dev-dependencies]` section. These dependencies are not propagated to other 6 | packages which depend on this package. 7 | 8 | One such example is [`pretty_assertions`](https://docs.rs/pretty_assertions/1.0.0/pretty_assertions/index.html), which extends standard `assert_eq!` and `assert_ne!` macros, to provide colorful diff. 9 | File `Cargo.toml`: 10 | 11 | ```toml 12 | # standard crate data is left out 13 | [dev-dependencies] 14 | pretty_assertions = "1" 15 | ``` 16 | 17 | File `src/lib.rs`: 18 | 19 | ```rust,ignore 20 | pub fn add(a: i32, b: i32) -> i32 { 21 | a + b 22 | } 23 | 24 | #[cfg(test)] 25 | mod tests { 26 | use super::*; 27 | use pretty_assertions::assert_eq; // crate for test-only use. Cannot be used in non-test code. 28 | 29 | #[test] 30 | fn test_add() { 31 | assert_eq!(add(2, 3), 5); 32 | } 33 | } 34 | ``` 35 | 36 | ## See Also 37 | 38 | [Cargo][cargo] docs on specifying dependencies. 39 | 40 | [cargo]: http://doc.crates.io/specifying-dependencies.html 41 | -------------------------------------------------------------------------------- /src/testing/integration_testing.md: -------------------------------------------------------------------------------- 1 | # Integration testing 2 | 3 | [Unit tests][unit] are testing one module in isolation at a time: they're small 4 | and can test private code. Integration tests are external to your crate and use 5 | only its public interface in the same way any other code would. Their purpose is 6 | to test that many parts of your library work correctly together. 7 | 8 | Cargo looks for integration tests in `tests` directory next to `src`. 9 | 10 | File `src/lib.rs`: 11 | 12 | ```rust,ignore 13 | // Define this in a crate called `adder`. 14 | pub fn add(a: i32, b: i32) -> i32 { 15 | a + b 16 | } 17 | ``` 18 | 19 | File with test: `tests/integration_test.rs`: 20 | 21 | ```rust,ignore 22 | #[test] 23 | fn test_add() { 24 | assert_eq!(adder::add(3, 2), 5); 25 | } 26 | ``` 27 | 28 | Running tests with `cargo test` command: 29 | 30 | ```shell 31 | $ cargo test 32 | running 0 tests 33 | 34 | test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out 35 | 36 | Running target/debug/deps/integration_test-bcd60824f5fbfe19 37 | 38 | running 1 test 39 | test test_add ... ok 40 | 41 | test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out 42 | 43 | Doc-tests adder 44 | 45 | running 0 tests 46 | 47 | test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out 48 | ``` 49 | 50 | Each Rust source file in the `tests` directory is compiled as a separate crate. In 51 | order to share some code between integration tests we can make a module with public 52 | functions, importing and using it within tests. 53 | 54 | File `tests/common/mod.rs`: 55 | 56 | ```rust,ignore 57 | pub fn setup() { 58 | // some setup code, like creating required files/directories, starting 59 | // servers, etc. 60 | } 61 | ``` 62 | 63 | File with test: `tests/integration_test.rs` 64 | 65 | ```rust,ignore 66 | // importing common module. 67 | mod common; 68 | 69 | #[test] 70 | fn test_add() { 71 | // using common code. 72 | common::setup(); 73 | assert_eq!(adder::add(3, 2), 5); 74 | } 75 | ``` 76 | 77 | Creating the module as `tests/common.rs` also works, but is not recommended 78 | because the test runner will treat the file as a test crate and try to run tests 79 | inside it. 80 | 81 | [unit]: unit_testing.md 82 | [mod]: ../mod.md 83 | -------------------------------------------------------------------------------- /src/trait.md: -------------------------------------------------------------------------------- 1 | # Traits 2 | 3 | A `trait` is a collection of methods defined for an unknown type: 4 | `Self`. They can access other methods declared in the same trait. 5 | 6 | Traits can be implemented for any data type. In the example below, 7 | we define `Animal`, a group of methods. The `Animal` `trait` is 8 | then implemented for the `Sheep` data type, allowing the use of 9 | methods from `Animal` with a `Sheep`. 10 | 11 | ```rust,editable 12 | struct Sheep { naked: bool, name: &'static str } 13 | 14 | trait Animal { 15 | // Associated function signature; `Self` refers to the implementor type. 16 | fn new(name: &'static str) -> Self; 17 | 18 | // Method signatures; these will return a string. 19 | fn name(&self) -> &'static str; 20 | fn noise(&self) -> &'static str; 21 | 22 | // Traits can provide default method definitions. 23 | fn talk(&self) { 24 | println!("{} says {}", self.name(), self.noise()); 25 | } 26 | } 27 | 28 | impl Sheep { 29 | fn is_naked(&self) -> bool { 30 | self.naked 31 | } 32 | 33 | fn shear(&mut self) { 34 | if self.is_naked() { 35 | // Implementor methods can use the implementor's trait methods. 36 | println!("{} is already naked...", self.name()); 37 | } else { 38 | println!("{} gets a haircut!", self.name); 39 | 40 | self.naked = true; 41 | } 42 | } 43 | } 44 | 45 | // Implement the `Animal` trait for `Sheep`. 46 | impl Animal for Sheep { 47 | // `Self` is the implementor type: `Sheep`. 48 | fn new(name: &'static str) -> Sheep { 49 | Sheep { name: name, naked: false } 50 | } 51 | 52 | fn name(&self) -> &'static str { 53 | self.name 54 | } 55 | 56 | fn noise(&self) -> &'static str { 57 | if self.is_naked() { 58 | "baaaaah?" 59 | } else { 60 | "baaaaah!" 61 | } 62 | } 63 | 64 | // Default trait methods can be overridden. 65 | fn talk(&self) { 66 | // For example, we can add some quiet contemplation. 67 | println!("{} pauses briefly... {}", self.name, self.noise()); 68 | } 69 | } 70 | 71 | fn main() { 72 | // Type annotation is necessary in this case. 73 | let mut dolly: Sheep = Animal::new("Dolly"); 74 | // TODO ^ Try removing the type annotations. 75 | 76 | dolly.talk(); 77 | dolly.shear(); 78 | dolly.talk(); 79 | } 80 | ``` 81 | -------------------------------------------------------------------------------- /src/trait/clone.md: -------------------------------------------------------------------------------- 1 | # Clone 2 | 3 | When dealing with resources, the default behavior is to transfer them during 4 | assignments or function calls. However, sometimes we need to make a 5 | copy of the resource as well. 6 | 7 | The [`Clone`][clone] trait helps us do exactly this. Most commonly, we can 8 | use the `.clone()` method defined by the `Clone` trait. 9 | 10 | ```rust,editable 11 | // A unit struct without resources 12 | #[derive(Debug, Clone, Copy)] 13 | struct Unit; 14 | 15 | // A tuple struct with resources that implements the `Clone` trait 16 | #[derive(Clone, Debug)] 17 | struct Pair(Box, Box); 18 | 19 | fn main() { 20 | // Instantiate `Unit` 21 | let unit = Unit; 22 | // Copy `Unit`, there are no resources to move 23 | let copied_unit = unit; 24 | 25 | // Both `Unit`s can be used independently 26 | println!("original: {:?}", unit); 27 | println!("copy: {:?}", copied_unit); 28 | 29 | // Instantiate `Pair` 30 | let pair = Pair(Box::new(1), Box::new(2)); 31 | println!("original: {:?}", pair); 32 | 33 | // Move `pair` into `moved_pair`, moves resources 34 | let moved_pair = pair; 35 | println!("moved: {:?}", moved_pair); 36 | 37 | // Error! `pair` has lost its resources 38 | //println!("original: {:?}", pair); 39 | // TODO ^ Try uncommenting this line 40 | 41 | // Clone `moved_pair` into `cloned_pair` (resources are included) 42 | let cloned_pair = moved_pair.clone(); 43 | // Drop the moved original pair using std::mem::drop 44 | drop(moved_pair); 45 | 46 | // Error! `moved_pair` has been dropped 47 | //println!("moved and dropped: {:?}", moved_pair); 48 | // TODO ^ Try uncommenting this line 49 | 50 | // The result from .clone() can still be used! 51 | println!("clone: {:?}", cloned_pair); 52 | } 53 | ``` 54 | 55 | [clone]: https://doc.rust-lang.org/std/clone/trait.Clone.html 56 | -------------------------------------------------------------------------------- /src/trait/disambiguating.md: -------------------------------------------------------------------------------- 1 | # Disambiguating overlapping traits 2 | 3 | A type can implement many different traits. What if two traits both require 4 | the same name for a function? For example, many traits might have a method 5 | named `get()`. They might even have different return types! 6 | 7 | Good news: because each trait implementation gets its own `impl` block, it's 8 | clear which trait's `get` method you're implementing. 9 | 10 | What about when it comes time to _call_ those methods? To disambiguate between 11 | them, we have to use Fully Qualified Syntax. 12 | 13 | ```rust,editable 14 | trait UsernameWidget { 15 | // Get the selected username out of this widget 16 | fn get(&self) -> String; 17 | } 18 | 19 | trait AgeWidget { 20 | // Get the selected age out of this widget 21 | fn get(&self) -> u8; 22 | } 23 | 24 | // A form with both a UsernameWidget and an AgeWidget 25 | struct Form { 26 | username: String, 27 | age: u8, 28 | } 29 | 30 | impl UsernameWidget for Form { 31 | fn get(&self) -> String { 32 | self.username.clone() 33 | } 34 | } 35 | 36 | impl AgeWidget for Form { 37 | fn get(&self) -> u8 { 38 | self.age 39 | } 40 | } 41 | 42 | fn main() { 43 | let form = Form { 44 | username: "rustacean".to_owned(), 45 | age: 28, 46 | }; 47 | 48 | // If you uncomment this line, you'll get an error saying 49 | // "multiple `get` found". Because, after all, there are multiple methods 50 | // named `get`. 51 | // println!("{}", form.get()); 52 | 53 | let username =
::get(&form); 54 | assert_eq!("rustacean".to_owned(), username); 55 | let age = ::get(&form); 56 | assert_eq!(28, age); 57 | } 58 | ``` 59 | 60 | ### See also: 61 | 62 | [The Rust Programming Language chapter on Fully Qualified syntax][trpl_fqsyntax] 63 | 64 | [trpl_fqsyntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name 65 | -------------------------------------------------------------------------------- /src/trait/dyn.md: -------------------------------------------------------------------------------- 1 | # Returning Traits with `dyn` 2 | 3 | The Rust compiler needs to know how much space every function's return type requires. This means all 4 | your functions have to return a concrete type. Unlike other languages, if you have a trait like 5 | `Animal`, you can't write a function that returns `Animal`, because its different implementations 6 | will need different amounts of memory. 7 | 8 | However, there's an easy workaround. Instead of returning a trait object directly, our functions 9 | return a `Box` which _contains_ some `Animal`. A `box` is just a reference to some memory in the 10 | heap. Because a reference has a statically-known size, and the compiler can guarantee it points to a 11 | heap-allocated `Animal`, we can return a trait from our function! 12 | 13 | Rust tries to be as explicit as possible whenever it allocates memory on the heap. So if your 14 | function returns a pointer-to-trait-on-heap in this way, you need to write the return type with the 15 | `dyn` keyword, e.g. `Box`. 16 | 17 | ```rust,editable 18 | struct Sheep {} 19 | struct Cow {} 20 | 21 | trait Animal { 22 | // Instance method signature 23 | fn noise(&self) -> &'static str; 24 | } 25 | 26 | // Implement the `Animal` trait for `Sheep`. 27 | impl Animal for Sheep { 28 | fn noise(&self) -> &'static str { 29 | "baaaaah!" 30 | } 31 | } 32 | 33 | // Implement the `Animal` trait for `Cow`. 34 | impl Animal for Cow { 35 | fn noise(&self) -> &'static str { 36 | "moooooo!" 37 | } 38 | } 39 | 40 | // Returns some struct that implements Animal, but we don't know which one at compile time. 41 | fn random_animal(random_number: f64) -> Box { 42 | if random_number < 0.5 { 43 | Box::new(Sheep {}) 44 | } else { 45 | Box::new(Cow {}) 46 | } 47 | } 48 | 49 | fn main() { 50 | let random_number = 0.234; 51 | let animal = random_animal(random_number); 52 | println!("You've randomly chosen an animal, and it says {}", animal.noise()); 53 | } 54 | 55 | ``` 56 | -------------------------------------------------------------------------------- /src/trait/ops.md: -------------------------------------------------------------------------------- 1 | # Operator Overloading 2 | 3 | In Rust, many of the operators can be overloaded via traits. That is, some operators can 4 | be used to accomplish different tasks based on their input arguments. This is possible 5 | because operators are syntactic sugar for method calls. For example, the `+` operator in 6 | `a + b` calls the `add` method (as in `a.add(b)`). This `add` method is part of the `Add` 7 | trait. Hence, the `+` operator can be used by any implementor of the `Add` trait. 8 | 9 | A list of the traits, such as `Add`, that overload operators can be found in [`core::ops`][ops]. 10 | 11 | ```rust,editable 12 | use std::ops; 13 | 14 | struct Foo; 15 | struct Bar; 16 | 17 | #[derive(Debug)] 18 | struct FooBar; 19 | 20 | #[derive(Debug)] 21 | struct BarFoo; 22 | 23 | // The `std::ops::Add` trait is used to specify the functionality of `+`. 24 | // Here, we make `Add` - the trait for addition with a RHS of type `Bar`. 25 | // The following block implements the operation: Foo + Bar = FooBar 26 | impl ops::Add for Foo { 27 | type Output = FooBar; 28 | 29 | fn add(self, _rhs: Bar) -> FooBar { 30 | println!("> Foo.add(Bar) was called"); 31 | 32 | FooBar 33 | } 34 | } 35 | 36 | // By reversing the types, we end up implementing non-commutative addition. 37 | // Here, we make `Add` - the trait for addition with a RHS of type `Foo`. 38 | // This block implements the operation: Bar + Foo = BarFoo 39 | impl ops::Add for Bar { 40 | type Output = BarFoo; 41 | 42 | fn add(self, _rhs: Foo) -> BarFoo { 43 | println!("> Bar.add(Foo) was called"); 44 | 45 | BarFoo 46 | } 47 | } 48 | 49 | fn main() { 50 | println!("Foo + Bar = {:?}", Foo + Bar); 51 | println!("Bar + Foo = {:?}", Bar + Foo); 52 | } 53 | ``` 54 | 55 | ### See Also 56 | 57 | [Add][add], [Syntax Index][syntax] 58 | 59 | [add]: https://doc.rust-lang.org/core/ops/trait.Add.html 60 | [ops]: https://doc.rust-lang.org/core/ops/ 61 | [syntax]:https://doc.rust-lang.org/book/appendix-02-operators.html 62 | -------------------------------------------------------------------------------- /src/trait/supertraits.md: -------------------------------------------------------------------------------- 1 | # Supertraits 2 | 3 | Rust doesn't have "inheritance", but you can define a trait as being a superset 4 | of another trait. For example: 5 | 6 | ```rust,editable 7 | trait Person { 8 | fn name(&self) -> String; 9 | } 10 | 11 | // Person is a supertrait of Student. 12 | // Implementing Student requires you to also impl Person. 13 | trait Student: Person { 14 | fn university(&self) -> String; 15 | } 16 | 17 | trait Programmer { 18 | fn fav_language(&self) -> String; 19 | } 20 | 21 | // CompSciStudent (computer science student) is a subtrait of both Programmer 22 | // and Student. Implementing CompSciStudent requires you to impl both supertraits. 23 | trait CompSciStudent: Programmer + Student { 24 | fn git_username(&self) -> String; 25 | } 26 | 27 | fn comp_sci_student_greeting(student: &dyn CompSciStudent) -> String { 28 | format!( 29 | "My name is {} and I attend {}. My favorite language is {}. My Git username is {}", 30 | student.name(), 31 | student.university(), 32 | student.fav_language(), 33 | student.git_username() 34 | ) 35 | } 36 | 37 | fn main() {} 38 | ``` 39 | 40 | ### See also: 41 | 42 | [The Rust Programming Language chapter on supertraits][trpl_supertraits] 43 | 44 | [trpl_supertraits]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-supertraits-to-require-one-traits-functionality-within-another-trait 45 | -------------------------------------------------------------------------------- /src/types.md: -------------------------------------------------------------------------------- 1 | # Types 2 | 3 | Rust provides several mechanisms to change or define the type of primitive and 4 | user defined types. The following sections cover: 5 | 6 | * [Casting] between primitive types 7 | * Specifying the desired type of [literals] 8 | * Using [type inference] 9 | * [Aliasing] types 10 | 11 | [Casting]: types/cast.md 12 | [literals]: types/literals.md 13 | [type inference]: types/inference.md 14 | [Aliasing]: types/alias.md 15 | -------------------------------------------------------------------------------- /src/types/alias.md: -------------------------------------------------------------------------------- 1 | # Aliasing 2 | 3 | The `type` statement can be used to give a new name to an existing type. Types 4 | must have `UpperCamelCase` names, or the compiler will raise a warning. The 5 | exception to this rule are the primitive types: `usize`, `f32`, etc. 6 | 7 | ```rust,editable 8 | // `NanoSecond`, `Inch`, and `U64` are new names for `u64`. 9 | type NanoSecond = u64; 10 | type Inch = u64; 11 | type U64 = u64; 12 | 13 | fn main() { 14 | // `NanoSecond` = `Inch` = `U64` = `u64`. 15 | let nanoseconds: NanoSecond = 5 as u64; 16 | let inches: Inch = 2 as U64; 17 | 18 | // Note that type aliases *don't* provide any extra type safety, because 19 | // aliases are *not* new types 20 | println!("{} nanoseconds + {} inches = {} unit?", 21 | nanoseconds, 22 | inches, 23 | nanoseconds + inches); 24 | } 25 | ``` 26 | 27 | The main use of aliases is to reduce boilerplate; for example the `io::Result` type 28 | is an alias for the `Result` type. 29 | 30 | ### See also: 31 | 32 | [Attributes](../attribute.md) 33 | -------------------------------------------------------------------------------- /src/types/inference.md: -------------------------------------------------------------------------------- 1 | # Inference 2 | 3 | The type inference engine is pretty smart. It does more than looking at the 4 | type of the value expression 5 | during an initialization. It also looks at how the variable is used afterwards 6 | to infer its type. Here's an advanced example of type inference: 7 | 8 | ```rust,editable 9 | fn main() { 10 | // Because of the annotation, the compiler knows that `elem` has type u8. 11 | let elem = 5u8; 12 | 13 | // Create an empty vector (a growable array). 14 | let mut vec = Vec::new(); 15 | // At this point the compiler doesn't know the exact type of `vec`, it 16 | // just knows that it's a vector of something (`Vec<_>`). 17 | 18 | // Insert `elem` in the vector. 19 | vec.push(elem); 20 | // Aha! Now the compiler knows that `vec` is a vector of `u8`s (`Vec`) 21 | // TODO ^ Try commenting out the `vec.push(elem)` line 22 | 23 | println!("{:?}", vec); 24 | } 25 | ``` 26 | 27 | No type annotation of variables was needed, the compiler is happy and so is the 28 | programmer! 29 | -------------------------------------------------------------------------------- /src/types/literals.md: -------------------------------------------------------------------------------- 1 | # Literals 2 | 3 | Numeric literals can be type annotated by adding the type as a suffix. As an example, 4 | to specify that the literal `42` should have the type `i32`, write `42i32`. 5 | 6 | The type of unsuffixed numeric literals will depend on how they are used. If no 7 | constraint exists, the compiler will use `i32` for integers, and `f64` for 8 | floating-point numbers. 9 | 10 | ```rust,editable 11 | fn main() { 12 | // Suffixed literals, their types are known at initialization 13 | let x = 1u8; 14 | let y = 2u32; 15 | let z = 3f32; 16 | 17 | // Unsuffixed literals, their types depend on how they are used 18 | let i = 1; 19 | let f = 1.0; 20 | 21 | // `size_of_val` returns the size of a variable in bytes 22 | println!("size of `x` in bytes: {}", std::mem::size_of_val(&x)); 23 | println!("size of `y` in bytes: {}", std::mem::size_of_val(&y)); 24 | println!("size of `z` in bytes: {}", std::mem::size_of_val(&z)); 25 | println!("size of `i` in bytes: {}", std::mem::size_of_val(&i)); 26 | println!("size of `f` in bytes: {}", std::mem::size_of_val(&f)); 27 | } 28 | ``` 29 | 30 | There are some concepts used in the previous code that haven't been explained 31 | yet, here's a brief explanation for the impatient readers: 32 | 33 | * `std::mem::size_of_val` is a function, but called with its *full path*. Code 34 | can be split in logical units called *modules*. In this case, the 35 | `size_of_val` function is defined in the `mem` module, and the `mem` module 36 | is defined in the `std` *crate*. For more details, see 37 | [modules][mod] and [crates][crate]. 38 | 39 | [mod]: ../mod.md 40 | [crate]: ../crates.md 41 | -------------------------------------------------------------------------------- /src/unsafe.md: -------------------------------------------------------------------------------- 1 | # Unsafe Operations 2 | 3 | As an introduction to this section, to borrow from [the official docs][unsafe], 4 | "one should try to minimize the amount of unsafe code in a code base." With that 5 | in mind, let's get started! Unsafe annotations in Rust are used to bypass 6 | protections put in place by the compiler; specifically, there are four primary 7 | things that unsafe is used for: 8 | 9 | * dereferencing raw pointers 10 | * calling functions or methods which are `unsafe` (including calling a function 11 | over FFI, see [a previous chapter](std_misc/ffi.md) of the book) 12 | * accessing or modifying static mutable variables 13 | * implementing unsafe traits 14 | 15 | ### Raw Pointers 16 | 17 | Raw pointers `*` and references `&T` function similarly, but references are 18 | always safe because they are guaranteed to point to valid data due to the 19 | borrow checker. Dereferencing a raw pointer can only be done through an unsafe 20 | block. 21 | 22 | ```rust,editable 23 | fn main() { 24 | let raw_p: *const u32 = &10; 25 | 26 | unsafe { 27 | assert!(*raw_p == 10); 28 | } 29 | } 30 | ``` 31 | 32 | ### Calling Unsafe Functions 33 | 34 | Some functions can be declared as `unsafe`, meaning it is the programmer's 35 | responsibility to ensure correctness instead of the compiler's. One example 36 | of this is [`std::slice::from_raw_parts`] which will create a slice given a 37 | pointer to the first element and a length. 38 | 39 | ```rust,editable 40 | use std::slice; 41 | 42 | fn main() { 43 | let some_vector = vec![1, 2, 3, 4]; 44 | 45 | let pointer = some_vector.as_ptr(); 46 | let length = some_vector.len(); 47 | 48 | unsafe { 49 | let my_slice: &[u32] = slice::from_raw_parts(pointer, length); 50 | 51 | assert_eq!(some_vector.as_slice(), my_slice); 52 | } 53 | } 54 | ``` 55 | 56 | For `slice::from_raw_parts`, one of the assumptions which *must* be upheld is 57 | that the pointer passed in points to valid memory and that the memory pointed to 58 | is of the correct type. If these invariants aren't upheld then the program's 59 | behaviour is undefined and there is no knowing what will happen. 60 | 61 | [unsafe]: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html 62 | [`std::slice::from_raw_parts`]: https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html 63 | -------------------------------------------------------------------------------- /src/variable_bindings.md: -------------------------------------------------------------------------------- 1 | # Variable Bindings 2 | 3 | Rust provides type safety via static typing. Variable bindings can be type 4 | annotated when declared. However, in most cases, the compiler will be able 5 | to infer the type of the variable from the context, heavily reducing the 6 | annotation burden. 7 | 8 | Values (like literals) can be bound to variables, using the `let` binding. 9 | 10 | ```rust,editable 11 | fn main() { 12 | let an_integer = 1u32; 13 | let a_boolean = true; 14 | let unit = (); 15 | 16 | // copy `an_integer` into `copied_integer` 17 | let copied_integer = an_integer; 18 | 19 | println!("An integer: {:?}", copied_integer); 20 | println!("A boolean: {:?}", a_boolean); 21 | println!("Meet the unit value: {:?}", unit); 22 | 23 | // The compiler warns about unused variable bindings; these warnings can 24 | // be silenced by prefixing the variable name with an underscore 25 | let _unused_variable = 3u32; 26 | 27 | let noisy_unused_variable = 2u32; 28 | // FIXME ^ Prefix with an underscore to suppress the warning 29 | // Please note that warnings may not be shown in a browser 30 | } 31 | ``` 32 | -------------------------------------------------------------------------------- /src/variable_bindings/declare.md: -------------------------------------------------------------------------------- 1 | # Declare first 2 | 3 | It is possible to declare variable bindings first and initialize them later, but all variable bindings must be initialized before they are used: the compiler forbids use of uninitialized variable bindings, as it would lead to undefined behavior. 4 | 5 | It is not common to declare a variable binding and initialize it later in the function. 6 | It is more difficult for a reader to find the initialization when initialization is separated from declaration. 7 | It is common to declare and initialize a variable binding near where the variable will be used. 8 | 9 | ```rust,editable,ignore,mdbook-runnable 10 | fn main() { 11 | // Declare a variable binding 12 | let a_binding; 13 | 14 | { 15 | let x = 2; 16 | 17 | // Initialize the binding 18 | a_binding = x * x; 19 | } 20 | 21 | println!("a binding: {}", a_binding); 22 | 23 | let another_binding; 24 | 25 | // Error! Use of uninitialized binding 26 | println!("another binding: {}", another_binding); 27 | // FIXME ^ Comment out this line 28 | 29 | another_binding = 1; 30 | 31 | println!("another binding: {}", another_binding); 32 | } 33 | ``` 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/variable_bindings/freeze.md: -------------------------------------------------------------------------------- 1 | # Freezing 2 | 3 | When data is bound by the same name immutably, it also *freezes*. *Frozen* data can't be 4 | modified until the immutable binding goes out of scope: 5 | 6 | ```rust,editable,ignore,mdbook-runnable 7 | fn main() { 8 | let mut _mutable_integer = 7i32; 9 | 10 | { 11 | // Shadowing by immutable `_mutable_integer` 12 | let _mutable_integer = _mutable_integer; 13 | 14 | // Error! `_mutable_integer` is frozen in this scope 15 | _mutable_integer = 50; 16 | // FIXME ^ Comment out this line 17 | 18 | // `_mutable_integer` goes out of scope 19 | } 20 | 21 | // Ok! `_mutable_integer` is not frozen in this scope 22 | _mutable_integer = 3; 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /src/variable_bindings/mut.md: -------------------------------------------------------------------------------- 1 | # Mutability 2 | 3 | Variable bindings are immutable by default, but this can be overridden using 4 | the `mut` modifier. 5 | 6 | ```rust,editable,ignore,mdbook-runnable 7 | fn main() { 8 | let _immutable_binding = 1; 9 | let mut mutable_binding = 1; 10 | 11 | println!("Before mutation: {}", mutable_binding); 12 | 13 | // Ok 14 | mutable_binding += 1; 15 | 16 | println!("After mutation: {}", mutable_binding); 17 | 18 | // Error! Cannot assign a new value to an immutable variable 19 | _immutable_binding += 1; 20 | } 21 | ``` 22 | 23 | The compiler will throw a detailed diagnostic about mutability errors. 24 | -------------------------------------------------------------------------------- /src/variable_bindings/scope.md: -------------------------------------------------------------------------------- 1 | # Scope and Shadowing 2 | 3 | Variable bindings have a scope, and are constrained to live in a *block*. A 4 | block is a collection of statements enclosed by braces `{}`. 5 | 6 | ```rust,editable,ignore,mdbook-runnable 7 | fn main() { 8 | // This binding lives in the main function 9 | let long_lived_binding = 1; 10 | 11 | // This is a block, and has a smaller scope than the main function 12 | { 13 | // This binding only exists in this block 14 | let short_lived_binding = 2; 15 | 16 | println!("inner short: {}", short_lived_binding); 17 | } 18 | // End of the block 19 | 20 | // Error! `short_lived_binding` doesn't exist in this scope 21 | println!("outer short: {}", short_lived_binding); 22 | // FIXME ^ Comment out this line 23 | 24 | println!("outer long: {}", long_lived_binding); 25 | } 26 | ``` 27 | 28 | Also, [variable shadowing][variable-shadow] is allowed. 29 | 30 | ```rust,editable,ignore,mdbook-runnable 31 | fn main() { 32 | let shadowed_binding = 1; 33 | 34 | { 35 | println!("before being shadowed: {}", shadowed_binding); 36 | 37 | // This binding *shadows* the outer one 38 | let shadowed_binding = "abc"; 39 | 40 | println!("shadowed in inner block: {}", shadowed_binding); 41 | } 42 | println!("outside inner block: {}", shadowed_binding); 43 | 44 | // This binding *shadows* the previous binding 45 | let shadowed_binding = 2; 46 | println!("shadowed in outer block: {}", shadowed_binding); 47 | } 48 | ``` 49 | 50 | [variable-shadow]: https://en.wikipedia.org/wiki/Variable_shadowing 51 | -------------------------------------------------------------------------------- /theme/css/language-picker.css: -------------------------------------------------------------------------------- 1 | #language-list { 2 | left: auto; 3 | right: 10px; 4 | } 5 | 6 | [dir="rtl"] #language-list { 7 | left: 10px; 8 | right: auto; 9 | } 10 | 11 | #language-list a { 12 | color: inherit; 13 | } 14 | -------------------------------------------------------------------------------- /theme/head.hbs: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /theme/js/language-picker.js: -------------------------------------------------------------------------------- 1 | (function addThemePicker() { 2 | const rightButtonsElement = document.querySelector('.right-buttons'); 3 | rightButtonsElement.insertAdjacentHTML("afterbegin", ` 4 | 10 | 24 | `); 25 | 26 | const language = document.documentElement.getAttribute("lang"); 27 | let langToggle = document.getElementById("language-toggle"); 28 | let langList = document.getElementById("language-list"); 29 | langToggle.addEventListener("click", (event) => { 30 | langList.style.display = 31 | langList.style.display == "block" ? "none" : "block"; 32 | }); 33 | let selectedLang = document.getElementById(language); 34 | if (selectedLang) { 35 | selectedLang.parentNode.classList.add("theme-selected"); 36 | } 37 | 38 | // The path to the root, taking the current language into account. 39 | let full_path_to_root = 40 | language == "en" ? `${mdbookPathToRoot}` : `${mdbookPathToRoot}../`; 41 | // The page path (mdbook only gives us access to the path to the Markdown file). 42 | let path = mdbookPath.replace(/\.md$/, ".html"); 43 | for (let lang of langList.querySelectorAll("a")) { 44 | if (lang.id == "en") { 45 | lang.href = `${full_path_to_root}${path}`; 46 | } else { 47 | lang.href = `${full_path_to_root}${lang.id}/${path}`; 48 | } 49 | } 50 | })(); 51 | -------------------------------------------------------------------------------- /triagebot.toml: -------------------------------------------------------------------------------- 1 | [assign] 2 | 3 | [assign.owners] 4 | "*" = ["@marioidival"] 5 | --------------------------------------------------------------------------------