| <!DOCTYPE HTML> |
| <html lang="en" class="sidebar-visible no-js light"> |
| <head> |
| <!-- Book generated using mdBook --> |
| <meta charset="UTF-8"> |
| <title>Rust By Example</title> |
| <meta name="robots" content="noindex" /> |
| <!-- Custom HTML head --> |
| |
| |
| <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> |
| <meta name="description" content="Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust concepts and standard libraries."> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <meta name="theme-color" content="#ffffff" /> |
| |
| <link rel="icon" href="favicon.svg"> |
| <link rel="shortcut icon" href="favicon.png"> |
| <link rel="stylesheet" href="css/variables.css"> |
| <link rel="stylesheet" href="css/general.css"> |
| <link rel="stylesheet" href="css/chrome.css"> |
| <link rel="stylesheet" href="css/print.css" media="print"> |
| <!-- Fonts --> |
| <link rel="stylesheet" href="FontAwesome/css/font-awesome.css"> |
| <link rel="stylesheet" href="fonts/fonts.css"> |
| <!-- Highlight.js Stylesheets --> |
| <link rel="stylesheet" href="highlight.css"> |
| <link rel="stylesheet" href="tomorrow-night.css"> |
| <link rel="stylesheet" href="ayu-highlight.css"> |
| |
| <!-- Custom theme stylesheets --> |
| </head> |
| <body> |
| <!-- Provide site root to javascript --> |
| <script type="text/javascript"> |
| var path_to_root = ""; |
| var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light"; |
| </script> |
| |
| <!-- Work around some values being stored in localStorage wrapped in quotes --> |
| <script type="text/javascript"> |
| try { |
| var theme = localStorage.getItem('mdbook-theme'); |
| var sidebar = localStorage.getItem('mdbook-sidebar'); |
| |
| if (theme.startsWith('"') && theme.endsWith('"')) { |
| localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1)); |
| } |
| |
| if (sidebar.startsWith('"') && sidebar.endsWith('"')) { |
| localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1)); |
| } |
| } catch (e) { } |
| </script> |
| |
| <!-- Set the theme before any content is loaded, prevents flash --> |
| <script type="text/javascript"> |
| var theme; |
| try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } |
| if (theme === null || theme === undefined) { theme = default_theme; } |
| var html = document.querySelector('html'); |
| html.classList.remove('no-js') |
| html.classList.remove('light') |
| html.classList.add(theme); |
| html.classList.add('js'); |
| </script> |
| |
| <!-- Hide / unhide sidebar before it is displayed --> |
| <script type="text/javascript"> |
| var html = document.querySelector('html'); |
| var sidebar = 'hidden'; |
| if (document.body.clientWidth >= 1080) { |
| try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } |
| sidebar = sidebar || 'visible'; |
| } |
| html.classList.remove('sidebar-visible'); |
| html.classList.add("sidebar-" + sidebar); |
| </script> |
| |
| <nav id="sidebar" class="sidebar" aria-label="Table of contents"> |
| <div class="sidebar-scrollbox"> |
| <ol class="chapter"><li class="chapter-item affix "><a href="index.html">Introduction</a></li><li class="chapter-item "><a href="hello.html"><strong aria-hidden="true">1.</strong> Hello World</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="hello/comment.html"><strong aria-hidden="true">1.1.</strong> Comments</a></li><li class="chapter-item "><a href="hello/print.html"><strong aria-hidden="true">1.2.</strong> Formatted print</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="hello/print/print_debug.html"><strong aria-hidden="true">1.2.1.</strong> Debug</a></li><li class="chapter-item "><a href="hello/print/print_display.html"><strong aria-hidden="true">1.2.2.</strong> Display</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="hello/print/print_display/testcase_list.html"><strong aria-hidden="true">1.2.2.1.</strong> Testcase: List</a></li></ol></li><li class="chapter-item "><a href="hello/print/fmt.html"><strong aria-hidden="true">1.2.3.</strong> Formatting</a></li></ol></li></ol></li><li class="chapter-item "><a href="primitives.html"><strong aria-hidden="true">2.</strong> Primitives</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="primitives/literals.html"><strong aria-hidden="true">2.1.</strong> Literals and operators</a></li><li class="chapter-item "><a href="primitives/tuples.html"><strong aria-hidden="true">2.2.</strong> Tuples</a></li><li class="chapter-item "><a href="primitives/array.html"><strong aria-hidden="true">2.3.</strong> Arrays and Slices</a></li></ol></li><li class="chapter-item "><a href="custom_types.html"><strong aria-hidden="true">3.</strong> Custom Types</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="custom_types/structs.html"><strong aria-hidden="true">3.1.</strong> Structures</a></li><li class="chapter-item "><a href="custom_types/enum.html"><strong aria-hidden="true">3.2.</strong> Enums</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="custom_types/enum/enum_use.html"><strong aria-hidden="true">3.2.1.</strong> use</a></li><li class="chapter-item "><a href="custom_types/enum/c_like.html"><strong aria-hidden="true">3.2.2.</strong> C-like</a></li><li class="chapter-item "><a href="custom_types/enum/testcase_linked_list.html"><strong aria-hidden="true">3.2.3.</strong> Testcase: linked-list</a></li></ol></li><li class="chapter-item "><a href="custom_types/constants.html"><strong aria-hidden="true">3.3.</strong> constants</a></li></ol></li><li class="chapter-item "><a href="variable_bindings.html"><strong aria-hidden="true">4.</strong> Variable Bindings</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="variable_bindings/mut.html"><strong aria-hidden="true">4.1.</strong> Mutability</a></li><li class="chapter-item "><a href="variable_bindings/scope.html"><strong aria-hidden="true">4.2.</strong> Scope and Shadowing</a></li><li class="chapter-item "><a href="variable_bindings/declare.html"><strong aria-hidden="true">4.3.</strong> Declare first</a></li><li class="chapter-item "><a href="variable_bindings/freeze.html"><strong aria-hidden="true">4.4.</strong> Freezing</a></li></ol></li><li class="chapter-item "><a href="types.html"><strong aria-hidden="true">5.</strong> Types</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="types/cast.html"><strong aria-hidden="true">5.1.</strong> Casting</a></li><li class="chapter-item "><a href="types/literals.html"><strong aria-hidden="true">5.2.</strong> Literals</a></li><li class="chapter-item "><a href="types/inference.html"><strong aria-hidden="true">5.3.</strong> Inference</a></li><li class="chapter-item "><a href="types/alias.html"><strong aria-hidden="true">5.4.</strong> Aliasing</a></li></ol></li><li class="chapter-item "><a href="conversion.html"><strong aria-hidden="true">6.</strong> Conversion</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="conversion/from_into.html"><strong aria-hidden="true">6.1.</strong> From and Into</a></li><li class="chapter-item "><a href="conversion/try_from_try_into.html"><strong aria-hidden="true">6.2.</strong> TryFrom and TryInto</a></li><li class="chapter-item "><a href="conversion/string.html"><strong aria-hidden="true">6.3.</strong> To and from Strings</a></li></ol></li><li class="chapter-item "><a href="expression.html"><strong aria-hidden="true">7.</strong> Expressions</a></li><li class="chapter-item "><a href="flow_control.html"><strong aria-hidden="true">8.</strong> Flow of Control</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="flow_control/if_else.html"><strong aria-hidden="true">8.1.</strong> if/else</a></li><li class="chapter-item "><a href="flow_control/loop.html"><strong aria-hidden="true">8.2.</strong> loop</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="flow_control/loop/nested.html"><strong aria-hidden="true">8.2.1.</strong> Nesting and labels</a></li><li class="chapter-item "><a href="flow_control/loop/return.html"><strong aria-hidden="true">8.2.2.</strong> Returning from loops</a></li></ol></li><li class="chapter-item "><a href="flow_control/while.html"><strong aria-hidden="true">8.3.</strong> while</a></li><li class="chapter-item "><a href="flow_control/for.html"><strong aria-hidden="true">8.4.</strong> for and range</a></li><li class="chapter-item "><a href="flow_control/match.html"><strong aria-hidden="true">8.5.</strong> match</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="flow_control/match/destructuring.html"><strong aria-hidden="true">8.5.1.</strong> Destructuring</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="flow_control/match/destructuring/destructure_tuple.html"><strong aria-hidden="true">8.5.1.1.</strong> tuples</a></li><li class="chapter-item "><a href="flow_control/match/destructuring/destructure_enum.html"><strong aria-hidden="true">8.5.1.2.</strong> enums</a></li><li class="chapter-item "><a href="flow_control/match/destructuring/destructure_pointers.html"><strong aria-hidden="true">8.5.1.3.</strong> pointers/ref</a></li><li class="chapter-item "><a href="flow_control/match/destructuring/destructure_structures.html"><strong aria-hidden="true">8.5.1.4.</strong> structs</a></li></ol></li><li class="chapter-item "><a href="flow_control/match/guard.html"><strong aria-hidden="true">8.5.2.</strong> Guards</a></li><li class="chapter-item "><a href="flow_control/match/binding.html"><strong aria-hidden="true">8.5.3.</strong> Binding</a></li></ol></li><li class="chapter-item "><a href="flow_control/if_let.html"><strong aria-hidden="true">8.6.</strong> if let</a></li><li class="chapter-item "><a href="flow_control/while_let.html"><strong aria-hidden="true">8.7.</strong> while let</a></li></ol></li><li class="chapter-item "><a href="fn.html"><strong aria-hidden="true">9.</strong> Functions</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="fn/methods.html"><strong aria-hidden="true">9.1.</strong> Methods</a></li><li class="chapter-item "><a href="fn/closures.html"><strong aria-hidden="true">9.2.</strong> Closures</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="fn/closures/capture.html"><strong aria-hidden="true">9.2.1.</strong> Capturing</a></li><li class="chapter-item "><a href="fn/closures/input_parameters.html"><strong aria-hidden="true">9.2.2.</strong> As input parameters</a></li><li class="chapter-item "><a href="fn/closures/anonymity.html"><strong aria-hidden="true">9.2.3.</strong> Type anonymity</a></li><li class="chapter-item "><a href="fn/closures/input_functions.html"><strong aria-hidden="true">9.2.4.</strong> Input functions</a></li><li class="chapter-item "><a href="fn/closures/output_parameters.html"><strong aria-hidden="true">9.2.5.</strong> As output parameters</a></li><li class="chapter-item "><a href="fn/closures/closure_examples.html"><strong aria-hidden="true">9.2.6.</strong> Examples in std</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="fn/closures/closure_examples/iter_any.html"><strong aria-hidden="true">9.2.6.1.</strong> Iterator::any</a></li><li class="chapter-item "><a href="fn/closures/closure_examples/iter_find.html"><strong aria-hidden="true">9.2.6.2.</strong> Searching through iterators</a></li></ol></li></ol></li><li class="chapter-item "><a href="fn/hof.html"><strong aria-hidden="true">9.3.</strong> Higher Order Functions</a></li><li class="chapter-item "><a href="fn/diverging.html"><strong aria-hidden="true">9.4.</strong> Diverging functions</a></li></ol></li><li class="chapter-item "><a href="mod.html"><strong aria-hidden="true">10.</strong> Modules</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="mod/visibility.html"><strong aria-hidden="true">10.1.</strong> Visibility</a></li><li class="chapter-item "><a href="mod/struct_visibility.html"><strong aria-hidden="true">10.2.</strong> Struct visibility</a></li><li class="chapter-item "><a href="mod/use.html"><strong aria-hidden="true">10.3.</strong> The use declaration</a></li><li class="chapter-item "><a href="mod/super.html"><strong aria-hidden="true">10.4.</strong> super and self</a></li><li class="chapter-item "><a href="mod/split.html"><strong aria-hidden="true">10.5.</strong> File hierarchy</a></li></ol></li><li class="chapter-item "><a href="crates.html"><strong aria-hidden="true">11.</strong> Crates</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="crates/lib.html"><strong aria-hidden="true">11.1.</strong> Creating a Library</a></li><li class="chapter-item "><a href="crates/using_lib.html"><strong aria-hidden="true">11.2.</strong> Using a Library</a></li></ol></li><li class="chapter-item "><a href="cargo.html"><strong aria-hidden="true">12.</strong> Cargo</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="cargo/deps.html"><strong aria-hidden="true">12.1.</strong> Dependencies</a></li><li class="chapter-item "><a href="cargo/conventions.html"><strong aria-hidden="true">12.2.</strong> Conventions</a></li><li class="chapter-item "><a href="cargo/test.html"><strong aria-hidden="true">12.3.</strong> Tests</a></li><li class="chapter-item "><a href="cargo/build_scripts.html"><strong aria-hidden="true">12.4.</strong> Build Scripts</a></li></ol></li><li class="chapter-item "><a href="attribute.html"><strong aria-hidden="true">13.</strong> Attributes</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="attribute/unused.html"><strong aria-hidden="true">13.1.</strong> dead_code</a></li><li class="chapter-item "><a href="attribute/crate.html"><strong aria-hidden="true">13.2.</strong> Crates</a></li><li class="chapter-item "><a href="attribute/cfg.html"><strong aria-hidden="true">13.3.</strong> cfg</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="attribute/cfg/custom.html"><strong aria-hidden="true">13.3.1.</strong> Custom</a></li></ol></li></ol></li><li class="chapter-item "><a href="generics.html"><strong aria-hidden="true">14.</strong> Generics</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="generics/gen_fn.html"><strong aria-hidden="true">14.1.</strong> Functions</a></li><li class="chapter-item "><a href="generics/impl.html"><strong aria-hidden="true">14.2.</strong> Implementation</a></li><li class="chapter-item "><a href="generics/gen_trait.html"><strong aria-hidden="true">14.3.</strong> Traits</a></li><li class="chapter-item "><a href="generics/bounds.html"><strong aria-hidden="true">14.4.</strong> Bounds</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="generics/bounds/testcase_empty.html"><strong aria-hidden="true">14.4.1.</strong> Testcase: empty bounds</a></li></ol></li><li class="chapter-item "><a href="generics/multi_bounds.html"><strong aria-hidden="true">14.5.</strong> Multiple bounds</a></li><li class="chapter-item "><a href="generics/where.html"><strong aria-hidden="true">14.6.</strong> Where clauses</a></li><li class="chapter-item "><a href="generics/new_types.html"><strong aria-hidden="true">14.7.</strong> New Type Idiom</a></li><li class="chapter-item "><a href="generics/assoc_items.html"><strong aria-hidden="true">14.8.</strong> Associated items</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="generics/assoc_items/the_problem.html"><strong aria-hidden="true">14.8.1.</strong> The Problem</a></li><li class="chapter-item "><a href="generics/assoc_items/types.html"><strong aria-hidden="true">14.8.2.</strong> Associated types</a></li></ol></li><li class="chapter-item "><a href="generics/phantom.html"><strong aria-hidden="true">14.9.</strong> Phantom type parameters</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="generics/phantom/testcase_units.html"><strong aria-hidden="true">14.9.1.</strong> Testcase: unit clarification</a></li></ol></li></ol></li><li class="chapter-item "><a href="scope.html"><strong aria-hidden="true">15.</strong> Scoping rules</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="scope/raii.html"><strong aria-hidden="true">15.1.</strong> RAII</a></li><li class="chapter-item "><a href="scope/move.html"><strong aria-hidden="true">15.2.</strong> Ownership and moves</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="scope/move/mut.html"><strong aria-hidden="true">15.2.1.</strong> Mutability</a></li><li class="chapter-item "><a href="scope/move/partial_move.html"><strong aria-hidden="true">15.2.2.</strong> Partial moves</a></li></ol></li><li class="chapter-item "><a href="scope/borrow.html"><strong aria-hidden="true">15.3.</strong> Borrowing</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="scope/borrow/mut.html"><strong aria-hidden="true">15.3.1.</strong> Mutability</a></li><li class="chapter-item "><a href="scope/borrow/alias.html"><strong aria-hidden="true">15.3.2.</strong> Aliasing</a></li><li class="chapter-item "><a href="scope/borrow/ref.html"><strong aria-hidden="true">15.3.3.</strong> The ref pattern</a></li></ol></li><li class="chapter-item "><a href="scope/lifetime.html"><strong aria-hidden="true">15.4.</strong> Lifetimes</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="scope/lifetime/explicit.html"><strong aria-hidden="true">15.4.1.</strong> Explicit annotation</a></li><li class="chapter-item "><a href="scope/lifetime/fn.html"><strong aria-hidden="true">15.4.2.</strong> Functions</a></li><li class="chapter-item "><a href="scope/lifetime/methods.html"><strong aria-hidden="true">15.4.3.</strong> Methods</a></li><li class="chapter-item "><a href="scope/lifetime/struct.html"><strong aria-hidden="true">15.4.4.</strong> Structs</a></li><li class="chapter-item "><a href="scope/lifetime/trait.html"><strong aria-hidden="true">15.4.5.</strong> Traits</a></li><li class="chapter-item "><a href="scope/lifetime/lifetime_bounds.html"><strong aria-hidden="true">15.4.6.</strong> Bounds</a></li><li class="chapter-item "><a href="scope/lifetime/lifetime_coercion.html"><strong aria-hidden="true">15.4.7.</strong> Coercion</a></li><li class="chapter-item "><a href="scope/lifetime/static_lifetime.html"><strong aria-hidden="true">15.4.8.</strong> Static</a></li><li class="chapter-item "><a href="scope/lifetime/elision.html"><strong aria-hidden="true">15.4.9.</strong> Elision</a></li></ol></li></ol></li><li class="chapter-item "><a href="trait.html"><strong aria-hidden="true">16.</strong> Traits</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="trait/derive.html"><strong aria-hidden="true">16.1.</strong> Derive</a></li><li class="chapter-item "><a href="trait/dyn.html"><strong aria-hidden="true">16.2.</strong> Returning Traits with dyn</a></li><li class="chapter-item "><a href="trait/ops.html"><strong aria-hidden="true">16.3.</strong> Operator Overloading</a></li><li class="chapter-item "><a href="trait/drop.html"><strong aria-hidden="true">16.4.</strong> Drop</a></li><li class="chapter-item "><a href="trait/iter.html"><strong aria-hidden="true">16.5.</strong> Iterators</a></li><li class="chapter-item "><a href="trait/impl_trait.html"><strong aria-hidden="true">16.6.</strong> impl Trait</a></li><li class="chapter-item "><a href="trait/clone.html"><strong aria-hidden="true">16.7.</strong> Clone</a></li><li class="chapter-item "><a href="trait/supertraits.html"><strong aria-hidden="true">16.8.</strong> Supertraits</a></li><li class="chapter-item "><a href="trait/disambiguating.html"><strong aria-hidden="true">16.9.</strong> Disambiguating overlapping traits</a></li></ol></li><li class="chapter-item "><a href="macros.html"><strong aria-hidden="true">17.</strong> macro_rules!</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="macros/syntax.html"><strong aria-hidden="true">17.1.</strong> Syntax</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="macros/designators.html"><strong aria-hidden="true">17.1.1.</strong> Designators</a></li><li class="chapter-item "><a href="macros/overload.html"><strong aria-hidden="true">17.1.2.</strong> Overload</a></li><li class="chapter-item "><a href="macros/repeat.html"><strong aria-hidden="true">17.1.3.</strong> Repeat</a></li></ol></li><li class="chapter-item "><a href="macros/dry.html"><strong aria-hidden="true">17.2.</strong> DRY (Don't Repeat Yourself)</a></li><li class="chapter-item "><a href="macros/dsl.html"><strong aria-hidden="true">17.3.</strong> DSL (Domain Specific Languages)</a></li><li class="chapter-item "><a href="macros/variadics.html"><strong aria-hidden="true">17.4.</strong> Variadics</a></li></ol></li><li class="chapter-item "><a href="error.html"><strong aria-hidden="true">18.</strong> Error handling</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="error/panic.html"><strong aria-hidden="true">18.1.</strong> panic</a></li><li class="chapter-item "><a href="error/option_unwrap.html"><strong aria-hidden="true">18.2.</strong> Option & unwrap</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="error/option_unwrap/question_mark.html"><strong aria-hidden="true">18.2.1.</strong> Unpacking options with ?</a></li><li class="chapter-item "><a href="error/option_unwrap/map.html"><strong aria-hidden="true">18.2.2.</strong> Combinators: map</a></li><li class="chapter-item "><a href="error/option_unwrap/and_then.html"><strong aria-hidden="true">18.2.3.</strong> Combinators: and_then</a></li></ol></li><li class="chapter-item "><a href="error/result.html"><strong aria-hidden="true">18.3.</strong> Result</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="error/result/result_map.html"><strong aria-hidden="true">18.3.1.</strong> map for Result</a></li><li class="chapter-item "><a href="error/result/result_alias.html"><strong aria-hidden="true">18.3.2.</strong> aliases for Result</a></li><li class="chapter-item "><a href="error/result/early_returns.html"><strong aria-hidden="true">18.3.3.</strong> Early returns</a></li><li class="chapter-item "><a href="error/result/enter_question_mark.html"><strong aria-hidden="true">18.3.4.</strong> Introducing ?</a></li></ol></li><li class="chapter-item "><a href="error/multiple_error_types.html"><strong aria-hidden="true">18.4.</strong> Multiple error types</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="error/multiple_error_types/option_result.html"><strong aria-hidden="true">18.4.1.</strong> Pulling Results out of Options</a></li><li class="chapter-item "><a href="error/multiple_error_types/define_error_type.html"><strong aria-hidden="true">18.4.2.</strong> Defining an error type</a></li><li class="chapter-item "><a href="error/multiple_error_types/boxing_errors.html"><strong aria-hidden="true">18.4.3.</strong> Boxing errors</a></li><li class="chapter-item "><a href="error/multiple_error_types/reenter_question_mark.html"><strong aria-hidden="true">18.4.4.</strong> Other uses of ?</a></li><li class="chapter-item "><a href="error/multiple_error_types/wrap_error.html"><strong aria-hidden="true">18.4.5.</strong> Wrapping errors</a></li></ol></li><li class="chapter-item "><a href="error/iter_result.html"><strong aria-hidden="true">18.5.</strong> Iterating over Results</a></li></ol></li><li class="chapter-item "><a href="std.html"><strong aria-hidden="true">19.</strong> Std library types</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="std/box.html"><strong aria-hidden="true">19.1.</strong> Box, stack and heap</a></li><li class="chapter-item "><a href="std/vec.html"><strong aria-hidden="true">19.2.</strong> Vectors</a></li><li class="chapter-item "><a href="std/str.html"><strong aria-hidden="true">19.3.</strong> Strings</a></li><li class="chapter-item "><a href="std/option.html"><strong aria-hidden="true">19.4.</strong> Option</a></li><li class="chapter-item "><a href="std/result.html"><strong aria-hidden="true">19.5.</strong> Result</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="std/result/question_mark.html"><strong aria-hidden="true">19.5.1.</strong> ?</a></li></ol></li><li class="chapter-item "><a href="std/panic.html"><strong aria-hidden="true">19.6.</strong> panic!</a></li><li class="chapter-item "><a href="std/hash.html"><strong aria-hidden="true">19.7.</strong> HashMap</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="std/hash/alt_key_types.html"><strong aria-hidden="true">19.7.1.</strong> Alternate/custom key types</a></li><li class="chapter-item "><a href="std/hash/hashset.html"><strong aria-hidden="true">19.7.2.</strong> HashSet</a></li></ol></li><li class="chapter-item "><a href="std/rc.html"><strong aria-hidden="true">19.8.</strong> Rc</a></li><li class="chapter-item "><a href="std/arc.html"><strong aria-hidden="true">19.9.</strong> Arc</a></li></ol></li><li class="chapter-item "><a href="std_misc.html"><strong aria-hidden="true">20.</strong> Std misc</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="std_misc/threads.html"><strong aria-hidden="true">20.1.</strong> Threads</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="std_misc/threads/testcase_mapreduce.html"><strong aria-hidden="true">20.1.1.</strong> Testcase: map-reduce</a></li></ol></li><li class="chapter-item "><a href="std_misc/channels.html"><strong aria-hidden="true">20.2.</strong> Channels</a></li><li class="chapter-item "><a href="std_misc/path.html"><strong aria-hidden="true">20.3.</strong> Path</a></li><li class="chapter-item "><a href="std_misc/file.html"><strong aria-hidden="true">20.4.</strong> File I/O</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="std_misc/file/open.html"><strong aria-hidden="true">20.4.1.</strong> open</a></li><li class="chapter-item "><a href="std_misc/file/create.html"><strong aria-hidden="true">20.4.2.</strong> create</a></li><li class="chapter-item "><a href="std_misc/file/read_lines.html"><strong aria-hidden="true">20.4.3.</strong> read lines</a></li></ol></li><li class="chapter-item "><a href="std_misc/process.html"><strong aria-hidden="true">20.5.</strong> Child processes</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="std_misc/process/pipe.html"><strong aria-hidden="true">20.5.1.</strong> Pipes</a></li><li class="chapter-item "><a href="std_misc/process/wait.html"><strong aria-hidden="true">20.5.2.</strong> Wait</a></li></ol></li><li class="chapter-item "><a href="std_misc/fs.html"><strong aria-hidden="true">20.6.</strong> Filesystem Operations</a></li><li class="chapter-item "><a href="std_misc/arg.html"><strong aria-hidden="true">20.7.</strong> Program arguments</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="std_misc/arg/matching.html"><strong aria-hidden="true">20.7.1.</strong> Argument parsing</a></li></ol></li><li class="chapter-item "><a href="std_misc/ffi.html"><strong aria-hidden="true">20.8.</strong> Foreign Function Interface</a></li></ol></li><li class="chapter-item "><a href="testing.html"><strong aria-hidden="true">21.</strong> Testing</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="testing/unit_testing.html"><strong aria-hidden="true">21.1.</strong> Unit testing</a></li><li class="chapter-item "><a href="testing/doc_testing.html"><strong aria-hidden="true">21.2.</strong> Documentation testing</a></li><li class="chapter-item "><a href="testing/integration_testing.html"><strong aria-hidden="true">21.3.</strong> Integration testing</a></li><li class="chapter-item "><a href="testing/dev_dependencies.html"><strong aria-hidden="true">21.4.</strong> Dev-dependencies</a></li></ol></li><li class="chapter-item "><a href="unsafe.html"><strong aria-hidden="true">22.</strong> Unsafe Operations</a></li><li class="chapter-item "><a href="compatibility.html"><strong aria-hidden="true">23.</strong> Compatibility</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="compatibility/raw_identifiers.html"><strong aria-hidden="true">23.1.</strong> Raw identifiers</a></li></ol></li><li class="chapter-item "><a href="meta.html"><strong aria-hidden="true">24.</strong> Meta</a><a class="toggle"><div>❱</div></a></li><li><ol class="section"><li class="chapter-item "><a href="meta/doc.html"><strong aria-hidden="true">24.1.</strong> Documentation</a></li><li class="chapter-item "><a href="meta/playpen.html"><strong aria-hidden="true">24.2.</strong> Playpen</a></li></ol></li></ol> |
| </div> |
| <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> |
| </nav> |
| |
| <div id="page-wrapper" class="page-wrapper"> |
| |
| <div class="page"> |
| |
| <div id="menu-bar-hover-placeholder"></div> |
| <div id="menu-bar" class="menu-bar sticky bordered"> |
| <div class="left-buttons"> |
| <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> |
| <i class="fa fa-bars"></i> |
| </button> |
| <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list"> |
| <i class="fa fa-paint-brush"></i> |
| </button> |
| <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu"> |
| <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li> |
| </ul> |
| <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar"> |
| <i class="fa fa-search"></i> |
| </button> |
| </div> |
| |
| <h1 class="menu-title">Rust By Example</h1> |
| |
| <div class="right-buttons"> |
| <a href="print.html" title="Print this book" aria-label="Print this book"> |
| <i id="print-button" class="fa fa-print"></i> |
| </a> |
| </div> |
| </div> |
| |
| <div id="search-wrapper" class="hidden"> |
| <form id="searchbar-outer" class="searchbar-outer"> |
| <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header"> |
| </form> |
| <div id="searchresults-outer" class="searchresults-outer hidden"> |
| <div id="searchresults-header" class="searchresults-header"></div> |
| <ul id="searchresults"> |
| </ul> |
| </div> |
| </div> |
| <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM --> |
| <script type="text/javascript"> |
| document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); |
| document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); |
| Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) { |
| link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1); |
| }); |
| </script> |
| |
| <div id="content" class="content"> |
| <main> |
| <h1 id="rust-by-example"><a class="header" href="#rust-by-example">Rust by Example</a></h1> |
| <p><a href="https://www.rust-lang.org/">Rust</a> is a modern systems programming language focusing on safety, speed, |
| and concurrency. It accomplishes these goals by being memory safe without using |
| garbage collection.</p> |
| <p>Rust by Example (RBE) is a collection of runnable examples that illustrate various Rust |
| concepts and standard libraries. To get even more out of these examples, don't forget |
| to <a href="https://www.rust-lang.org/tools/install">install Rust locally</a> and check out the <a href="https://doc.rust-lang.org/std/">official docs</a>. |
| Additionally for the curious, you can also <a href="https://github.com/rust-lang/rust-by-example">check out the source code for this site</a>.</p> |
| <p>Now let's begin!</p> |
| <ul> |
| <li> |
| <p><a href="hello.html">Hello World</a> - Start with a traditional Hello World program.</p> |
| </li> |
| <li> |
| <p><a href="primitives.html">Primitives</a> - Learn about signed integers, unsigned integers and other primitives.</p> |
| </li> |
| <li> |
| <p><a href="custom_types.html">Custom Types</a> - <code>struct</code> and <code>enum</code>.</p> |
| </li> |
| <li> |
| <p><a href="variable_bindings.html">Variable Bindings</a> - mutable bindings, scope, shadowing.</p> |
| </li> |
| <li> |
| <p><a href="types.html">Types</a> - Learn about changing and defining types.</p> |
| </li> |
| <li> |
| <p><a href="conversion.html">Conversion</a></p> |
| </li> |
| <li> |
| <p><a href="expression.html">Expressions</a></p> |
| </li> |
| <li> |
| <p><a href="flow_control.html">Flow of Control</a> - <code>if</code>/<code>else</code>, <code>for</code>, and others.</p> |
| </li> |
| <li> |
| <p><a href="fn.html">Functions</a> - Learn about Methods, Closures and High Order Functions.</p> |
| </li> |
| <li> |
| <p><a href="mod.html">Modules</a> - Organize code using modules</p> |
| </li> |
| <li> |
| <p><a href="crates.html">Crates</a> - A crate is a compilation unit in Rust. Learn to create a library.</p> |
| </li> |
| <li> |
| <p><a href="cargo.html">Cargo</a> - Go through some basic features of the official Rust package management tool.</p> |
| </li> |
| <li> |
| <p><a href="attribute.html">Attributes</a> - An attribute is metadata applied to some module, crate or item.</p> |
| </li> |
| <li> |
| <p><a href="generics.html">Generics</a> - Learn about writing a function or data type which can work for multiple types of arguments.</p> |
| </li> |
| <li> |
| <p><a href="scope.html">Scoping rules</a> - Scopes play an important part in ownership, borrowing, and lifetimes.</p> |
| </li> |
| <li> |
| <p><a href="trait.html">Traits</a> - A trait is a collection of methods defined for an unknown type: <code>Self</code></p> |
| </li> |
| <li> |
| <p><a href="macros.html">Macros</a></p> |
| </li> |
| <li> |
| <p><a href="error.html">Error handling</a> - Learn Rust way of handling failures.</p> |
| </li> |
| <li> |
| <p><a href="std.html">Std library types</a> - Learn about some custom types provided by <code>std</code> library.</p> |
| </li> |
| <li> |
| <p><a href="std_misc.html">Std misc</a> - More custom types for file handling, threads.</p> |
| </li> |
| <li> |
| <p><a href="testing.html">Testing</a> - All sorts of testing in Rust.</p> |
| </li> |
| <li> |
| <p><a href="unsafe.html">Unsafe Operations</a></p> |
| </li> |
| <li> |
| <p><a href="compatibility.html">Compatibility</a></p> |
| </li> |
| <li> |
| <p><a href="meta.html">Meta</a> - Documentation, Benchmarking.</p> |
| </li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="hello-world"><a class="header" href="#hello-world">Hello World</a></h1> |
| <p>This is the source code of the traditional Hello World program.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// This is a comment, and is ignored by the compiler |
| // You can test this code by clicking the "Run" button over there -> |
| // or if you prefer to use your keyboard, you can use the "Ctrl + Enter" shortcut |
| |
| // This code is editable, feel free to hack it! |
| // You can always return to the original code by clicking the "Reset" button -> |
| |
| // This is the main function |
| fn main() { |
| // Statements here are executed when the compiled binary is called |
| |
| // Print text to the console |
| println!("Hello World!"); |
| } |
| </code></pre></pre> |
| <p><code>println!</code> is a <a href="macros.html"><em>macro</em></a> that prints text to the |
| console.</p> |
| <p>A binary can be generated using the Rust compiler: <code>rustc</code>.</p> |
| <pre><code class="language-bash">$ rustc hello.rs |
| </code></pre> |
| <p><code>rustc</code> will produce a <code>hello</code> binary that can be executed.</p> |
| <pre><code class="language-bash">$ ./hello |
| Hello World! |
| </code></pre> |
| <h3 id="activity"><a class="header" href="#activity">Activity</a></h3> |
| <p>Click 'Run' above to see the expected output. Next, add a new |
| line with a second <code>println!</code> macro so that the output |
| shows:</p> |
| <pre><code class="language-text">Hello World! |
| I'm a Rustacean! |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="comments"><a class="header" href="#comments">Comments</a></h1> |
| <p>Any program requires comments, and Rust supports |
| a few different varieties:</p> |
| <ul> |
| <li><em>Regular comments</em> which are ignored by the compiler: |
| <ul> |
| <li><code>// Line comments which go to the end of the line.</code></li> |
| <li><code>/* Block comments which go to the closing delimiter. */</code></li> |
| </ul> |
| </li> |
| <li><em>Doc comments</em> which are parsed into HTML library |
| <a href="hello/../meta/doc.html">documentation</a>: |
| <ul> |
| <li><code>/// Generate library docs for the following item.</code></li> |
| <li><code>//! Generate library docs for the enclosing item.</code></li> |
| </ul> |
| </li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // This is an example of a line comment |
| // There are two slashes at the beginning of the line |
| // And nothing written inside these will be read by the compiler |
| |
| // println!("Hello, world!"); |
| |
| // Run it. See? Now try deleting the two slashes, and run it again. |
| |
| /* |
| * This is another type of comment, a block comment. In general, |
| * line comments are the recommended comment style. But |
| * block comments are extremely useful for temporarily disabling |
| * chunks of code. /* Block comments can be /* nested, */ */ |
| * so it takes only a few keystrokes to comment out everything |
| * in this main() function. /*/*/* Try it yourself! */*/*/ |
| */ |
| |
| /* |
| Note: The previous column of `*` was entirely for style. There's |
| no actual need for it. |
| */ |
| |
| // You can manipulate expressions more easily with block comments |
| // than with line comments. Try deleting the comment delimiters |
| // to change the result: |
| let x = 5 + /* 90 + */ 5; |
| println!("Is `x` 10 or 100? x = {}", x); |
| } |
| |
| </code></pre></pre> |
| <h3 id="see-also"><a class="header" href="#see-also">See also:</a></h3> |
| <p><a href="hello/../meta/doc.html">Library documentation</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="formatted-print"><a class="header" href="#formatted-print">Formatted print</a></h1> |
| <p>Printing is handled by a series of <a href="hello/../macros.html"><code>macros</code></a> defined in <a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a> |
| some of which include:</p> |
| <ul> |
| <li><code>format!</code>: write formatted text to <a href="hello/../std/str.html"><code>String</code></a></li> |
| <li><code>print!</code>: same as <code>format!</code> but the text is printed to the console (io::stdout).</li> |
| <li><code>println!</code>: same as <code>print!</code> but a newline is appended.</li> |
| <li><code>eprint!</code>: same as <code>format!</code> but the text is printed to the standard error (io::stderr).</li> |
| <li><code>eprintln!</code>: same as <code>eprint!</code>but a newline is appended.</li> |
| </ul> |
| <p>All parse text in the same fashion. As a plus, Rust checks formatting |
| correctness at compile time.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn main() { |
| // In general, the `{}` will be automatically replaced with any |
| // arguments. These will be stringified. |
| println!("{} days", 31); |
| |
| // Without a suffix, 31 becomes an i32. You can change what type 31 is |
| // by providing a suffix. The number 31i64 for example has the type i64. |
| |
| // There are various optional patterns this works with. Positional |
| // arguments can be used. |
| println!("{0}, this is {1}. {1}, this is {0}", "Alice", "Bob"); |
| |
| // As can named arguments. |
| println!("{subject} {verb} {object}", |
| object="the lazy dog", |
| subject="the quick brown fox", |
| verb="jumps over"); |
| |
| // Special formatting can be specified after a `:`. |
| println!("{} of {:b} people know binary, the other half doesn't", 1, 2); |
| |
| // You can right-align text with a specified width. This will output |
| // " 1". 5 white spaces and a "1". |
| println!("{number:>width$}", number=1, width=6); |
| |
| // You can pad numbers with extra zeroes. This will output "000001". |
| println!("{number:0>width$}", number=1, width=6); |
| |
| // Rust even checks to make sure the correct number of arguments are |
| // used. |
| println!("My name is {0}, {1} {0}", "Bond"); |
| // FIXME ^ Add the missing argument: "James" |
| |
| // Create a structure named `Structure` which contains an `i32`. |
| #[allow(dead_code)] |
| struct Structure(i32); |
| |
| // However, custom types such as this structure require more complicated |
| // handling. This will not work. |
| println!("This struct `{}` won't print...", Structure(3)); |
| // FIXME ^ Comment out this line. |
| } |
| </code></pre></pre> |
| <p><a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a> contains many <a href="https://doc.rust-lang.org/std/fmt/#formatting-traits"><code>traits</code></a> which govern the display |
| of text. The base form of two important ones are listed below:</p> |
| <ul> |
| <li><code>fmt::Debug</code>: Uses the <code>{:?}</code> marker. Format text for debugging purposes.</li> |
| <li><code>fmt::Display</code>: Uses the <code>{}</code> marker. Format text in a more elegant, user |
| friendly fashion.</li> |
| </ul> |
| <p>Here, we used <code>fmt::Display</code> because the std library provides implementations |
| for these types. To print text for custom types, more steps are required.</p> |
| <p>Implementing the <code>fmt::Display</code> trait automatically implements the |
| <a href="https://doc.rust-lang.org/std/string/trait.ToString.html"><code>ToString</code></a> trait which allows us to <a href="hello/../conversion/string.html">convert</a> the type to <a href="hello/../std/str.html"><code>String</code></a>.</p> |
| <h3 id="activities"><a class="header" href="#activities">Activities</a></h3> |
| <ul> |
| <li>Fix the two issues in the above code (see FIXME) so that it runs without |
| error.</li> |
| <li>Add a <code>println!</code> macro that prints: <code>Pi is roughly 3.142</code> by controlling |
| the number of decimal places shown. For the purposes of this exercise, |
| use <code>let pi = 3.141592</code> as an estimate for pi. (Hint: you may need to |
| check the <a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a> documentation for setting the number of |
| decimals to display)</li> |
| </ul> |
| <h3 id="see-also-1"><a class="header" href="#see-also-1">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a>, <a href="hello/../macros.html"><code>macros</code></a>, <a href="hello/../custom_types/structs.html"><code>struct</code></a>, |
| and <a href="https://doc.rust-lang.org/std/fmt/#formatting-traits"><code>traits</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="debug"><a class="header" href="#debug">Debug</a></h1> |
| <p>All types which want to use <code>std::fmt</code> formatting <code>traits</code> require an |
| implementation to be printable. Automatic implementations are only provided |
| for types such as in the <code>std</code> library. All others <em>must</em> be manually |
| implemented somehow.</p> |
| <p>The <code>fmt::Debug</code> <code>trait</code> makes this very straightforward. <em>All</em> types can |
| <code>derive</code> (automatically create) the <code>fmt::Debug</code> implementation. This is |
| not true for <code>fmt::Display</code> which must be manually implemented.</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>// This structure cannot be printed either with `fmt::Display` or |
| // with `fmt::Debug`. |
| struct UnPrintable(i32); |
| |
| // The `derive` attribute automatically creates the implementation |
| // required to make this `struct` printable with `fmt::Debug`. |
| #[derive(Debug)] |
| struct DebugPrintable(i32); |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p>All <code>std</code> library types are automatically printable with <code>{:?}</code> too:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Derive the `fmt::Debug` implementation for `Structure`. `Structure` |
| // is a structure which contains a single `i32`. |
| #[derive(Debug)] |
| struct Structure(i32); |
| |
| // Put a `Structure` inside of the structure `Deep`. Make it printable |
| // also. |
| #[derive(Debug)] |
| struct Deep(Structure); |
| |
| fn main() { |
| // Printing with `{:?}` is similar to with `{}`. |
| println!("{:?} months in a year.", 12); |
| println!("{1:?} {0:?} is the {actor:?} name.", |
| "Slater", |
| "Christian", |
| actor="actor's"); |
| |
| // `Structure` is printable! |
| println!("Now {:?} will print!", Structure(3)); |
| |
| // The problem with `derive` is there is no control over how |
| // the results look. What if I want this to just show a `7`? |
| println!("Now {:?} will print!", Deep(Structure(7))); |
| } |
| </code></pre></pre> |
| <p>So <code>fmt::Debug</code> definitely makes this printable but sacrifices some |
| elegance. Rust also provides "pretty printing" with <code>{:#?}</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">#[derive(Debug)] |
| struct Person<'a> { |
| name: &'a str, |
| age: u8 |
| } |
| |
| fn main() { |
| let name = "Peter"; |
| let age = 27; |
| let peter = Person { name, age }; |
| |
| // Pretty print |
| println!("{:#?}", peter); |
| } |
| </code></pre></pre> |
| <p>One can manually implement <code>fmt::Display</code> to control the display.</p> |
| <h3 id="see-also-2"><a class="header" href="#see-also-2">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/reference/attributes.html"><code>attributes</code></a>, <a href="hello/print/../../trait/derive.html"><code>derive</code></a>, <a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a>, |
| and <a href="hello/print/../../custom_types/structs.html"><code>struct</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="display"><a class="header" href="#display">Display</a></h1> |
| <p><code>fmt::Debug</code> hardly looks compact and clean, so it is often advantageous to |
| customize the output appearance. This is done by manually implementing |
| <a href="https://doc.rust-lang.org/std/fmt/"><code>fmt::Display</code></a>, which uses the <code>{}</code> print marker. Implementing it |
| looks like this:</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>// Import (via `use`) the `fmt` module to make it available. |
| use std::fmt; |
| |
| // Define a structure for which `fmt::Display` will be implemented. This is |
| // a tuple struct named `Structure` that contains an `i32`. |
| struct Structure(i32); |
| |
| // To use the `{}` marker, the trait `fmt::Display` must be implemented |
| // manually for the type. |
| impl fmt::Display for Structure { |
| // This trait requires `fmt` with this exact signature. |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| // Write strictly the first element into the supplied output |
| // stream: `f`. Returns `fmt::Result` which indicates whether the |
| // operation succeeded or failed. Note that `write!` uses syntax which |
| // is very similar to `println!`. |
| write!(f, "{}", self.0) |
| } |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p><code>fmt::Display</code> may be cleaner than <code>fmt::Debug</code> but this presents |
| a problem for the <code>std</code> library. How should ambiguous types be displayed? |
| For example, if the <code>std</code> library implemented a single style for all |
| <code>Vec<T></code>, what style should it be? Would it be either of these two?</p> |
| <ul> |
| <li><code>Vec<path></code>: <code>/:/etc:/home/username:/bin</code> (split on <code>:</code>)</li> |
| <li><code>Vec<number></code>: <code>1,2,3</code> (split on <code>,</code>)</li> |
| </ul> |
| <p>No, because there is no ideal style for all types and the <code>std</code> library |
| doesn't presume to dictate one. <code>fmt::Display</code> is not implemented for <code>Vec<T></code> |
| or for any other generic containers. <code>fmt::Debug</code> must then be used for these |
| generic cases.</p> |
| <p>This is not a problem though because for any new <em>container</em> type which is |
| <em>not</em> generic,<code>fmt::Display</code> can be implemented.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::fmt; // Import `fmt` |
| |
| // A structure holding two numbers. `Debug` will be derived so the results can |
| // be contrasted with `Display`. |
| #[derive(Debug)] |
| struct MinMax(i64, i64); |
| |
| // Implement `Display` for `MinMax`. |
| impl fmt::Display for MinMax { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| // Use `self.number` to refer to each positional data point. |
| write!(f, "({}, {})", self.0, self.1) |
| } |
| } |
| |
| // Define a structure where the fields are nameable for comparison. |
| #[derive(Debug)] |
| struct Point2D { |
| x: f64, |
| y: f64, |
| } |
| |
| // Similarly, implement `Display` for `Point2D` |
| impl fmt::Display for Point2D { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| // Customize so only `x` and `y` are denoted. |
| write!(f, "x: {}, y: {}", self.x, self.y) |
| } |
| } |
| |
| fn main() { |
| let minmax = MinMax(0, 14); |
| |
| println!("Compare structures:"); |
| println!("Display: {}", minmax); |
| println!("Debug: {:?}", minmax); |
| |
| let big_range = MinMax(-300, 300); |
| let small_range = MinMax(-3, 3); |
| |
| println!("The big range is {big} and the small is {small}", |
| small = small_range, |
| big = big_range); |
| |
| let point = Point2D { x: 3.3, y: 7.2 }; |
| |
| println!("Compare points:"); |
| println!("Display: {}", point); |
| println!("Debug: {:?}", point); |
| |
| // Error. Both `Debug` and `Display` were implemented, but `{:b}` |
| // requires `fmt::Binary` to be implemented. This will not work. |
| // println!("What does Point2D look like in binary: {:b}?", point); |
| } |
| </code></pre></pre> |
| <p>So, <code>fmt::Display</code> has been implemented but <code>fmt::Binary</code> has not, and |
| therefore cannot be used. <code>std::fmt</code> has many such <a href="https://doc.rust-lang.org/std/fmt/#formatting-traits"><code>traits</code></a> and |
| each requires its own implementation. This is detailed further in |
| <a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a>.</p> |
| <h3 id="activity-1"><a class="header" href="#activity-1">Activity</a></h3> |
| <p>After checking the output of the above example, use the <code>Point2D</code> struct as a |
| guide to add a <code>Complex</code> struct to the example. When printed in the same |
| way, the output should be:</p> |
| <pre><code class="language-txt">Display: 3.3 + 7.2i |
| Debug: Complex { real: 3.3, imag: 7.2 } |
| </code></pre> |
| <h3 id="see-also-3"><a class="header" href="#see-also-3">See also:</a></h3> |
| <p><a href="hello/print/../../trait/derive.html"><code>derive</code></a>, <a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a>, <a href="hello/print/../../macros.html"><code>macros</code></a>, <a href="hello/print/../../custom_types/structs.html"><code>struct</code></a>, |
| <a href="https://doc.rust-lang.org/std/fmt/#formatting-traits"><code>trait</code></a>, and <a href="hello/print/../../mod/use.html"><code>use</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="testcase-list"><a class="header" href="#testcase-list">Testcase: List</a></h1> |
| <p>Implementing <code>fmt::Display</code> for a structure where the elements must each be |
| handled sequentially is tricky. The problem is that each <code>write!</code> generates a |
| <code>fmt::Result</code>. Proper handling of this requires dealing with <em>all</em> the |
| results. Rust provides the <code>?</code> operator for exactly this purpose.</p> |
| <p>Using <code>?</code> on <code>write!</code> looks like this:</p> |
| <pre><code class="language-rust ignore">// Try `write!` to see if it errors. If it errors, return |
| // the error. Otherwise continue. |
| write!(f, "{}", value)?; |
| </code></pre> |
| <p>With <code>?</code> available, implementing <code>fmt::Display</code> for a <code>Vec</code> is |
| straightforward:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::fmt; // Import the `fmt` module. |
| |
| // Define a structure named `List` containing a `Vec`. |
| struct List(Vec<i32>); |
| |
| impl fmt::Display for List { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| // Extract the value using tuple indexing, |
| // and create a reference to `vec`. |
| let vec = &self.0; |
| |
| write!(f, "[")?; |
| |
| // Iterate over `v` in `vec` while enumerating the iteration |
| // count in `count`. |
| for (count, v) in vec.iter().enumerate() { |
| // For every element except the first, add a comma. |
| // Use the ? operator to return on errors. |
| if count != 0 { write!(f, ", ")?; } |
| write!(f, "{}", v)?; |
| } |
| |
| // Close the opened bracket and return a fmt::Result value. |
| write!(f, "]") |
| } |
| } |
| |
| fn main() { |
| let v = List(vec![1, 2, 3]); |
| println!("{}", v); |
| } |
| </code></pre></pre> |
| <h3 id="activity-2"><a class="header" href="#activity-2">Activity</a></h3> |
| <p>Try changing the program so that the index of each element in the vector is also printed. The new output should look like this:</p> |
| <pre><code class="language-rust ignore">[0: 1, 1: 2, 2: 3] |
| </code></pre> |
| <h3 id="see-also-4"><a class="header" href="#see-also-4">See also:</a></h3> |
| <p><a href="hello/print/print_display/../../../flow_control/for.html"><code>for</code></a>, <a href="hello/print/print_display/../../../scope/borrow/ref.html"><code>ref</code></a>, <a href="hello/print/print_display/../../../std/result.html"><code>Result</code></a>, <a href="hello/print/print_display/../../../custom_types/structs.html"><code>struct</code></a>, |
| <a href="hello/print/print_display/../../../std/result/question_mark.html"><code>?</code></a>, and <a href="hello/print/print_display/../../../std/vec.html"><code>vec!</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="formatting"><a class="header" href="#formatting">Formatting</a></h1> |
| <p>We've seen that formatting is specified via a <em>format string</em>:</p> |
| <ul> |
| <li><code>format!("{}", foo)</code> -> <code>"3735928559"</code></li> |
| <li><code>format!("0x{:X}", foo)</code> -> |
| <a href="https://en.wikipedia.org/wiki/Deadbeef#Magic_debug_values"><code>"0xDEADBEEF"</code></a></li> |
| <li><code>format!("0o{:o}", foo)</code> -> <code>"0o33653337357"</code></li> |
| </ul> |
| <p>The same variable (<code>foo</code>) can be formatted differently depending on which |
| <em>argument type</em> is used: <code>X</code> vs <code>o</code> vs <em>unspecified</em>.</p> |
| <p>This formatting functionality is implemented via traits, and there is one trait |
| for each argument type. The most common formatting trait is <code>Display</code>, which |
| handles cases where the argument type is left unspecified: <code>{}</code> for instance.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::fmt::{self, Formatter, Display}; |
| |
| struct City { |
| name: &'static str, |
| // Latitude |
| lat: f32, |
| // Longitude |
| lon: f32, |
| } |
| |
| impl Display for City { |
| // `f` is a buffer, and this method must write the formatted string into it |
| fn fmt(&self, f: &mut Formatter) -> fmt::Result { |
| let lat_c = if self.lat >= 0.0 { 'N' } else { 'S' }; |
| let lon_c = if self.lon >= 0.0 { 'E' } else { 'W' }; |
| |
| // `write!` is like `format!`, but it will write the formatted string |
| // into a buffer (the first argument) |
| write!(f, "{}: {:.3}°{} {:.3}°{}", |
| self.name, self.lat.abs(), lat_c, self.lon.abs(), lon_c) |
| } |
| } |
| |
| #[derive(Debug)] |
| struct Color { |
| red: u8, |
| green: u8, |
| blue: u8, |
| } |
| |
| fn main() { |
| for city in [ |
| City { name: "Dublin", lat: 53.347778, lon: -6.259722 }, |
| City { name: "Oslo", lat: 59.95, lon: 10.75 }, |
| City { name: "Vancouver", lat: 49.25, lon: -123.1 }, |
| ].iter() { |
| println!("{}", *city); |
| } |
| for color in [ |
| Color { red: 128, green: 255, blue: 90 }, |
| Color { red: 0, green: 3, blue: 254 }, |
| Color { red: 0, green: 0, blue: 0 }, |
| ].iter() { |
| // Switch this to use {} once you've added an implementation |
| // for fmt::Display. |
| println!("{:?}", *color); |
| } |
| } |
| </code></pre></pre> |
| <p>You can view a <a href="https://doc.rust-lang.org/std/fmt/#formatting-traits">full list of formatting traits</a> and their argument |
| types in the <a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a> documentation.</p> |
| <h3 id="activity-3"><a class="header" href="#activity-3">Activity</a></h3> |
| <p>Add an implementation of the <code>fmt::Display</code> trait for the <code>Color</code> struct above |
| so that the output displays as:</p> |
| <pre><code class="language-text">RGB (128, 255, 90) 0x80FF5A |
| RGB (0, 3, 254) 0x0003FE |
| RGB (0, 0, 0) 0x000000 |
| </code></pre> |
| <p>Two hints if you get stuck:</p> |
| <ul> |
| <li>You <a href="https://doc.rust-lang.org/std/fmt/#named-parameters">may need to list each color more than once</a>,</li> |
| <li>You can <a href="https://doc.rust-lang.org/std/fmt/#width">pad with zeros to a width of 2</a> with <code>:02</code>.</li> |
| </ul> |
| <h3 id="see-also-5"><a class="header" href="#see-also-5">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/fmt/"><code>std::fmt</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="primitives"><a class="header" href="#primitives">Primitives</a></h1> |
| <p>Rust provides access to a wide variety of <code>primitives</code>. A sample includes:</p> |
| <h3 id="scalar-types"><a class="header" href="#scalar-types">Scalar Types</a></h3> |
| <ul> |
| <li>signed integers: <code>i8</code>, <code>i16</code>, <code>i32</code>, <code>i64</code>, <code>i128</code> and <code>isize</code> (pointer size)</li> |
| <li>unsigned integers: <code>u8</code>, <code>u16</code>, <code>u32</code>, <code>u64</code>, <code>u128</code> and <code>usize</code> (pointer |
| size)</li> |
| <li>floating point: <code>f32</code>, <code>f64</code></li> |
| <li><code>char</code> Unicode scalar values like <code>'a'</code>, <code>'α'</code> and <code>'∞'</code> (4 bytes each)</li> |
| <li><code>bool</code> either <code>true</code> or <code>false</code></li> |
| <li>and the unit type <code>()</code>, whose only possible value is an empty tuple: <code>()</code></li> |
| </ul> |
| <p>Despite the value of a unit type being a tuple, it is not considered a |
| compound type because it does not contain multiple values. </p> |
| <h3 id="compound-types"><a class="header" href="#compound-types">Compound Types</a></h3> |
| <ul> |
| <li>arrays like <code>[1, 2, 3]</code></li> |
| <li>tuples like <code>(1, true)</code></li> |
| </ul> |
| <p>Variables can always be <em>type annotated</em>. Numbers may additionally be |
| annotated via a <em>suffix</em> or <em>by default</em>. Integers default to <code>i32</code> and |
| floats to <code>f64</code>. Note that Rust can also infer types from context.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn main() { |
| // Variables can be type annotated. |
| let logical: bool = true; |
| |
| let a_float: f64 = 1.0; // Regular annotation |
| let an_integer = 5i32; // Suffix annotation |
| |
| // Or a default will be used. |
| let default_float = 3.0; // `f64` |
| let default_integer = 7; // `i32` |
| |
| // A type can also be inferred from context |
| let mut inferred_type = 12; // Type i64 is inferred from another line |
| inferred_type = 4294967296i64; |
| |
| // A mutable variable's value can be changed. |
| let mut mutable = 12; // Mutable `i32` |
| mutable = 21; |
| |
| // Error! The type of a variable can't be changed. |
| mutable = true; |
| |
| // Variables can be overwritten with shadowing. |
| let mutable = true; |
| } |
| </code></pre></pre> |
| <h3 id="see-also-6"><a class="header" href="#see-also-6">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/">the <code>std</code> library</a>, <a href="variable_bindings/mut.html"><code>mut</code></a>, <a href="types/inference.html"><code>inference</code></a>, and <a href="variable_bindings/scope.html"><code>shadowing</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="literals-and-operators"><a class="header" href="#literals-and-operators">Literals and operators</a></h1> |
| <p>Integers <code>1</code>, floats <code>1.2</code>, characters <code>'a'</code>, strings <code>"abc"</code>, booleans <code>true</code> |
| and the unit type <code>()</code> can be expressed using literals.</p> |
| <p>Integers can, alternatively, be expressed using hexadecimal, octal or binary |
| notation using these prefixes respectively: <code>0x</code>, <code>0o</code> or <code>0b</code>.</p> |
| <p>Underscores can be inserted in numeric literals to improve readability, e.g. |
| <code>1_000</code> is the same as <code>1000</code>, and <code>0.000_001</code> is the same as <code>0.000001</code>.</p> |
| <p>We need to tell the compiler the type of the literals we use. For now, |
| we'll use the <code>u32</code> suffix to indicate that the literal is an unsigned 32-bit |
| integer, and the <code>i32</code> suffix to indicate that it's a signed 32-bit integer.</p> |
| <p>The operators available and their precedence <a href="https://doc.rust-lang.org/reference/expressions.html#expression-precedence">in Rust</a> are similar to other |
| <a href="https://en.wikipedia.org/wiki/Operator_precedence#Programming_languages">C-like languages</a>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // Integer addition |
| println!("1 + 2 = {}", 1u32 + 2); |
| |
| // Integer subtraction |
| println!("1 - 2 = {}", 1i32 - 2); |
| // TODO ^ Try changing `1i32` to `1u32` to see why the type is important |
| |
| // Short-circuiting boolean logic |
| println!("true AND false is {}", true && false); |
| println!("true OR false is {}", true || false); |
| println!("NOT true is {}", !true); |
| |
| // Bitwise operations |
| println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101); |
| println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101); |
| println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101); |
| println!("1 << 5 is {}", 1u32 << 5); |
| println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2); |
| |
| // Use underscores to improve readability! |
| println!("One million is written as {}", 1_000_000u32); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="tuples"><a class="header" href="#tuples">Tuples</a></h1> |
| <p>A tuple is a collection of values of different types. Tuples are constructed |
| using parentheses <code>()</code>, and each tuple itself is a value with type signature |
| <code>(T1, T2, ...)</code>, where <code>T1</code>, <code>T2</code> are the types of its members. Functions can |
| use tuples to return multiple values, as tuples can hold any number of values.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Tuples can be used as function arguments and as return values |
| fn reverse(pair: (i32, bool)) -> (bool, i32) { |
| // `let` can be used to bind the members of a tuple to variables |
| let (integer, boolean) = pair; |
| |
| (boolean, integer) |
| } |
| |
| // The following struct is for the activity. |
| #[derive(Debug)] |
| struct Matrix(f32, f32, f32, f32); |
| |
| fn main() { |
| // A tuple with a bunch of different types |
| let long_tuple = (1u8, 2u16, 3u32, 4u64, |
| -1i8, -2i16, -3i32, -4i64, |
| 0.1f32, 0.2f64, |
| 'a', true); |
| |
| // Values can be extracted from the tuple using tuple indexing |
| println!("long tuple first value: {}", long_tuple.0); |
| println!("long tuple second value: {}", long_tuple.1); |
| |
| // Tuples can be tuple members |
| let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16); |
| |
| // Tuples are printable |
| println!("tuple of tuples: {:?}", tuple_of_tuples); |
| |
| // But long Tuples cannot be printed |
| // let too_long_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13); |
| // println!("too long tuple: {:?}", too_long_tuple); |
| // TODO ^ Uncomment the above 2 lines to see the compiler error |
| |
| let pair = (1, true); |
| println!("pair is {:?}", pair); |
| |
| println!("the reversed pair is {:?}", reverse(pair)); |
| |
| // To create one element tuples, the comma is required to tell them apart |
| // from a literal surrounded by parentheses |
| println!("one element tuple: {:?}", (5u32,)); |
| println!("just an integer: {:?}", (5u32)); |
| |
| //tuples can be destructured to create bindings |
| let tuple = (1, "hello", 4.5, true); |
| |
| let (a, b, c, d) = tuple; |
| println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d); |
| |
| let matrix = Matrix(1.1, 1.2, 2.1, 2.2); |
| println!("{:?}", matrix); |
| |
| } |
| </code></pre></pre> |
| <h3 id="activity-4"><a class="header" href="#activity-4">Activity</a></h3> |
| <ol> |
| <li> |
| <p><em>Recap</em>: Add the <code>fmt::Display</code> trait to the <code>Matrix</code> struct in the above example, |
| so that if you switch from printing the debug format <code>{:?}</code> to the display |
| format <code>{}</code>, you see the following output:</p> |
| <pre><code class="language-text">( 1.1 1.2 ) |
| ( 2.1 2.2 ) |
| </code></pre> |
| <p>You may want to refer back to the example for <a href="primitives/../hello/print/print_display.html">print display</a>.</p> |
| </li> |
| <li> |
| <p>Add a <code>transpose</code> function using the <code>reverse</code> function as a template, which |
| accepts a matrix as an argument, and returns a matrix in which two elements |
| have been swapped. For example:</p> |
| <pre><code class="language-rust ignore">println!("Matrix:\n{}", matrix); |
| println!("Transpose:\n{}", transpose(matrix)); |
| </code></pre> |
| <p>results in the output:</p> |
| <pre><code class="language-text">Matrix: |
| ( 1.1 1.2 ) |
| ( 2.1 2.2 ) |
| Transpose: |
| ( 1.1 2.1 ) |
| ( 1.2 2.2 ) |
| </code></pre> |
| </li> |
| </ol> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="arrays-and-slices"><a class="header" href="#arrays-and-slices">Arrays and Slices</a></h1> |
| <p>An array is a collection of objects of the same type <code>T</code>, stored in contiguous |
| memory. Arrays are created using brackets <code>[]</code>, and their length, which is known |
| at compile time, is part of their type signature <code>[T; length]</code>.</p> |
| <p>Slices are similar to arrays, but their length is not known at compile time. |
| Instead, a slice is a two-word object, the first word is a pointer to the data, |
| and the second word is the length of the slice. The word size is the same as |
| usize, determined by the processor architecture eg 64 bits on an x86-64. |
| Slices can be used to borrow a section of an array, and have the type signature |
| <code>&[T]</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">use std::mem; |
| |
| // This function borrows a slice |
| fn analyze_slice(slice: &[i32]) { |
| println!("first element of the slice: {}", slice[0]); |
| println!("the slice has {} elements", slice.len()); |
| } |
| |
| fn main() { |
| // Fixed-size array (type signature is superfluous) |
| let xs: [i32; 5] = [1, 2, 3, 4, 5]; |
| |
| // All elements can be initialized to the same value |
| let ys: [i32; 500] = [0; 500]; |
| |
| // Indexing starts at 0 |
| println!("first element of the array: {}", xs[0]); |
| println!("second element of the array: {}", xs[1]); |
| |
| // `len` returns the count of elements in the array |
| println!("number of elements in array: {}", xs.len()); |
| |
| // Arrays are stack allocated |
| println!("array occupies {} bytes", mem::size_of_val(&xs)); |
| |
| // Arrays can be automatically borrowed as slices |
| println!("borrow the whole array as a slice"); |
| analyze_slice(&xs); |
| |
| // Slices can point to a section of an array |
| // They are of the form [starting_index..ending_index] |
| // starting_index is the first position in the slice |
| // ending_index is one more than the last position in the slice |
| println!("borrow a section of the array as a slice"); |
| analyze_slice(&ys[1 .. 4]); |
| |
| // Out of bound indexing causes compile error |
| println!("{}", xs[5]); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="custom-types"><a class="header" href="#custom-types">Custom Types</a></h1> |
| <p>Rust custom data types are formed mainly through the two keywords:</p> |
| <ul> |
| <li><code>struct</code>: define a structure</li> |
| <li><code>enum</code>: define an enumeration</li> |
| </ul> |
| <p>Constants can also be created via the <code>const</code> and <code>static</code> keywords.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="structures"><a class="header" href="#structures">Structures</a></h1> |
| <p>There are three types of structures ("structs") that can be created using the |
| <code>struct</code> keyword:</p> |
| <ul> |
| <li>Tuple structs, which are, basically, named tuples.</li> |
| <li>The classic <a href="https://en.wikipedia.org/wiki/Struct_(C_programming_language)">C structs</a></li> |
| <li>Unit structs, which are field-less, are useful for generics.</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable">#[derive(Debug)] |
| struct Person { |
| name: String, |
| age: u8, |
| } |
| |
| // A unit struct |
| struct Unit; |
| |
| // A tuple struct |
| struct Pair(i32, f32); |
| |
| // A struct with two fields |
| struct Point { |
| x: f32, |
| y: f32, |
| } |
| |
| // Structs can be reused as fields of another struct |
| #[allow(dead_code)] |
| struct Rectangle { |
| // A rectangle can be specified by where the top left and bottom right |
| // corners are in space. |
| top_left: Point, |
| bottom_right: Point, |
| } |
| |
| fn main() { |
| // Create struct with field init shorthand |
| let name = String::from("Peter"); |
| let age = 27; |
| let peter = Person { name, age }; |
| |
| // Print debug struct |
| println!("{:?}", peter); |
| |
| |
| // Instantiate a `Point` |
| let point: Point = Point { x: 10.3, y: 0.4 }; |
| |
| // Access the fields of the point |
| println!("point coordinates: ({}, {})", point.x, point.y); |
| |
| // Make a new point by using struct update syntax to use the fields of our |
| // other one |
| let bottom_right = Point { x: 5.2, ..point }; |
| |
| // `bottom_right.y` will be the same as `point.y` because we used that field |
| // from `point` |
| println!("second point: ({}, {})", bottom_right.x, bottom_right.y); |
| |
| // Destructure the point using a `let` binding |
| let Point { x: left_edge, y: top_edge } = point; |
| |
| let _rectangle = Rectangle { |
| // struct instantiation is an expression too |
| top_left: Point { x: left_edge, y: top_edge }, |
| bottom_right: bottom_right, |
| }; |
| |
| // Instantiate a unit struct |
| let _unit = Unit; |
| |
| // Instantiate a tuple struct |
| let pair = Pair(1, 0.1); |
| |
| // Access the fields of a tuple struct |
| println!("pair contains {:?} and {:?}", pair.0, pair.1); |
| |
| // Destructure a tuple struct |
| let Pair(integer, decimal) = pair; |
| |
| println!("pair contains {:?} and {:?}", integer, decimal); |
| } |
| </code></pre></pre> |
| <h3 id="activity-5"><a class="header" href="#activity-5">Activity</a></h3> |
| <ol> |
| <li>Add a function <code>rect_area</code> which calculates the area of a <code>Rectangle</code> (try |
| using nested destructuring).</li> |
| <li>Add a function <code>square</code> which takes a <code>Point</code> and a <code>f32</code> as arguments, and |
| returns a <code>Rectangle</code> with its lower left corner on the point, and a width and |
| height corresponding to the <code>f32</code>.</li> |
| </ol> |
| <h3 id="see-also-7"><a class="header" href="#see-also-7">See also</a></h3> |
| <p><a href="custom_types/../attribute.html"><code>attributes</code></a>, and <a href="custom_types/../flow_control/match/destructuring.html">destructuring</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="enums"><a class="header" href="#enums">Enums</a></h1> |
| <p>The <code>enum</code> keyword allows the creation of a type which may be one of a few |
| different variants. Any variant which is valid as a <code>struct</code> is also valid as |
| an <code>enum</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Create an `enum` to classify a web event. Note how both |
| // names and type information together specify the variant: |
| // `PageLoad != PageUnload` and `KeyPress(char) != Paste(String)`. |
| // Each is different and independent. |
| enum WebEvent { |
| // An `enum` may either be `unit-like`, |
| PageLoad, |
| PageUnload, |
| // like tuple structs, |
| KeyPress(char), |
| Paste(String), |
| // or c-like structures. |
| Click { x: i64, y: i64 }, |
| } |
| |
| // A function which takes a `WebEvent` enum as an argument and |
| // returns nothing. |
| fn inspect(event: WebEvent) { |
| match event { |
| WebEvent::PageLoad => println!("page loaded"), |
| WebEvent::PageUnload => println!("page unloaded"), |
| // Destructure `c` from inside the `enum`. |
| WebEvent::KeyPress(c) => println!("pressed '{}'.", c), |
| WebEvent::Paste(s) => println!("pasted \"{}\".", s), |
| // Destructure `Click` into `x` and `y`. |
| WebEvent::Click { x, y } => { |
| println!("clicked at x={}, y={}.", x, y); |
| }, |
| } |
| } |
| |
| fn main() { |
| let pressed = WebEvent::KeyPress('x'); |
| // `to_owned()` creates an owned `String` from a string slice. |
| let pasted = WebEvent::Paste("my text".to_owned()); |
| let click = WebEvent::Click { x: 20, y: 80 }; |
| let load = WebEvent::PageLoad; |
| let unload = WebEvent::PageUnload; |
| |
| inspect(pressed); |
| inspect(pasted); |
| inspect(click); |
| inspect(load); |
| inspect(unload); |
| } |
| |
| </code></pre></pre> |
| <h2 id="type-aliases"><a class="header" href="#type-aliases">Type aliases</a></h2> |
| <p>If you use a type alias, you can refer to each enum variant via its alias. |
| This might be useful if the enum's name is too long or too generic, and you |
| want to rename it.</p> |
| <pre><pre class="playground"><code class="language-rust editable">enum VeryVerboseEnumOfThingsToDoWithNumbers { |
| Add, |
| Subtract, |
| } |
| |
| // Creates a type alias |
| type Operations = VeryVerboseEnumOfThingsToDoWithNumbers; |
| |
| fn main() { |
| // We can refer to each variant via its alias, not its long and inconvenient |
| // name. |
| let x = Operations::Add; |
| } |
| </code></pre></pre> |
| <p>The most common place you'll see this is in <code>impl</code> blocks using the <code>Self</code> alias.</p> |
| <pre><pre class="playground"><code class="language-rust editable">enum VeryVerboseEnumOfThingsToDoWithNumbers { |
| Add, |
| Subtract, |
| } |
| |
| impl VeryVerboseEnumOfThingsToDoWithNumbers { |
| fn run(&self, x: i32, y: i32) -> i32 { |
| match self { |
| Self::Add => x + y, |
| Self::Subtract => x - y, |
| } |
| } |
| } |
| </code></pre></pre> |
| <p>To learn more about enums and type aliases, you can read the |
| <a href="https://github.com/rust-lang/rust/pull/61682/#issuecomment-502472847">stabilization report</a> from when this feature was stabilized into |
| Rust.</p> |
| <h3 id="see-also-8"><a class="header" href="#see-also-8">See also:</a></h3> |
| <p><a href="custom_types/../flow_control/match.html"><code>match</code></a>, <a href="custom_types/../fn.html"><code>fn</code></a>, and <a href="custom_types/../std/str.html"><code>String</code></a>, <a href="https://rust-lang.github.io/rfcs/2338-type-alias-enum-variants.html">"Type alias enum variants" RFC</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="use"><a class="header" href="#use">use</a></h1> |
| <p>The <code>use</code> declaration can be used so manual scoping isn't needed:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// An attribute to hide warnings for unused code. |
| #![allow(dead_code)] |
| |
| enum Status { |
| Rich, |
| Poor, |
| } |
| |
| enum Work { |
| Civilian, |
| Soldier, |
| } |
| |
| fn main() { |
| // Explicitly `use` each name so they are available without |
| // manual scoping. |
| use crate::Status::{Poor, Rich}; |
| // Automatically `use` each name inside `Work`. |
| use crate::Work::*; |
| |
| // Equivalent to `Status::Poor`. |
| let status = Poor; |
| // Equivalent to `Work::Civilian`. |
| let work = Civilian; |
| |
| match status { |
| // Note the lack of scoping because of the explicit `use` above. |
| Rich => println!("The rich have lots of money!"), |
| Poor => println!("The poor have no money..."), |
| } |
| |
| match work { |
| // Note again the lack of scoping. |
| Civilian => println!("Civilians work!"), |
| Soldier => println!("Soldiers fight!"), |
| } |
| } |
| </code></pre></pre> |
| <h3 id="see-also-9"><a class="header" href="#see-also-9">See also:</a></h3> |
| <p><a href="custom_types/enum/../../flow_control/match.html"><code>match</code></a> and <a href="custom_types/enum/../../mod/use.html"><code>use</code></a> </p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="c-like"><a class="header" href="#c-like">C-like</a></h1> |
| <p><code>enum</code> can also be used as C-like enums.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// An attribute to hide warnings for unused code. |
| #![allow(dead_code)] |
| |
| // enum with implicit discriminator (starts at 0) |
| enum Number { |
| Zero, |
| One, |
| Two, |
| } |
| |
| // enum with explicit discriminator |
| enum Color { |
| Red = 0xff0000, |
| Green = 0x00ff00, |
| Blue = 0x0000ff, |
| } |
| |
| fn main() { |
| // `enums` can be cast as integers. |
| println!("zero is {}", Number::Zero as i32); |
| println!("one is {}", Number::One as i32); |
| |
| println!("roses are #{:06x}", Color::Red as i32); |
| println!("violets are #{:06x}", Color::Blue as i32); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-10"><a class="header" href="#see-also-10">See also:</a></h3> |
| <p><a href="custom_types/enum/../../types/cast.html">casting</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="testcase-linked-list"><a class="header" href="#testcase-linked-list">Testcase: linked-list</a></h1> |
| <p>A common use for <code>enums</code> is to create a linked-list:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use crate::List::*; |
| |
| enum List { |
| // Cons: Tuple struct that wraps an element and a pointer to the next node |
| Cons(u32, Box<List>), |
| // Nil: A node that signifies the end of the linked list |
| Nil, |
| } |
| |
| // Methods can be attached to an enum |
| impl List { |
| // Create an empty list |
| fn new() -> List { |
| // `Nil` has type `List` |
| Nil |
| } |
| |
| // Consume a list, and return the same list with a new element at its front |
| fn prepend(self, elem: u32) -> List { |
| // `Cons` also has type List |
| Cons(elem, Box::new(self)) |
| } |
| |
| // Return the length of the list |
| fn len(&self) -> u32 { |
| // `self` has to be matched, because the behavior of this method |
| // depends on the variant of `self` |
| // `self` has type `&List`, and `*self` has type `List`, matching on a |
| // concrete type `T` is preferred over a match on a reference `&T` |
| // after Rust 2018 you can use self here and tail (with no ref) below as well, |
| // rust will infer &s and ref tail. |
| // See https://doc.rust-lang.org/edition-guide/rust-2018/ownership-and-lifetimes/default-match-bindings.html |
| match *self { |
| // Can't take ownership of the tail, because `self` is borrowed; |
| // instead take a reference to the tail |
| Cons(_, ref tail) => 1 + tail.len(), |
| // Base Case: An empty list has zero length |
| Nil => 0 |
| } |
| } |
| |
| // Return representation of the list as a (heap allocated) string |
| fn stringify(&self) -> String { |
| match *self { |
| Cons(head, ref tail) => { |
| // `format!` is similar to `print!`, but returns a heap |
| // allocated string instead of printing to the console |
| format!("{}, {}", head, tail.stringify()) |
| }, |
| Nil => { |
| format!("Nil") |
| }, |
| } |
| } |
| } |
| |
| fn main() { |
| // Create an empty linked list |
| let mut list = List::new(); |
| |
| // Prepend some elements |
| list = list.prepend(1); |
| list = list.prepend(2); |
| list = list.prepend(3); |
| |
| // Show the final state of the list |
| println!("linked list has length: {}", list.len()); |
| println!("{}", list.stringify()); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-11"><a class="header" href="#see-also-11">See also:</a></h3> |
| <p><a href="custom_types/enum/../../std/box.html"><code>Box</code></a> and <a href="custom_types/enum/../../fn/methods.html">methods</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="constants"><a class="header" href="#constants">constants</a></h1> |
| <p>Rust has two different types of constants which can be declared in any scope |
| including global. Both require explicit type annotation:</p> |
| <ul> |
| <li><code>const</code>: An unchangeable value (the common case).</li> |
| <li><code>static</code>: A possibly <code>mut</code>able variable with <a href="custom_types/../scope/lifetime/static_lifetime.html"><code>'static</code></a> lifetime. |
| The static lifetime is inferred and does not have to be specified. |
| Accessing or modifying a mutable static variable is <a href="custom_types/../unsafe.html"><code>unsafe</code></a>.</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">// Globals are declared outside all other scopes. |
| static LANGUAGE: &str = "Rust"; |
| const THRESHOLD: i32 = 10; |
| |
| fn is_big(n: i32) -> bool { |
| // Access constant in some function |
| n > THRESHOLD |
| } |
| |
| fn main() { |
| let n = 16; |
| |
| // Access constant in the main thread |
| println!("This is {}", LANGUAGE); |
| println!("The threshold is {}", THRESHOLD); |
| println!("{} is {}", n, if is_big(n) { "big" } else { "small" }); |
| |
| // Error! Cannot modify a `const`. |
| THRESHOLD = 5; |
| // FIXME ^ Comment out this line |
| } |
| </code></pre></pre> |
| <h3 id="see-also-12"><a class="header" href="#see-also-12">See also:</a></h3> |
| <p><a href="https://github.com/rust-lang/rfcs/blob/master/text/0246-const-vs-static.md">The <code>const</code>/<code>static</code> RFC</a>, |
| <a href="custom_types/../scope/lifetime/static_lifetime.html"><code>'static</code> lifetime</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="variable-bindings"><a class="header" href="#variable-bindings">Variable Bindings</a></h1> |
| <p>Rust provides type safety via static typing. Variable bindings can be type |
| annotated when declared. However, in most cases, the compiler will be able |
| to infer the type of the variable from the context, heavily reducing the |
| annotation burden.</p> |
| <p>Values (like literals) can be bound to variables, using the <code>let</code> binding.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let an_integer = 1u32; |
| let a_boolean = true; |
| let unit = (); |
| |
| // copy `an_integer` into `copied_integer` |
| let copied_integer = an_integer; |
| |
| println!("An integer: {:?}", copied_integer); |
| println!("A boolean: {:?}", a_boolean); |
| println!("Meet the unit value: {:?}", unit); |
| |
| // The compiler warns about unused variable bindings; these warnings can |
| // be silenced by prefixing the variable name with an underscore |
| let _unused_variable = 3u32; |
| |
| let noisy_unused_variable = 2u32; |
| // FIXME ^ Prefix with an underscore to suppress the warning |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="mutability"><a class="header" href="#mutability">Mutability</a></h1> |
| <p>Variable bindings are immutable by default, but this can be overridden using |
| the <code>mut</code> modifier.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn main() { |
| let _immutable_binding = 1; |
| let mut mutable_binding = 1; |
| |
| println!("Before mutation: {}", mutable_binding); |
| |
| // Ok |
| mutable_binding += 1; |
| |
| println!("After mutation: {}", mutable_binding); |
| |
| // Error! |
| _immutable_binding += 1; |
| // FIXME ^ Comment out this line |
| } |
| </code></pre></pre> |
| <p>The compiler will throw a detailed diagnostic about mutability errors.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="scope-and-shadowing"><a class="header" href="#scope-and-shadowing">Scope and Shadowing</a></h1> |
| <p>Variable bindings have a scope, and are constrained to live in a <em>block</em>. A |
| block is a collection of statements enclosed by braces <code>{}</code>. </p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn main() { |
| // This binding lives in the main function |
| let long_lived_binding = 1; |
| |
| // This is a block, and has a smaller scope than the main function |
| { |
| // This binding only exists in this block |
| let short_lived_binding = 2; |
| |
| println!("inner short: {}", short_lived_binding); |
| } |
| // End of the block |
| |
| // Error! `short_lived_binding` doesn't exist in this scope |
| println!("outer short: {}", short_lived_binding); |
| // FIXME ^ Comment out this line |
| |
| println!("outer long: {}", long_lived_binding); |
| } |
| </code></pre></pre> |
| <p>Also, <a href="https://en.wikipedia.org/wiki/Variable_shadowing">variable shadowing</a> is allowed.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn main() { |
| let shadowed_binding = 1; |
| |
| { |
| println!("before being shadowed: {}", shadowed_binding); |
| |
| // This binding *shadows* the outer one |
| let shadowed_binding = "abc"; |
| |
| println!("shadowed in inner block: {}", shadowed_binding); |
| } |
| println!("outside inner block: {}", shadowed_binding); |
| |
| // This binding *shadows* the previous binding |
| let shadowed_binding = 2; |
| println!("shadowed in outer block: {}", shadowed_binding); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="declare-first"><a class="header" href="#declare-first">Declare first</a></h1> |
| <p>It's possible to declare variable bindings first, and initialize them later. |
| However, this form is seldom used, as it may lead to the use of uninitialized |
| variables.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn main() { |
| // Declare a variable binding |
| let a_binding; |
| |
| { |
| let x = 2; |
| |
| // Initialize the binding |
| a_binding = x * x; |
| } |
| |
| println!("a binding: {}", a_binding); |
| |
| let another_binding; |
| |
| // Error! Use of uninitialized binding |
| println!("another binding: {}", another_binding); |
| // FIXME ^ Comment out this line |
| |
| another_binding = 1; |
| |
| println!("another binding: {}", another_binding); |
| } |
| </code></pre></pre> |
| <p>The compiler forbids use of uninitialized variables, as this would lead to |
| undefined behavior.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="freezing"><a class="header" href="#freezing">Freezing</a></h1> |
| <p>When data is bound by the same name immutably, it also <em>freezes</em>. <em>Frozen</em> data can't be |
| modified until the immutable binding goes out of scope:</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn main() { |
| let mut _mutable_integer = 7i32; |
| |
| { |
| // Shadowing by immutable `_mutable_integer` |
| let _mutable_integer = _mutable_integer; |
| |
| // Error! `_mutable_integer` is frozen in this scope |
| _mutable_integer = 50; |
| // FIXME ^ Comment out this line |
| |
| // `_mutable_integer` goes out of scope |
| } |
| |
| // Ok! `_mutable_integer` is not frozen in this scope |
| _mutable_integer = 3; |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="types"><a class="header" href="#types">Types</a></h1> |
| <p>Rust provides several mechanisms to change or define the type of primitive and |
| user defined types. The following sections cover:</p> |
| <ul> |
| <li><a href="types/cast.html">Casting</a> between primitive types</li> |
| <li>Specifying the desired type of <a href="types/literals.html">literals</a></li> |
| <li>Using <a href="types/inference.html">type inference</a></li> |
| <li><a href="types/alias.html">Aliasing</a> types</li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="casting"><a class="header" href="#casting">Casting</a></h1> |
| <p>Rust provides no implicit type conversion (coercion) between primitive types. |
| But, explicit type conversion (casting) can be performed using the <code>as</code> keyword.</p> |
| <p>Rules for converting between integral types follow C conventions generally, |
| except in cases where C has undefined behavior. The behavior of all casts |
| between integral types is well defined in Rust.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">// Suppress all warnings from casts which overflow. |
| #![allow(overflowing_literals)] |
| |
| fn main() { |
| let decimal = 65.4321_f32; |
| |
| // Error! No implicit conversion |
| let integer: u8 = decimal; |
| // FIXME ^ Comment out this line |
| |
| // Explicit conversion |
| let integer = decimal as u8; |
| let character = integer as char; |
| |
| // Error! There are limitations in conversion rules. |
| // A float cannot be directly converted to a char. |
| let character = decimal as char; |
| // FIXME ^ Comment out this line |
| |
| println!("Casting: {} -> {} -> {}", decimal, integer, character); |
| |
| // when casting any value to an unsigned type, T, |
| // T::MAX + 1 is added or subtracted until the value |
| // fits into the new type |
| |
| // 1000 already fits in a u16 |
| println!("1000 as a u16 is: {}", 1000 as u16); |
| |
| // 1000 - 256 - 256 - 256 = 232 |
| // Under the hood, the first 8 least significant bits (LSB) are kept, |
| // while the rest towards the most significant bit (MSB) get truncated. |
| println!("1000 as a u8 is : {}", 1000 as u8); |
| // -1 + 256 = 255 |
| println!(" -1 as a u8 is : {}", (-1i8) as u8); |
| |
| // For positive numbers, this is the same as the modulus |
| println!("1000 mod 256 is : {}", 1000 % 256); |
| |
| // When casting to a signed type, the (bitwise) result is the same as |
| // first casting to the corresponding unsigned type. If the most significant |
| // bit of that value is 1, then the value is negative. |
| |
| // Unless it already fits, of course. |
| println!(" 128 as a i16 is: {}", 128 as i16); |
| // 128 as u8 -> 128, whose two's complement in eight bits is: |
| println!(" 128 as a i8 is : {}", 128 as i8); |
| |
| // repeating the example above |
| // 1000 as u8 -> 232 |
| println!("1000 as a u8 is : {}", 1000 as u8); |
| // and the two's complement of 232 is -24 |
| println!(" 232 as a i8 is : {}", 232 as i8); |
| |
| // Since Rust 1.45, the `as` keyword performs a *saturating cast* |
| // when casting from float to int. If the floating point value exceeds |
| // the upper bound or is less than the lower bound, the returned value |
| // will be equal to the bound crossed. |
| |
| // 300.0 is 255 |
| println!("300.0 is {}", 300.0_f32 as u8); |
| // -100.0 as u8 is 0 |
| println!("-100.0 as u8 is {}", -100.0_f32 as u8); |
| // nan as u8 is 0 |
| println!("nan as u8 is {}", f32::NAN as u8); |
| |
| // This behavior incurs a small runtime cost and can be avoided |
| // with unsafe methods, however the results might overflow and |
| // return **unsound values**. Use these methods wisely: |
| unsafe { |
| // 300.0 is 44 |
| println!("300.0 is {}", 300.0_f32.to_int_unchecked::<u8>()); |
| // -100.0 as u8 is 156 |
| println!("-100.0 as u8 is {}", (-100.0_f32).to_int_unchecked::<u8>()); |
| // nan as u8 is 0 |
| println!("nan as u8 is {}", f32::NAN.to_int_unchecked::<u8>()); |
| } |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="literals"><a class="header" href="#literals">Literals</a></h1> |
| <p>Numeric literals can be type annotated by adding the type as a suffix. As an example, |
| to specify that the literal <code>42</code> should have the type <code>i32</code>, write <code>42i32</code>.</p> |
| <p>The type of unsuffixed numeric literals will depend on how they are used. If no |
| constraint exists, the compiler will use <code>i32</code> for integers, and <code>f64</code> for |
| floating-point numbers.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // Suffixed literals, their types are known at initialization |
| let x = 1u8; |
| let y = 2u32; |
| let z = 3f32; |
| |
| // Unsuffixed literals, their types depend on how they are used |
| let i = 1; |
| let f = 1.0; |
| |
| // `size_of_val` returns the size of a variable in bytes |
| println!("size of `x` in bytes: {}", std::mem::size_of_val(&x)); |
| println!("size of `y` in bytes: {}", std::mem::size_of_val(&y)); |
| println!("size of `z` in bytes: {}", std::mem::size_of_val(&z)); |
| println!("size of `i` in bytes: {}", std::mem::size_of_val(&i)); |
| println!("size of `f` in bytes: {}", std::mem::size_of_val(&f)); |
| } |
| </code></pre></pre> |
| <p>There are some concepts used in the previous code that haven't been explained |
| yet, here's a brief explanation for the impatient readers:</p> |
| <ul> |
| <li><code>std::mem::size_of_val</code> is a function, but called with its <em>full path</em>. Code |
| can be split in logical units called <em>modules</em>. In this case, the |
| <code>size_of_val</code> function is defined in the <code>mem</code> module, and the <code>mem</code> module |
| is defined in the <code>std</code> <em>crate</em>. For more details, see |
| <a href="types/../mod.html">modules</a> and <a href="types/../crates.html">crates</a>.</li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="inference"><a class="header" href="#inference">Inference</a></h1> |
| <p>The type inference engine is pretty smart. It does more than looking at the |
| type of the value expression |
| during an initialization. It also looks at how the variable is used afterwards |
| to infer its type. Here's an advanced example of type inference:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // Because of the annotation, the compiler knows that `elem` has type u8. |
| let elem = 5u8; |
| |
| // Create an empty vector (a growable array). |
| let mut vec = Vec::new(); |
| // At this point the compiler doesn't know the exact type of `vec`, it |
| // just knows that it's a vector of something (`Vec<_>`). |
| |
| // Insert `elem` in the vector. |
| vec.push(elem); |
| // Aha! Now the compiler knows that `vec` is a vector of `u8`s (`Vec<u8>`) |
| // TODO ^ Try commenting out the `vec.push(elem)` line |
| |
| println!("{:?}", vec); |
| } |
| </code></pre></pre> |
| <p>No type annotation of variables was needed, the compiler is happy and so is the |
| programmer!</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="aliasing"><a class="header" href="#aliasing">Aliasing</a></h1> |
| <p>The <code>type</code> statement can be used to give a new name to an existing type. Types |
| must have <code>UpperCamelCase</code> names, or the compiler will raise a warning. The |
| exception to this rule are the primitive types: <code>usize</code>, <code>f32</code>, etc.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// `NanoSecond` is a new name for `u64`. |
| type NanoSecond = u64; |
| type Inch = u64; |
| |
| // Use an attribute to silence warning. |
| #[allow(non_camel_case_types)] |
| type u64_t = u64; |
| // TODO ^ Try removing the attribute |
| |
| fn main() { |
| // `NanoSecond` = `Inch` = `u64_t` = `u64`. |
| let nanoseconds: NanoSecond = 5 as u64_t; |
| let inches: Inch = 2 as u64_t; |
| |
| // Note that type aliases *don't* provide any extra type safety, because |
| // aliases are *not* new types |
| println!("{} nanoseconds + {} inches = {} unit?", |
| nanoseconds, |
| inches, |
| nanoseconds + inches); |
| } |
| </code></pre></pre> |
| <p>The main use of aliases is to reduce boilerplate; for example the <code>IoResult<T></code> type |
| is an alias for the <code>Result<T, IoError></code> type.</p> |
| <h3 id="see-also-13"><a class="header" href="#see-also-13">See also:</a></h3> |
| <p><a href="types/../attribute.html">Attributes</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="conversion"><a class="header" href="#conversion">Conversion</a></h1> |
| <p>Primitive types can be converted to each other through <a href="types/cast.html">casting</a>.</p> |
| <p>Rust addresses conversion between custom types (i.e., <code>struct</code> and <code>enum</code>) |
| by the use of <a href="trait.html">traits</a>. The generic |
| conversions will use the <a href="https://doc.rust-lang.org/std/convert/trait.From.html"><code>From</code></a> and <a href="https://doc.rust-lang.org/std/convert/trait.Into.html"><code>Into</code></a> traits. However there are more |
| specific ones for the more common cases, in particular when converting to and |
| from <code>String</code>s.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="from-and-into"><a class="header" href="#from-and-into"><code>From</code> and <code>Into</code></a></h1> |
| <p>The <a href="https://doc.rust-lang.org/std/convert/trait.From.html"><code>From</code></a> and <a href="https://doc.rust-lang.org/std/convert/trait.Into.html"><code>Into</code></a> traits are inherently linked, and this is actually part of |
| its implementation. If you are able to convert type A from type B, then it |
| should be easy to believe that we should be able to convert type B to type A.</p> |
| <h2 id="from"><a class="header" href="#from"><code>From</code></a></h2> |
| <p>The <a href="https://doc.rust-lang.org/std/convert/trait.From.html"><code>From</code></a> trait allows for a type to define how to create itself from another |
| type, hence providing a very simple mechanism for converting between several |
| types. There are numerous implementations of this trait within the standard |
| library for conversion of primitive and common types.</p> |
| <p>For example we can easily convert a <code>str</code> into a <code>String</code></p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>let my_str = "hello"; |
| let my_string = String::from(my_str); |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p>We can do similar for defining a conversion for our own type.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::convert::From; |
| |
| #[derive(Debug)] |
| struct Number { |
| value: i32, |
| } |
| |
| impl From<i32> for Number { |
| fn from(item: i32) -> Self { |
| Number { value: item } |
| } |
| } |
| |
| fn main() { |
| let num = Number::from(30); |
| println!("My number is {:?}", num); |
| } |
| </code></pre></pre> |
| <h2 id="into"><a class="header" href="#into"><code>Into</code></a></h2> |
| <p>The <a href="https://doc.rust-lang.org/std/convert/trait.Into.html"><code>Into</code></a> trait is simply the reciprocal of the <code>From</code> trait. That is, if you |
| have implemented the <code>From</code> trait for your type, <code>Into</code> will call it when |
| necessary.</p> |
| <p>Using the <code>Into</code> trait will typically require specification of the type to |
| convert into as the compiler is unable to determine this most of the time. |
| However this is a small trade-off considering we get the functionality for free.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::convert::From; |
| |
| #[derive(Debug)] |
| struct Number { |
| value: i32, |
| } |
| |
| impl From<i32> for Number { |
| fn from(item: i32) -> Self { |
| Number { value: item } |
| } |
| } |
| |
| fn main() { |
| let int = 5; |
| // Try removing the type declaration |
| let num: Number = int.into(); |
| println!("My number is {:?}", num); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="tryfrom-and-tryinto"><a class="header" href="#tryfrom-and-tryinto"><code>TryFrom</code> and <code>TryInto</code></a></h1> |
| <p>Similar to <a href="conversion/from_into.html"><code>From</code> and <code>Into</code></a>, <a href="https://doc.rust-lang.org/std/convert/trait.TryFrom.html"><code>TryFrom</code></a> and <a href="https://doc.rust-lang.org/std/convert/trait.TryInto.html"><code>TryInto</code></a> are |
| generic traits for converting between types. Unlike <code>From</code>/<code>Into</code>, the |
| <code>TryFrom</code>/<code>TryInto</code> traits are used for fallible conversions, and as such, |
| return <a href="https://doc.rust-lang.org/std/result/enum.Result.html"><code>Result</code></a>s.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::convert::TryFrom; |
| use std::convert::TryInto; |
| |
| #[derive(Debug, PartialEq)] |
| struct EvenNumber(i32); |
| |
| impl TryFrom<i32> for EvenNumber { |
| type Error = (); |
| |
| fn try_from(value: i32) -> Result<Self, Self::Error> { |
| if value % 2 == 0 { |
| Ok(EvenNumber(value)) |
| } else { |
| Err(()) |
| } |
| } |
| } |
| |
| fn main() { |
| // TryFrom |
| |
| assert_eq!(EvenNumber::try_from(8), Ok(EvenNumber(8))); |
| assert_eq!(EvenNumber::try_from(5), Err(())); |
| |
| // TryInto |
| |
| let result: Result<EvenNumber, ()> = 8i32.try_into(); |
| assert_eq!(result, Ok(EvenNumber(8))); |
| let result: Result<EvenNumber, ()> = 5i32.try_into(); |
| assert_eq!(result, Err(())); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="to-and-from-strings"><a class="header" href="#to-and-from-strings">To and from Strings</a></h1> |
| <h2 id="converting-to-string"><a class="header" href="#converting-to-string">Converting to String</a></h2> |
| <p>To convert any type to a <code>String</code> is as simple as implementing the <a href="https://doc.rust-lang.org/std/string/trait.ToString.html"><code>ToString</code></a> |
| trait for the type. Rather than doing so directly, you should implement the |
| <a href="https://doc.rust-lang.org/std/fmt/trait.Display.html"><code>fmt::Display</code></a> trait which automagically provides <a href="https://doc.rust-lang.org/std/string/trait.ToString.html"><code>ToString</code></a> and |
| also allows printing the type as discussed in the section on <a href="conversion/../hello/print.html"><code>print!</code></a>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::fmt; |
| |
| struct Circle { |
| radius: i32 |
| } |
| |
| impl fmt::Display for Circle { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| write!(f, "Circle of radius {}", self.radius) |
| } |
| } |
| |
| fn main() { |
| let circle = Circle { radius: 6 }; |
| println!("{}", circle.to_string()); |
| } |
| </code></pre></pre> |
| <h2 id="parsing-a-string"><a class="header" href="#parsing-a-string">Parsing a String</a></h2> |
| <p>One of the more common types to convert a string into is a number. The idiomatic |
| approach to this is to use the <a href="https://doc.rust-lang.org/std/primitive.str.html#method.parse"><code>parse</code></a> function and either to arrange for |
| type inference or to specify the type to parse using the 'turbofish' syntax. |
| Both alternatives are shown in the following example.</p> |
| <p>This will convert the string into the type specified so long as the <a href="https://doc.rust-lang.org/std/str/trait.FromStr.html"><code>FromStr</code></a> |
| trait is implemented for that type. This is implemented for numerous types |
| within the standard library. To obtain this functionality on a user defined type |
| simply implement the <a href="https://doc.rust-lang.org/std/str/trait.FromStr.html"><code>FromStr</code></a> trait for that type.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let parsed: i32 = "5".parse().unwrap(); |
| let turbo_parsed = "10".parse::<i32>().unwrap(); |
| |
| let sum = parsed + turbo_parsed; |
| println!("Sum: {:?}", sum); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="expressions"><a class="header" href="#expressions">Expressions</a></h1> |
| <p>A Rust program is (mostly) made up of a series of statements:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // statement |
| // statement |
| // statement |
| } |
| </code></pre></pre> |
| <p>There are a few kinds of statements in Rust. The most common two are declaring |
| a variable binding, and using a <code>;</code> with an expression:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // variable binding |
| let x = 5; |
| |
| // expression; |
| x; |
| x + 1; |
| 15; |
| } |
| </code></pre></pre> |
| <p>Blocks are expressions too, so they can be used as values in |
| assignments. The last expression in the block will be assigned to the |
| place expression such as a local variable. However, if the last expression of the block ends with a |
| semicolon, the return value will be <code>()</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let x = 5u32; |
| |
| let y = { |
| let x_squared = x * x; |
| let x_cube = x_squared * x; |
| |
| // This expression will be assigned to `y` |
| x_cube + x_squared + x |
| }; |
| |
| let z = { |
| // The semicolon suppresses this expression and `()` is assigned to `z` |
| 2 * x; |
| }; |
| |
| println!("x is {:?}", x); |
| println!("y is {:?}", y); |
| println!("z is {:?}", z); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="flow-of-control"><a class="header" href="#flow-of-control">Flow of Control</a></h1> |
| <p>An essential part of any programming languages are ways to modify control flow: |
| <code>if</code>/<code>else</code>, <code>for</code>, and others. Let's talk about them in Rust.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="ifelse"><a class="header" href="#ifelse">if/else</a></h1> |
| <p>Branching with <code>if</code>-<code>else</code> is similar to other languages. Unlike many of them, |
| the boolean condition doesn't need to be surrounded by parentheses, and each |
| condition is followed by a block. <code>if</code>-<code>else</code> conditionals are expressions, |
| and, all branches must return the same type.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let n = 5; |
| |
| if n < 0 { |
| print!("{} is negative", n); |
| } else if n > 0 { |
| print!("{} is positive", n); |
| } else { |
| print!("{} is zero", n); |
| } |
| |
| let big_n = |
| if n < 10 && n > -10 { |
| println!(", and is a small number, increase ten-fold"); |
| |
| // This expression returns an `i32`. |
| 10 * n |
| } else { |
| println!(", and is a big number, halve the number"); |
| |
| // This expression must return an `i32` as well. |
| n / 2 |
| // TODO ^ Try suppressing this expression with a semicolon. |
| }; |
| // ^ Don't forget to put a semicolon here! All `let` bindings need it. |
| |
| println!("{} -> {}", n, big_n); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="loop"><a class="header" href="#loop">loop</a></h1> |
| <p>Rust provides a <code>loop</code> keyword to indicate an infinite loop.</p> |
| <p>The <code>break</code> statement can be used to exit a loop at anytime, whereas the |
| <code>continue</code> statement can be used to skip the rest of the iteration and start a |
| new one.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let mut count = 0u32; |
| |
| println!("Let's count until infinity!"); |
| |
| // Infinite loop |
| loop { |
| count += 1; |
| |
| if count == 3 { |
| println!("three"); |
| |
| // Skip the rest of this iteration |
| continue; |
| } |
| |
| println!("{}", count); |
| |
| if count == 5 { |
| println!("OK, that's enough"); |
| |
| // Exit this loop |
| break; |
| } |
| } |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="nesting-and-labels"><a class="header" href="#nesting-and-labels">Nesting and labels</a></h1> |
| <p>It's possible to <code>break</code> or <code>continue</code> outer loops when dealing with nested |
| loops. In these cases, the loops must be annotated with some <code>'label</code>, and the |
| label must be passed to the <code>break</code>/<code>continue</code> statement.</p> |
| <pre><pre class="playground"><code class="language-rust editable">#![allow(unreachable_code)] |
| |
| fn main() { |
| 'outer: loop { |
| println!("Entered the outer loop"); |
| |
| 'inner: loop { |
| println!("Entered the inner loop"); |
| |
| // This would break only the inner loop |
| //break; |
| |
| // This breaks the outer loop |
| break 'outer; |
| } |
| |
| println!("This point will never be reached"); |
| } |
| |
| println!("Exited the outer loop"); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="returning-from-loops"><a class="header" href="#returning-from-loops">Returning from loops</a></h1> |
| <p>One of the uses of a <code>loop</code> is to retry an operation until it succeeds. If the |
| operation returns a value though, you might need to pass it to the rest of the |
| code: put it after the <code>break</code>, and it will be returned by the <code>loop</code> |
| expression.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let mut counter = 0; |
| |
| let result = loop { |
| counter += 1; |
| |
| if counter == 10 { |
| break counter * 2; |
| } |
| }; |
| |
| assert_eq!(result, 20); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="while"><a class="header" href="#while">while</a></h1> |
| <p>The <code>while</code> keyword can be used to run a loop while a condition is true.</p> |
| <p>Let's write the infamous <a href="https://en.wikipedia.org/wiki/Fizz_buzz">FizzBuzz</a> using a <code>while</code> loop.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // A counter variable |
| let mut n = 1; |
| |
| // Loop while `n` is less than 101 |
| while n < 101 { |
| if n % 15 == 0 { |
| println!("fizzbuzz"); |
| } else if n % 3 == 0 { |
| println!("fizz"); |
| } else if n % 5 == 0 { |
| println!("buzz"); |
| } else { |
| println!("{}", n); |
| } |
| |
| // Increment counter |
| n += 1; |
| } |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="for-loops"><a class="header" href="#for-loops">for loops</a></h1> |
| <h2 id="for-and-range"><a class="header" href="#for-and-range">for and range</a></h2> |
| <p>The <code>for in</code> construct can be used to iterate through an <code>Iterator</code>. |
| One of the easiest ways to create an iterator is to use the range |
| notation <code>a..b</code>. This yields values from <code>a</code> (inclusive) to <code>b</code> |
| (exclusive) in steps of one.</p> |
| <p>Let's write FizzBuzz using <code>for</code> instead of <code>while</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // `n` will take the values: 1, 2, ..., 100 in each iteration |
| for n in 1..101 { |
| if n % 15 == 0 { |
| println!("fizzbuzz"); |
| } else if n % 3 == 0 { |
| println!("fizz"); |
| } else if n % 5 == 0 { |
| println!("buzz"); |
| } else { |
| println!("{}", n); |
| } |
| } |
| } |
| </code></pre></pre> |
| <p>Alternatively, <code>a..=b</code> can be used for a range that is inclusive on both ends. |
| The above can be written as:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // `n` will take the values: 1, 2, ..., 100 in each iteration |
| for n in 1..=100 { |
| if n % 15 == 0 { |
| println!("fizzbuzz"); |
| } else if n % 3 == 0 { |
| println!("fizz"); |
| } else if n % 5 == 0 { |
| println!("buzz"); |
| } else { |
| println!("{}", n); |
| } |
| } |
| } |
| </code></pre></pre> |
| <h2 id="for-and-iterators"><a class="header" href="#for-and-iterators">for and iterators</a></h2> |
| <p>The <code>for in</code> construct is able to interact with an <code>Iterator</code> in several ways. |
| As discussed in the section on the <a href="flow_control/../trait/iter.html">Iterator</a> trait, by default the <code>for</code> |
| loop will apply the <code>into_iter</code> function to the collection. However, this is |
| not the only means of converting collections into iterators.</p> |
| <p><code>into_iter</code>, <code>iter</code> and <code>iter_mut</code> all handle the conversion of a collection |
| into an iterator in different ways, by providing different views on the data |
| within.</p> |
| <ul> |
| <li><code>iter</code> - This borrows each element of the collection through each iteration. |
| Thus leaving the collection untouched and available for reuse after the loop.</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let names = vec!["Bob", "Frank", "Ferris"]; |
| |
| for name in names.iter() { |
| match name { |
| &"Ferris" => println!("There is a rustacean among us!"), |
| // TODO ^ Try deleting the & and matching just "Ferris" |
| _ => println!("Hello {}", name), |
| } |
| } |
| |
| println!("names: {:?}", names); |
| } |
| </code></pre></pre> |
| <ul> |
| <li><code>into_iter</code> - This consumes the collection so that on each iteration the exact |
| data is provided. Once the collection has been consumed it is no longer |
| available for reuse as it has been 'moved' within the loop.</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn main() { |
| let names = vec!["Bob", "Frank", "Ferris"]; |
| |
| for name in names.into_iter() { |
| match name { |
| "Ferris" => println!("There is a rustacean among us!"), |
| _ => println!("Hello {}", name), |
| } |
| } |
| |
| println!("names: {:?}", names); |
| // FIXME ^ Comment out this line |
| } |
| </code></pre></pre> |
| <ul> |
| <li><code>iter_mut</code> - This mutably borrows each element of the collection, allowing for |
| the collection to be modified in place.</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let mut names = vec!["Bob", "Frank", "Ferris"]; |
| |
| for name in names.iter_mut() { |
| *name = match name { |
| &mut "Ferris" => "There is a rustacean among us!", |
| _ => "Hello", |
| } |
| } |
| |
| println!("names: {:?}", names); |
| } |
| </code></pre></pre> |
| <p>In the above snippets note the type of <code>match</code> branch, that is the key |
| difference in the types of iteration. The difference in type then of course |
| implies differing actions that are able to be performed.</p> |
| <h3 id="see-also-14"><a class="header" href="#see-also-14">See also:</a></h3> |
| <p><a href="flow_control/../trait/iter.html">Iterator</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="match"><a class="header" href="#match">match</a></h1> |
| <p>Rust provides pattern matching via the <code>match</code> keyword, which can be used like |
| a C <code>switch</code>. The first matching arm is evaluated and all possible values must be |
| covered.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let number = 13; |
| // TODO ^ Try different values for `number` |
| |
| println!("Tell me about {}", number); |
| match number { |
| // Match a single value |
| 1 => println!("One!"), |
| // Match several values |
| 2 | 3 | 5 | 7 | 11 => println!("This is a prime"), |
| // TODO ^ Try adding 13 to the list of prime values |
| // Match an inclusive range |
| 13..=19 => println!("A teen"), |
| // Handle the rest of cases |
| _ => println!("Ain't special"), |
| // TODO ^ Try commenting out this catch-all arm |
| } |
| |
| let boolean = true; |
| // Match is an expression too |
| let binary = match boolean { |
| // The arms of a match must cover all the possible values |
| false => 0, |
| true => 1, |
| // TODO ^ Try commenting out one of these arms |
| }; |
| |
| println!("{} -> {}", boolean, binary); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="destructuring"><a class="header" href="#destructuring">Destructuring</a></h1> |
| <p>A <code>match</code> block can destructure items in a variety of ways.</p> |
| <ul> |
| <li><a href="flow_control/match/destructuring/destructure_tuple.html">Destructuring Tuples</a></li> |
| <li><a href="flow_control/match/destructuring/destructure_enum.html">Destructuring Enums</a></li> |
| <li><a href="flow_control/match/destructuring/destructure_pointers.html">Destructuring Pointers</a></li> |
| <li><a href="flow_control/match/destructuring/destructure_structures.html">Destructuring Structures</a></li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="tuples-1"><a class="header" href="#tuples-1">tuples</a></h1> |
| <p>Tuples can be destructured in a <code>match</code> as follows:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let triple = (0, -2, 3); |
| // TODO ^ Try different values for `triple` |
| |
| println!("Tell me about {:?}", triple); |
| // Match can be used to destructure a tuple |
| match triple { |
| // Destructure the second and third elements |
| (0, y, z) => println!("First is `0`, `y` is {:?}, and `z` is {:?}", y, z), |
| (1, ..) => println!("First is `1` and the rest doesn't matter"), |
| // `..` can be the used ignore the rest of the tuple |
| _ => println!("It doesn't matter what they are"), |
| // `_` means don't bind the value to a variable |
| } |
| } |
| </code></pre></pre> |
| <h3 id="see-also-15"><a class="header" href="#see-also-15">See also:</a></h3> |
| <p><a href="flow_control/match/destructuring/../../../primitives/tuples.html">Tuples</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="enums-1"><a class="header" href="#enums-1">enums</a></h1> |
| <p>An <code>enum</code> is destructured similarly:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// `allow` required to silence warnings because only |
| // one variant is used. |
| #[allow(dead_code)] |
| enum Color { |
| // These 3 are specified solely by their name. |
| Red, |
| Blue, |
| Green, |
| // These likewise tie `u32` tuples to different names: color models. |
| RGB(u32, u32, u32), |
| HSV(u32, u32, u32), |
| HSL(u32, u32, u32), |
| CMY(u32, u32, u32), |
| CMYK(u32, u32, u32, u32), |
| } |
| |
| fn main() { |
| let color = Color::RGB(122, 17, 40); |
| // TODO ^ Try different variants for `color` |
| |
| println!("What color is it?"); |
| // An `enum` can be destructured using a `match`. |
| match color { |
| Color::Red => println!("The color is Red!"), |
| Color::Blue => println!("The color is Blue!"), |
| Color::Green => println!("The color is Green!"), |
| Color::RGB(r, g, b) => |
| println!("Red: {}, green: {}, and blue: {}!", r, g, b), |
| Color::HSV(h, s, v) => |
| println!("Hue: {}, saturation: {}, value: {}!", h, s, v), |
| Color::HSL(h, s, l) => |
| println!("Hue: {}, saturation: {}, lightness: {}!", h, s, l), |
| Color::CMY(c, m, y) => |
| println!("Cyan: {}, magenta: {}, yellow: {}!", c, m, y), |
| Color::CMYK(c, m, y, k) => |
| println!("Cyan: {}, magenta: {}, yellow: {}, key (black): {}!", |
| c, m, y, k), |
| // Don't need another arm because all variants have been examined |
| } |
| } |
| </code></pre></pre> |
| <h3 id="see-also-16"><a class="header" href="#see-also-16">See also:</a></h3> |
| <p><a href="flow_control/match/destructuring/../../../attribute/unused.html"><code>#[allow(...)]</code></a>, <a href="https://en.wikipedia.org/wiki/Color_model">color models</a> and <a href="flow_control/match/destructuring/../../../custom_types/enum.html"><code>enum</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="pointersref"><a class="header" href="#pointersref">pointers/ref</a></h1> |
| <p>For pointers, a distinction needs to be made between destructuring |
| and dereferencing as they are different concepts which are used |
| differently from a language like <code>C</code>.</p> |
| <ul> |
| <li>Dereferencing uses <code>*</code></li> |
| <li>Destructuring uses <code>&</code>, <code>ref</code>, and <code>ref mut</code></li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // Assign a reference of type `i32`. The `&` signifies there |
| // is a reference being assigned. |
| let reference = &4; |
| |
| match reference { |
| // If `reference` is pattern matched against `&val`, it results |
| // in a comparison like: |
| // `&i32` |
| // `&val` |
| // ^ We see that if the matching `&`s are dropped, then the `i32` |
| // should be assigned to `val`. |
| &val => println!("Got a value via destructuring: {:?}", val), |
| } |
| |
| // To avoid the `&`, you dereference before matching. |
| match *reference { |
| val => println!("Got a value via dereferencing: {:?}", val), |
| } |
| |
| // What if you don't start with a reference? `reference` was a `&` |
| // because the right side was already a reference. This is not |
| // a reference because the right side is not one. |
| let _not_a_reference = 3; |
| |
| // Rust provides `ref` for exactly this purpose. It modifies the |
| // assignment so that a reference is created for the element; this |
| // reference is assigned. |
| let ref _is_a_reference = 3; |
| |
| // Accordingly, by defining 2 values without references, references |
| // can be retrieved via `ref` and `ref mut`. |
| let value = 5; |
| let mut mut_value = 6; |
| |
| // Use `ref` keyword to create a reference. |
| match value { |
| ref r => println!("Got a reference to a value: {:?}", r), |
| } |
| |
| // Use `ref mut` similarly. |
| match mut_value { |
| ref mut m => { |
| // Got a reference. Gotta dereference it before we can |
| // add anything to it. |
| *m += 10; |
| println!("We added 10. `mut_value`: {:?}", m); |
| }, |
| } |
| } |
| </code></pre></pre> |
| <h3 id="see-also-17"><a class="header" href="#see-also-17">See also:</a></h3> |
| <p><a href="flow_control/match/destructuring/../../../scope/borrow/ref.html">The ref pattern</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="structs"><a class="header" href="#structs">structs</a></h1> |
| <p>Similarly, a <code>struct</code> can be destructured as shown:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| struct Foo { |
| x: (u32, u32), |
| y: u32, |
| } |
| |
| // Try changing the values in the struct to see what happens |
| let foo = Foo { x: (1, 2), y: 3 }; |
| |
| match foo { |
| Foo { x: (1, b), y } => println!("First of x is 1, b = {}, y = {} ", b, y), |
| |
| // you can destructure structs and rename the variables, |
| // the order is not important |
| Foo { y: 2, x: i } => println!("y is 2, i = {:?}", i), |
| |
| // and you can also ignore some variables: |
| Foo { y, .. } => println!("y = {}, we don't care about x", y), |
| // this will give an error: pattern does not mention field `x` |
| //Foo { y } => println!("y = {}", y), |
| } |
| } |
| </code></pre></pre> |
| <h3 id="see-also-18"><a class="header" href="#see-also-18">See also:</a></h3> |
| <p><a href="flow_control/match/destructuring/../../../custom_types/structs.html">Structs</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="guards"><a class="header" href="#guards">Guards</a></h1> |
| <p>A <code>match</code> <em>guard</em> can be added to filter the arm.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let pair = (2, -2); |
| // TODO ^ Try different values for `pair` |
| |
| println!("Tell me about {:?}", pair); |
| match pair { |
| (x, y) if x == y => println!("These are twins"), |
| // The ^ `if condition` part is a guard |
| (x, y) if x + y == 0 => println!("Antimatter, kaboom!"), |
| (x, _) if x % 2 == 1 => println!("The first one is odd"), |
| _ => println!("No correlation..."), |
| } |
| } |
| </code></pre></pre> |
| <p>Note that the compiler does not check arbitrary expressions for whether all |
| possible conditions have been checked. Therefore, you must use the <code>_</code> pattern |
| at the end.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let number: u8 = 4; |
| |
| match number { |
| i if i == 0 => println!("Zero"), |
| i if i > 0 => println!("Greater than zero"), |
| _ => println!("Fell through"), // This should not be possible to reach |
| } |
| } |
| </code></pre></pre> |
| <h3 id="see-also-19"><a class="header" href="#see-also-19">See also:</a></h3> |
| <p><a href="flow_control/match/../../primitives/tuples.html">Tuples</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="binding"><a class="header" href="#binding">Binding</a></h1> |
| <p>Indirectly accessing a variable makes it impossible to branch and use that |
| variable without re-binding. <code>match</code> provides the <code>@</code> sigil for binding values to |
| names:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// A function `age` which returns a `u32`. |
| fn age() -> u32 { |
| 15 |
| } |
| |
| fn main() { |
| println!("Tell me what type of person you are"); |
| |
| match age() { |
| 0 => println!("I haven't celebrated my first birthday yet"), |
| // Could `match` 1 ..= 12 directly but then what age |
| // would the child be? Instead, bind to `n` for the |
| // sequence of 1 ..= 12. Now the age can be reported. |
| n @ 1 ..= 12 => println!("I'm a child of age {:?}", n), |
| n @ 13 ..= 19 => println!("I'm a teen of age {:?}", n), |
| // Nothing bound. Return the result. |
| n => println!("I'm an old person of age {:?}", n), |
| } |
| } |
| </code></pre></pre> |
| <p>You can also use binding to "destructure" <code>enum</code> variants, such as <code>Option</code>:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn some_number() -> Option<u32> { |
| Some(42) |
| } |
| |
| fn main() { |
| match some_number() { |
| // Got `Some` variant, match if its value, bound to `n`, |
| // is equal to 42. |
| Some(n @ 42) => println!("The Answer: {}!", n), |
| // Match any other number. |
| Some(n) => println!("Not interesting... {}", n), |
| // Match anything else (`None` variant). |
| _ => (), |
| } |
| } |
| </code></pre></pre> |
| <h3 id="see-also-20"><a class="header" href="#see-also-20">See also:</a></h3> |
| <p><a href="flow_control/match/../../fn.html"><code>functions</code></a>, <a href="flow_control/match/../../custom_types/enum.html"><code>enums</code></a> and <a href="flow_control/match/../../std/option.html"><code>Option</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="if-let"><a class="header" href="#if-let">if let</a></h1> |
| <p>For some use cases, when matching enums, <code>match</code> is awkward. For example:</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>// Make `optional` of type `Option<i32>` |
| let optional = Some(7); |
| |
| match optional { |
| Some(i) => { |
| println!("This is a really long string and `{:?}`", i); |
| // ^ Needed 2 indentations just so we could destructure |
| // `i` from the option. |
| }, |
| _ => {}, |
| // ^ Required because `match` is exhaustive. Doesn't it seem |
| // like wasted space? |
| }; |
| |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p><code>if let</code> is cleaner for this use case and in addition allows various |
| failure options to be specified:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // All have type `Option<i32>` |
| let number = Some(7); |
| let letter: Option<i32> = None; |
| let emoticon: Option<i32> = None; |
| |
| // The `if let` construct reads: "if `let` destructures `number` into |
| // `Some(i)`, evaluate the block (`{}`). |
| if let Some(i) = number { |
| println!("Matched {:?}!", i); |
| } |
| |
| // If you need to specify a failure, use an else: |
| if let Some(i) = letter { |
| println!("Matched {:?}!", i); |
| } else { |
| // Destructure failed. Change to the failure case. |
| println!("Didn't match a number. Let's go with a letter!"); |
| } |
| |
| // Provide an altered failing condition. |
| let i_like_letters = false; |
| |
| if let Some(i) = emoticon { |
| println!("Matched {:?}!", i); |
| // Destructure failed. Evaluate an `else if` condition to see if the |
| // alternate failure branch should be taken: |
| } else if i_like_letters { |
| println!("Didn't match a number. Let's go with a letter!"); |
| } else { |
| // The condition evaluated false. This branch is the default: |
| println!("I don't like letters. Let's go with an emoticon :)!"); |
| } |
| } |
| </code></pre></pre> |
| <p>In the same way, <code>if let</code> can be used to match any enum value:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Our example enum |
| enum Foo { |
| Bar, |
| Baz, |
| Qux(u32) |
| } |
| |
| fn main() { |
| // Create example variables |
| let a = Foo::Bar; |
| let b = Foo::Baz; |
| let c = Foo::Qux(100); |
| |
| // Variable a matches Foo::Bar |
| if let Foo::Bar = a { |
| println!("a is foobar"); |
| } |
| |
| // Variable b does not match Foo::Bar |
| // So this will print nothing |
| if let Foo::Bar = b { |
| println!("b is foobar"); |
| } |
| |
| // Variable c matches Foo::Qux which has a value |
| // Similar to Some() in the previous example |
| if let Foo::Qux(value) = c { |
| println!("c is {}", value); |
| } |
| |
| // Binding also works with `if let` |
| if let Foo::Qux(value @ 100) = c { |
| println!("c is one hundred"); |
| } |
| } |
| </code></pre></pre> |
| <p>Another benefit is that <code>if let</code> allows us to match non-parameterized enum variants. This is true even in cases where the enum doesn't implement or derive <code>PartialEq</code>. In such cases <code>if Foo::Bar == a</code> would fail to compile, because instances of the enum cannot be equated, however <code>if let</code> will continue to work.</p> |
| <p>Would you like a challenge? Fix the following example to use <code>if let</code>:</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">// This enum purposely neither implements nor derives PartialEq. |
| // That is why comparing Foo::Bar == a fails below. |
| enum Foo {Bar} |
| |
| fn main() { |
| let a = Foo::Bar; |
| |
| // Variable a matches Foo::Bar |
| if Foo::Bar == a { |
| // ^-- this causes a compile-time error. Use `if let` instead. |
| println!("a is foobar"); |
| } |
| } |
| </code></pre></pre> |
| <h3 id="see-also-21"><a class="header" href="#see-also-21">See also:</a></h3> |
| <p><a href="flow_control/../custom_types/enum.html"><code>enum</code></a>, <a href="flow_control/../std/option.html"><code>Option</code></a>, and the <a href="https://github.com/rust-lang/rfcs/pull/160">RFC</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="while-let"><a class="header" href="#while-let">while let</a></h1> |
| <p>Similar to <code>if let</code>, <code>while let</code> can make awkward <code>match</code> sequences |
| more tolerable. Consider the following sequence that increments <code>i</code>:</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>// Make `optional` of type `Option<i32>` |
| let mut optional = Some(0); |
| |
| // Repeatedly try this test. |
| loop { |
| match optional { |
| // If `optional` destructures, evaluate the block. |
| Some(i) => { |
| if i > 9 { |
| println!("Greater than 9, quit!"); |
| optional = None; |
| } else { |
| println!("`i` is `{:?}`. Try again.", i); |
| optional = Some(i + 1); |
| } |
| // ^ Requires 3 indentations! |
| }, |
| // Quit the loop when the destructure fails: |
| _ => { break; } |
| // ^ Why should this be required? There must be a better way! |
| } |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p>Using <code>while let</code> makes this sequence much nicer:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // Make `optional` of type `Option<i32>` |
| let mut optional = Some(0); |
| |
| // This reads: "while `let` destructures `optional` into |
| // `Some(i)`, evaluate the block (`{}`). Else `break`. |
| while let Some(i) = optional { |
| if i > 9 { |
| println!("Greater than 9, quit!"); |
| optional = None; |
| } else { |
| println!("`i` is `{:?}`. Try again.", i); |
| optional = Some(i + 1); |
| } |
| // ^ Less rightward drift and doesn't require |
| // explicitly handling the failing case. |
| } |
| // ^ `if let` had additional optional `else`/`else if` |
| // clauses. `while let` does not have these. |
| } |
| </code></pre></pre> |
| <h3 id="see-also-22"><a class="header" href="#see-also-22">See also:</a></h3> |
| <p><a href="flow_control/../custom_types/enum.html"><code>enum</code></a>, <a href="flow_control/../std/option.html"><code>Option</code></a>, and the <a href="https://github.com/rust-lang/rfcs/pull/214">RFC</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="functions"><a class="header" href="#functions">Functions</a></h1> |
| <p>Functions are declared using the <code>fn</code> keyword. Its arguments are type |
| annotated, just like variables, and, if the function returns a value, the |
| return type must be specified after an arrow <code>-></code>.</p> |
| <p>The final expression in the function will be used as return value. |
| Alternatively, the <code>return</code> statement can be used to return a value earlier |
| from within the function, even from inside loops or <code>if</code> statements.</p> |
| <p>Let's rewrite FizzBuzz using functions!</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Unlike C/C++, there's no restriction on the order of function definitions |
| fn main() { |
| // We can use this function here, and define it somewhere later |
| fizzbuzz_to(100); |
| } |
| |
| // Function that returns a boolean value |
| fn is_divisible_by(lhs: u32, rhs: u32) -> bool { |
| // Corner case, early return |
| if rhs == 0 { |
| return false; |
| } |
| |
| // This is an expression, the `return` keyword is not necessary here |
| lhs % rhs == 0 |
| } |
| |
| // Functions that "don't" return a value, actually return the unit type `()` |
| fn fizzbuzz(n: u32) -> () { |
| if is_divisible_by(n, 15) { |
| println!("fizzbuzz"); |
| } else if is_divisible_by(n, 3) { |
| println!("fizz"); |
| } else if is_divisible_by(n, 5) { |
| println!("buzz"); |
| } else { |
| println!("{}", n); |
| } |
| } |
| |
| // When a function returns `()`, the return type can be omitted from the |
| // signature |
| fn fizzbuzz_to(n: u32) { |
| for n in 1..n + 1 { |
| fizzbuzz(n); |
| } |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="methods"><a class="header" href="#methods">Methods</a></h1> |
| <p>Methods are functions attached to objects. These methods have access to the |
| data of the object and its other methods via the <code>self</code> keyword. Methods are |
| defined under an <code>impl</code> block.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Point { |
| x: f64, |
| y: f64, |
| } |
| |
| // Implementation block, all `Point` methods go in here |
| impl Point { |
| // This is a static method |
| // Static methods don't need to be called by an instance |
| // These methods are generally used as constructors |
| fn origin() -> Point { |
| Point { x: 0.0, y: 0.0 } |
| } |
| |
| // Another static method, taking two arguments: |
| fn new(x: f64, y: f64) -> Point { |
| Point { x: x, y: y } |
| } |
| } |
| |
| struct Rectangle { |
| p1: Point, |
| p2: Point, |
| } |
| |
| impl Rectangle { |
| // This is an instance method |
| // `&self` is sugar for `self: &Self`, where `Self` is the type of the |
| // caller object. In this case `Self` = `Rectangle` |
| fn area(&self) -> f64 { |
| // `self` gives access to the struct fields via the dot operator |
| let Point { x: x1, y: y1 } = self.p1; |
| let Point { x: x2, y: y2 } = self.p2; |
| |
| // `abs` is a `f64` method that returns the absolute value of the |
| // caller |
| ((x1 - x2) * (y1 - y2)).abs() |
| } |
| |
| fn perimeter(&self) -> f64 { |
| let Point { x: x1, y: y1 } = self.p1; |
| let Point { x: x2, y: y2 } = self.p2; |
| |
| 2.0 * ((x1 - x2).abs() + (y1 - y2).abs()) |
| } |
| |
| // This method requires the caller object to be mutable |
| // `&mut self` desugars to `self: &mut Self` |
| fn translate(&mut self, x: f64, y: f64) { |
| self.p1.x += x; |
| self.p2.x += x; |
| |
| self.p1.y += y; |
| self.p2.y += y; |
| } |
| } |
| |
| // `Pair` owns resources: two heap allocated integers |
| struct Pair(Box<i32>, Box<i32>); |
| |
| impl Pair { |
| // This method "consumes" the resources of the caller object |
| // `self` desugars to `self: Self` |
| fn destroy(self) { |
| // Destructure `self` |
| let Pair(first, second) = self; |
| |
| println!("Destroying Pair({}, {})", first, second); |
| |
| // `first` and `second` go out of scope and get freed |
| } |
| } |
| |
| fn main() { |
| let rectangle = Rectangle { |
| // Static methods are called using double colons |
| p1: Point::origin(), |
| p2: Point::new(3.0, 4.0), |
| }; |
| |
| // Instance methods are called using the dot operator |
| // Note that the first argument `&self` is implicitly passed, i.e. |
| // `rectangle.perimeter()` === `Rectangle::perimeter(&rectangle)` |
| println!("Rectangle perimeter: {}", rectangle.perimeter()); |
| println!("Rectangle area: {}", rectangle.area()); |
| |
| let mut square = Rectangle { |
| p1: Point::origin(), |
| p2: Point::new(1.0, 1.0), |
| }; |
| |
| // Error! `rectangle` is immutable, but this method requires a mutable |
| // object |
| //rectangle.translate(1.0, 0.0); |
| // TODO ^ Try uncommenting this line |
| |
| // Okay! Mutable objects can call mutable methods |
| square.translate(1.0, 1.0); |
| |
| let pair = Pair(Box::new(1), Box::new(2)); |
| |
| pair.destroy(); |
| |
| // Error! Previous `destroy` call "consumed" `pair` |
| //pair.destroy(); |
| // TODO ^ Try uncommenting this line |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="closures"><a class="header" href="#closures">Closures</a></h1> |
| <p>Closures are functions that can capture the enclosing environment. For |
| example, a closure that captures the x variable:</p> |
| <pre><code class="language-Rust">|val| val + x |
| </code></pre> |
| <p>The syntax and capabilities of closures make them very convenient for |
| on the fly usage. Calling a closure is exactly like calling a function. |
| However, both input and return types <em>can</em> be inferred and input |
| variable names <em>must</em> be specified.</p> |
| <p>Other characteristics of closures include:</p> |
| <ul> |
| <li>using <code>||</code> instead of <code>()</code> around input variables.</li> |
| <li>optional body delimination (<code>{}</code>) for a single expression (mandatory otherwise).</li> |
| <li>the ability to capture the outer environment variables.</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // Increment via closures and functions. |
| fn function(i: i32) -> i32 { i + 1 } |
| |
| // Closures are anonymous, here we are binding them to references |
| // Annotation is identical to function annotation but is optional |
| // as are the `{}` wrapping the body. These nameless functions |
| // are assigned to appropriately named variables. |
| let closure_annotated = |i: i32| -> i32 { i + 1 }; |
| let closure_inferred = |i | i + 1 ; |
| |
| let i = 1; |
| // Call the function and closures. |
| println!("function: {}", function(i)); |
| println!("closure_annotated: {}", closure_annotated(i)); |
| println!("closure_inferred: {}", closure_inferred(i)); |
| |
| // A closure taking no arguments which returns an `i32`. |
| // The return type is inferred. |
| let one = || 1; |
| println!("closure returning one: {}", one()); |
| |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="capturing"><a class="header" href="#capturing">Capturing</a></h1> |
| <p>Closures are inherently flexible and will do what the functionality requires |
| to make the closure work without annotation. This allows capturing to |
| flexibly adapt to the use case, sometimes moving and sometimes borrowing. |
| Closures can capture variables:</p> |
| <ul> |
| <li>by reference: <code>&T</code></li> |
| <li>by mutable reference: <code>&mut T</code></li> |
| <li>by value: <code>T</code></li> |
| </ul> |
| <p>They preferentially capture variables by reference and only go lower when |
| required.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| use std::mem; |
| |
| let color = String::from("green"); |
| |
| // A closure to print `color` which immediately borrows (`&`) `color` and |
| // stores the borrow and closure in the `print` variable. It will remain |
| // borrowed until `print` is used the last time. |
| // |
| // `println!` only requires arguments by immutable reference so it doesn't |
| // impose anything more restrictive. |
| let print = || println!("`color`: {}", color); |
| |
| // Call the closure using the borrow. |
| print(); |
| |
| // `color` can be borrowed immutably again, because the closure only holds |
| // an immutable reference to `color`. |
| let _reborrow = &color; |
| print(); |
| |
| // A move or reborrow is allowed after the final use of `print` |
| let _color_moved = color; |
| |
| |
| let mut count = 0; |
| // A closure to increment `count` could take either `&mut count` or `count` |
| // but `&mut count` is less restrictive so it takes that. Immediately |
| // borrows `count`. |
| // |
| // A `mut` is required on `inc` because a `&mut` is stored inside. Thus, |
| // calling the closure mutates the closure which requires a `mut`. |
| let mut inc = || { |
| count += 1; |
| println!("`count`: {}", count); |
| }; |
| |
| // Call the closure using a mutable borrow. |
| inc(); |
| |
| // The closure still mutably borrows `count` because it is called later. |
| // An attempt to reborrow will lead to an error. |
| // let _reborrow = &count; |
| // ^ TODO: try uncommenting this line. |
| inc(); |
| |
| // The closure no longer needs to borrow `&mut count`. Therefore, it is |
| // possible to reborrow without an error |
| let _count_reborrowed = &mut count; |
| |
| |
| // A non-copy type. |
| let movable = Box::new(3); |
| |
| // `mem::drop` requires `T` so this must take by value. A copy type |
| // would copy into the closure leaving the original untouched. |
| // A non-copy must move and so `movable` immediately moves into |
| // the closure. |
| let consume = || { |
| println!("`movable`: {:?}", movable); |
| mem::drop(movable); |
| }; |
| |
| // `consume` consumes the variable so this can only be called once. |
| consume(); |
| // consume(); |
| // ^ TODO: Try uncommenting this line. |
| } |
| </code></pre></pre> |
| <p>Using <code>move</code> before vertical pipes forces closure |
| to take ownership of captured variables:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // `Vec` has non-copy semantics. |
| let haystack = vec![1, 2, 3]; |
| |
| let contains = move |needle| haystack.contains(needle); |
| |
| println!("{}", contains(&1)); |
| println!("{}", contains(&4)); |
| |
| // println!("There're {} elements in vec", haystack.len()); |
| // ^ Uncommenting above line will result in compile-time error |
| // because borrow checker doesn't allow re-using variable after it |
| // has been moved. |
| |
| // Removing `move` from closure's signature will cause closure |
| // to borrow _haystack_ variable immutably, hence _haystack_ is still |
| // available and uncommenting above line will not cause an error. |
| } |
| </code></pre></pre> |
| <h3 id="see-also-23"><a class="header" href="#see-also-23">See also:</a></h3> |
| <p><a href="fn/closures/../../std/box.html"><code>Box</code></a> and <a href="https://doc.rust-lang.org/std/mem/fn.drop.html"><code>std::mem::drop</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="as-input-parameters"><a class="header" href="#as-input-parameters">As input parameters</a></h1> |
| <p>While Rust chooses how to capture variables on the fly mostly without type |
| annotation, this ambiguity is not allowed when writing functions. When |
| taking a closure as an input parameter, the closure's complete type must be |
| annotated using one of a few <code>traits</code>. In order of decreasing restriction, |
| they are:</p> |
| <ul> |
| <li><code>Fn</code>: the closure captures by reference (<code>&T</code>)</li> |
| <li><code>FnMut</code>: the closure captures by mutable reference (<code>&mut T</code>)</li> |
| <li><code>FnOnce</code>: the closure captures by value (<code>T</code>)</li> |
| </ul> |
| <p>On a variable-by-variable basis, the compiler will capture variables in the |
| least restrictive manner possible.</p> |
| <p>For instance, consider a parameter annotated as <code>FnOnce</code>. This specifies |
| that the closure <em>may</em> capture by <code>&T</code>, <code>&mut T</code>, or <code>T</code>, but the compiler |
| will ultimately choose based on how the captured variables are used in the |
| closure.</p> |
| <p>This is because if a move is possible, then any type of borrow should also |
| be possible. Note that the reverse is not true. If the parameter is |
| annotated as <code>Fn</code>, then capturing variables by <code>&mut T</code> or <code>T</code> are not |
| allowed.</p> |
| <p>In the following example, try swapping the usage of <code>Fn</code>, <code>FnMut</code>, and |
| <code>FnOnce</code> to see what happens:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// A function which takes a closure as an argument and calls it. |
| // <F> denotes that F is a "Generic type parameter" |
| fn apply<F>(f: F) where |
| // The closure takes no input and returns nothing. |
| F: FnOnce() { |
| // ^ TODO: Try changing this to `Fn` or `FnMut`. |
| |
| f(); |
| } |
| |
| // A function which takes a closure and returns an `i32`. |
| fn apply_to_3<F>(f: F) -> i32 where |
| // The closure takes an `i32` and returns an `i32`. |
| F: Fn(i32) -> i32 { |
| |
| f(3) |
| } |
| |
| fn main() { |
| use std::mem; |
| |
| let greeting = "hello"; |
| // A non-copy type. |
| // `to_owned` creates owned data from borrowed one |
| let mut farewell = "goodbye".to_owned(); |
| |
| // Capture 2 variables: `greeting` by reference and |
| // `farewell` by value. |
| let diary = || { |
| // `greeting` is by reference: requires `Fn`. |
| println!("I said {}.", greeting); |
| |
| // Mutation forces `farewell` to be captured by |
| // mutable reference. Now requires `FnMut`. |
| farewell.push_str("!!!"); |
| println!("Then I screamed {}.", farewell); |
| println!("Now I can sleep. zzzzz"); |
| |
| // Manually calling drop forces `farewell` to |
| // be captured by value. Now requires `FnOnce`. |
| mem::drop(farewell); |
| }; |
| |
| // Call the function which applies the closure. |
| apply(diary); |
| |
| // `double` satisfies `apply_to_3`'s trait bound |
| let double = |x| 2 * x; |
| |
| println!("3 doubled: {}", apply_to_3(double)); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-24"><a class="header" href="#see-also-24">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/mem/fn.drop.html"><code>std::mem::drop</code></a>, <a href="https://doc.rust-lang.org/std/ops/trait.Fn.html"><code>Fn</code></a>, <a href="https://doc.rust-lang.org/std/ops/trait.FnMut.html"><code>FnMut</code></a>, <a href="fn/closures/../../generics.html">Generics</a>, <a href="fn/closures/../../generics/where.html">where</a> and <a href="https://doc.rust-lang.org/std/ops/trait.FnOnce.html"><code>FnOnce</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="type-anonymity"><a class="header" href="#type-anonymity">Type anonymity</a></h1> |
| <p>Closures succinctly capture variables from enclosing scopes. Does this have |
| any consequences? It surely does. Observe how using a closure as a function |
| parameter requires <a href="fn/closures/../../generics.html">generics</a>, which is necessary because of how they are |
| defined:</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>// `F` must be generic. |
| fn apply<F>(f: F) where |
| F: FnOnce() { |
| f(); |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p>When a closure is defined, the compiler implicitly creates a new |
| anonymous structure to store the captured variables inside, meanwhile |
| implementing the functionality via one of the <code>traits</code>: <code>Fn</code>, <code>FnMut</code>, or |
| <code>FnOnce</code> for this unknown type. This type is assigned to the variable which |
| is stored until calling.</p> |
| <p>Since this new type is of unknown type, any usage in a function will require |
| generics. However, an unbounded type parameter <code><T></code> would still be ambiguous |
| and not be allowed. Thus, bounding by one of the <code>traits</code>: <code>Fn</code>, <code>FnMut</code>, or |
| <code>FnOnce</code> (which it implements) is sufficient to specify its type.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// `F` must implement `Fn` for a closure which takes no |
| // inputs and returns nothing - exactly what is required |
| // for `print`. |
| fn apply<F>(f: F) where |
| F: Fn() { |
| f(); |
| } |
| |
| fn main() { |
| let x = 7; |
| |
| // Capture `x` into an anonymous type and implement |
| // `Fn` for it. Store it in `print`. |
| let print = || println!("{}", x); |
| |
| apply(print); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-25"><a class="header" href="#see-also-25">See also:</a></h3> |
| <p><a href="https://huonw.github.io/blog/2015/05/finding-closure-in-rust/">A thorough analysis</a>, <a href="https://doc.rust-lang.org/std/ops/trait.Fn.html"><code>Fn</code></a>, <a href="https://doc.rust-lang.org/std/ops/trait.FnMut.html"><code>FnMut</code></a>, |
| and <a href="https://doc.rust-lang.org/std/ops/trait.FnOnce.html"><code>FnOnce</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="input-functions"><a class="header" href="#input-functions">Input functions</a></h1> |
| <p>Since closures may be used as arguments, you might wonder if the same can be said |
| about functions. And indeed they can! If you declare a function that takes a |
| closure as parameter, then any function that satisfies the trait bound of that |
| closure can be passed as a parameter.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Define a function which takes a generic `F` argument |
| // bounded by `Fn`, and calls it |
| fn call_me<F: Fn()>(f: F) { |
| f(); |
| } |
| |
| // Define a wrapper function satisfying the `Fn` bound |
| fn function() { |
| println!("I'm a function!"); |
| } |
| |
| fn main() { |
| // Define a closure satisfying the `Fn` bound |
| let closure = || println!("I'm a closure!"); |
| |
| call_me(closure); |
| call_me(function); |
| } |
| </code></pre></pre> |
| <p>As an additional note, the <code>Fn</code>, <code>FnMut</code>, and <code>FnOnce</code> <code>traits</code> dictate how |
| a closure captures variables from the enclosing scope.</p> |
| <h3 id="see-also-26"><a class="header" href="#see-also-26">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/ops/trait.Fn.html"><code>Fn</code></a>, <a href="https://doc.rust-lang.org/std/ops/trait.FnMut.html"><code>FnMut</code></a>, and <a href="https://doc.rust-lang.org/std/ops/trait.FnOnce.html"><code>FnOnce</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="as-output-parameters"><a class="header" href="#as-output-parameters">As output parameters</a></h1> |
| <p>Closures as input parameters are possible, so returning closures as |
| output parameters should also be possible. However, anonymous |
| closure types are, by definition, unknown, so we have to use |
| <code>impl Trait</code> to return them.</p> |
| <p>The valid traits for returning a closure are:</p> |
| <ul> |
| <li><code>Fn</code></li> |
| <li><code>FnMut</code></li> |
| <li><code>FnOnce</code></li> |
| </ul> |
| <p>Beyond this, the <code>move</code> keyword must be used, which signals that all captures |
| occur by value. This is required because any captures by reference would be |
| dropped as soon as the function exited, leaving invalid references in the |
| closure.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn create_fn() -> impl Fn() { |
| let text = "Fn".to_owned(); |
| |
| move || println!("This is a: {}", text) |
| } |
| |
| fn create_fnmut() -> impl FnMut() { |
| let text = "FnMut".to_owned(); |
| |
| move || println!("This is a: {}", text) |
| } |
| |
| fn create_fnonce() -> impl FnOnce() { |
| let text = "FnOnce".to_owned(); |
| |
| move || println!("This is a: {}", text) |
| } |
| |
| fn main() { |
| let fn_plain = create_fn(); |
| let mut fn_mut = create_fnmut(); |
| let fn_once = create_fnonce(); |
| |
| fn_plain(); |
| fn_mut(); |
| fn_once(); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-27"><a class="header" href="#see-also-27">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/ops/trait.Fn.html"><code>Fn</code></a>, <a href="https://doc.rust-lang.org/std/ops/trait.FnMut.html"><code>FnMut</code></a>, <a href="fn/closures/../../generics.html">Generics</a> and <a href="fn/closures/../../trait/impl_trait.html">impl Trait</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="examples-in-std"><a class="header" href="#examples-in-std">Examples in <code>std</code></a></h1> |
| <p>This section contains a few examples of using closures from the <code>std</code> library.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="iteratorany"><a class="header" href="#iteratorany">Iterator::any</a></h1> |
| <p><code>Iterator::any</code> is a function which when passed an iterator, will return |
| <code>true</code> if any element satisfies the predicate. Otherwise <code>false</code>. Its |
| signature:</p> |
| <pre><code class="language-rust ignore">pub trait Iterator { |
| // The type being iterated over. |
| type Item; |
| |
| // `any` takes `&mut self` meaning the caller may be borrowed |
| // and modified, but not consumed. |
| fn any<F>(&mut self, f: F) -> bool where |
| // `FnMut` meaning any captured variable may at most be |
| // modified, not consumed. `Self::Item` states it takes |
| // arguments to the closure by value. |
| F: FnMut(Self::Item) -> bool {} |
| } |
| </code></pre> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let vec1 = vec![1, 2, 3]; |
| let vec2 = vec![4, 5, 6]; |
| |
| // `iter()` for vecs yields `&i32`. Destructure to `i32`. |
| println!("2 in vec1: {}", vec1.iter() .any(|&x| x == 2)); |
| // `into_iter()` for vecs yields `i32`. No destructuring required. |
| println!("2 in vec2: {}", vec2.into_iter().any(| x| x == 2)); |
| |
| let array1 = [1, 2, 3]; |
| let array2 = [4, 5, 6]; |
| |
| // `iter()` for arrays yields `&i32`. |
| println!("2 in array1: {}", array1.iter() .any(|&x| x == 2)); |
| // `into_iter()` for arrays unusually yields `&i32`. |
| println!("2 in array2: {}", array2.into_iter().any(|&x| x == 2)); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-28"><a class="header" href="#see-also-28">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.any"><code>std::iter::Iterator::any</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="searching-through-iterators"><a class="header" href="#searching-through-iterators">Searching through iterators</a></h1> |
| <p><code>Iterator::find</code> is a function which iterates over an iterator and searches for the |
| first value which satisfies some condition. If none of the values satisfy the |
| condition, it returns <code>None</code>. Its signature:</p> |
| <pre><code class="language-rust ignore">pub trait Iterator { |
| // The type being iterated over. |
| type Item; |
| |
| // `find` takes `&mut self` meaning the caller may be borrowed |
| // and modified, but not consumed. |
| fn find<P>(&mut self, predicate: P) -> Option<Self::Item> where |
| // `FnMut` meaning any captured variable may at most be |
| // modified, not consumed. `&Self::Item` states it takes |
| // arguments to the closure by reference. |
| P: FnMut(&Self::Item) -> bool {} |
| } |
| </code></pre> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let vec1 = vec![1, 2, 3]; |
| let vec2 = vec![4, 5, 6]; |
| |
| // `iter()` for vecs yields `&i32`. |
| let mut iter = vec1.iter(); |
| // `into_iter()` for vecs yields `i32`. |
| let mut into_iter = vec2.into_iter(); |
| |
| // `iter()` for vecs yields `&i32`, and we want to reference one of its |
| // items, so we have to destructure `&&i32` to `i32` |
| println!("Find 2 in vec1: {:?}", iter .find(|&&x| x == 2)); |
| // `into_iter()` for vecs yields `i32`, and we want to reference one of |
| // its items, so we have to destructure `&i32` to `i32` |
| println!("Find 2 in vec2: {:?}", into_iter.find(| &x| x == 2)); |
| |
| let array1 = [1, 2, 3]; |
| let array2 = [4, 5, 6]; |
| |
| // `iter()` for arrays yields `&i32` |
| println!("Find 2 in array1: {:?}", array1.iter() .find(|&&x| x == 2)); |
| // `into_iter()` for arrays unusually yields `&i32` |
| println!("Find 2 in array2: {:?}", array2.into_iter().find(|&&x| x == 2)); |
| } |
| </code></pre></pre> |
| <p><code>Iterator::find</code> gives you a reference to the item. But if you want the <em>index</em> of the |
| item, use <code>Iterator::position</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let vec = vec![1, 9, 3, 3, 13, 2]; |
| |
| let index_of_first_even_number = vec.iter().position(|x| x % 2 == 0); |
| assert_eq!(index_of_first_even_number, Some(5)); |
| |
| |
| let index_of_first_negative_number = vec.iter().position(|x| x < &0); |
| assert_eq!(index_of_first_negative_number, None); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-29"><a class="header" href="#see-also-29">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find"><code>std::iter::Iterator::find</code></a></p> |
| <p><a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.find_map"><code>std::iter::Iterator::find_map</code></a></p> |
| <p><a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.position"><code>std::iter::Iterator::position</code></a></p> |
| <p><a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.rposition"><code>std::iter::Iterator::rposition</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="higher-order-functions"><a class="header" href="#higher-order-functions">Higher Order Functions</a></h1> |
| <p>Rust provides Higher Order Functions (HOF). These are functions that |
| take one or more functions and/or produce a more useful function. HOFs |
| and lazy iterators give Rust its functional flavor.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn is_odd(n: u32) -> bool { |
| n % 2 == 1 |
| } |
| |
| fn main() { |
| println!("Find the sum of all the squared odd numbers under 1000"); |
| let upper = 1000; |
| |
| // Imperative approach |
| // Declare accumulator variable |
| let mut acc = 0; |
| // Iterate: 0, 1, 2, ... to infinity |
| for n in 0.. { |
| // Square the number |
| let n_squared = n * n; |
| |
| if n_squared >= upper { |
| // Break loop if exceeded the upper limit |
| break; |
| } else if is_odd(n_squared) { |
| // Accumulate value, if it's odd |
| acc += n_squared; |
| } |
| } |
| println!("imperative style: {}", acc); |
| |
| // Functional approach |
| let sum_of_squared_odd_numbers: u32 = |
| (0..).map(|n| n * n) // All natural numbers squared |
| .take_while(|&n_squared| n_squared < upper) // Below upper limit |
| .filter(|&n_squared| is_odd(n_squared)) // That are odd |
| .fold(0, |acc, n_squared| acc + n_squared); // Sum them |
| println!("functional style: {}", sum_of_squared_odd_numbers); |
| } |
| </code></pre></pre> |
| <p><a href="https://doc.rust-lang.org/core/option/enum.Option.html">Option</a> |
| and |
| <a href="https://doc.rust-lang.org/core/iter/trait.Iterator.html">Iterator</a> |
| implement their fair share of HOFs.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="diverging-functions"><a class="header" href="#diverging-functions">Diverging functions</a></h1> |
| <p>Diverging functions never return. They are marked using <code>!</code>, which is an empty type.</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>fn foo() -> ! { |
| panic!("This call never returns."); |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p>As opposed to all the other types, this one cannot be instantiated, because the |
| set of all possible values this type can have is empty. Note that, it is |
| different from the <code>()</code> type, which has exactly one possible value.</p> |
| <p>For example, this function returns as usual, although there is no information |
| in the return value.</p> |
| <pre><pre class="playground"><code class="language-rust">fn some_fn() { |
| () |
| } |
| |
| fn main() { |
| let a: () = some_fn(); |
| println!("This function returns and you can see this line.") |
| } |
| </code></pre></pre> |
| <p>As opposed to this function, which will never return the control back to the caller.</p> |
| <pre><code class="language-rust ignore">#![feature(never_type)] |
| |
| fn main() { |
| let x: ! = panic!("This call never returns."); |
| println!("You will never see this line!"); |
| } |
| </code></pre> |
| <p>Although this might seem like an abstract concept, it is in fact very useful and |
| often handy. The main advantage of this type is that it can be cast to any other |
| one and therefore used at places where an exact type is required, for instance |
| in <code>match</code> branches. This allows us to write code like this:</p> |
| <pre><pre class="playground"><code class="language-rust">fn main() { |
| fn sum_odd_numbers(up_to: u32) -> u32 { |
| let mut acc = 0; |
| for i in 0..up_to { |
| // Notice that the return type of this match expression must be u32 |
| // because of the type of the "addition" variable. |
| let addition: u32 = match i%2 == 1 { |
| // The "i" variable is of type u32, which is perfectly fine. |
| true => i, |
| // On the other hand, the "continue" expression does not return |
| // u32, but it is still fine, because it never returns and therefore |
| // does not violate the type requirements of the match expression. |
| false => continue, |
| }; |
| acc += addition; |
| } |
| acc |
| } |
| println!("Sum of odd numbers up to 9 (excluding): {}", sum_odd_numbers(9)); |
| } |
| </code></pre></pre> |
| <p>It is also the return type of functions that loop forever (e.g. <code>loop {}</code>) like |
| network servers or functions that terminate the process (e.g. <code>exit()</code>).</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="modules"><a class="header" href="#modules">Modules</a></h1> |
| <p>Rust provides a powerful module system that can be used to hierarchically split |
| code in logical units (modules), and manage visibility (public/private) between |
| them.</p> |
| <p>A module is a collection of items: functions, structs, traits, <code>impl</code> blocks, |
| and even other modules.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="visibility"><a class="header" href="#visibility">Visibility</a></h1> |
| <p>By default, the items in a module have private visibility, but this can be |
| overridden with the <code>pub</code> modifier. Only the public items of a module can be |
| accessed from outside the module scope.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// A module named `my_mod` |
| mod my_mod { |
| // Items in modules default to private visibility. |
| fn private_function() { |
| println!("called `my_mod::private_function()`"); |
| } |
| |
| // Use the `pub` modifier to override default visibility. |
| pub fn function() { |
| println!("called `my_mod::function()`"); |
| } |
| |
| // Items can access other items in the same module, |
| // even when private. |
| pub fn indirect_access() { |
| print!("called `my_mod::indirect_access()`, that\n> "); |
| private_function(); |
| } |
| |
| // Modules can also be nested |
| pub mod nested { |
| pub fn function() { |
| println!("called `my_mod::nested::function()`"); |
| } |
| |
| #[allow(dead_code)] |
| fn private_function() { |
| println!("called `my_mod::nested::private_function()`"); |
| } |
| |
| // Functions declared using `pub(in path)` syntax are only visible |
| // within the given path. `path` must be a parent or ancestor module |
| pub(in crate::my_mod) fn public_function_in_my_mod() { |
| print!("called `my_mod::nested::public_function_in_my_mod()`, that\n> "); |
| public_function_in_nested(); |
| } |
| |
| // Functions declared using `pub(self)` syntax are only visible within |
| // the current module, which is the same as leaving them private |
| pub(self) fn public_function_in_nested() { |
| println!("called `my_mod::nested::public_function_in_nested()`"); |
| } |
| |
| // Functions declared using `pub(super)` syntax are only visible within |
| // the parent module |
| pub(super) fn public_function_in_super_mod() { |
| println!("called `my_mod::nested::public_function_in_super_mod()`"); |
| } |
| } |
| |
| pub fn call_public_function_in_my_mod() { |
| print!("called `my_mod::call_public_function_in_my_mod()`, that\n> "); |
| nested::public_function_in_my_mod(); |
| print!("> "); |
| nested::public_function_in_super_mod(); |
| } |
| |
| // pub(crate) makes functions visible only within the current crate |
| pub(crate) fn public_function_in_crate() { |
| println!("called `my_mod::public_function_in_crate()`"); |
| } |
| |
| // Nested modules follow the same rules for visibility |
| mod private_nested { |
| #[allow(dead_code)] |
| pub fn function() { |
| println!("called `my_mod::private_nested::function()`"); |
| } |
| |
| // Private parent items will still restrict the visibility of a child item, |
| // even if it is declared as visible within a bigger scope. |
| #[allow(dead_code)] |
| pub(crate) fn restricted_function() { |
| println!("called `my_mod::private_nested::restricted_function()`"); |
| } |
| } |
| } |
| |
| fn function() { |
| println!("called `function()`"); |
| } |
| |
| fn main() { |
| // Modules allow disambiguation between items that have the same name. |
| function(); |
| my_mod::function(); |
| |
| // Public items, including those inside nested modules, can be |
| // accessed from outside the parent module. |
| my_mod::indirect_access(); |
| my_mod::nested::function(); |
| my_mod::call_public_function_in_my_mod(); |
| |
| // pub(crate) items can be called from anywhere in the same crate |
| my_mod::public_function_in_crate(); |
| |
| // pub(in path) items can only be called from within the module specified |
| // Error! function `public_function_in_my_mod` is private |
| //my_mod::nested::public_function_in_my_mod(); |
| // TODO ^ Try uncommenting this line |
| |
| // Private items of a module cannot be directly accessed, even if |
| // nested in a public module: |
| |
| // Error! `private_function` is private |
| //my_mod::private_function(); |
| // TODO ^ Try uncommenting this line |
| |
| // Error! `private_function` is private |
| //my_mod::nested::private_function(); |
| // TODO ^ Try uncommenting this line |
| |
| // Error! `private_nested` is a private module |
| //my_mod::private_nested::function(); |
| // TODO ^ Try uncommenting this line |
| |
| // Error! `private_nested` is a private module |
| //my_mod::private_nested::restricted_function(); |
| // TODO ^ Try uncommenting this line |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="struct-visibility"><a class="header" href="#struct-visibility">Struct visibility</a></h1> |
| <p>Structs have an extra level of visibility with their fields. The visibility |
| defaults to private, and can be overridden with the <code>pub</code> modifier. This |
| visibility only matters when a struct is accessed from outside the module |
| where it is defined, and has the goal of hiding information (encapsulation).</p> |
| <pre><pre class="playground"><code class="language-rust editable">mod my { |
| // A public struct with a public field of generic type `T` |
| pub struct OpenBox<T> { |
| pub contents: T, |
| } |
| |
| // A public struct with a private field of generic type `T` |
| #[allow(dead_code)] |
| pub struct ClosedBox<T> { |
| contents: T, |
| } |
| |
| impl<T> ClosedBox<T> { |
| // A public constructor method |
| pub fn new(contents: T) -> ClosedBox<T> { |
| ClosedBox { |
| contents: contents, |
| } |
| } |
| } |
| } |
| |
| fn main() { |
| // Public structs with public fields can be constructed as usual |
| let open_box = my::OpenBox { contents: "public information" }; |
| |
| // and their fields can be normally accessed. |
| println!("The open box contains: {}", open_box.contents); |
| |
| // Public structs with private fields cannot be constructed using field names. |
| // Error! `ClosedBox` has private fields |
| //let closed_box = my::ClosedBox { contents: "classified information" }; |
| // TODO ^ Try uncommenting this line |
| |
| // However, structs with private fields can be created using |
| // public constructors |
| let _closed_box = my::ClosedBox::new("classified information"); |
| |
| // and the private fields of a public struct cannot be accessed. |
| // Error! The `contents` field is private |
| //println!("The closed box contains: {}", _closed_box.contents); |
| // TODO ^ Try uncommenting this line |
| } |
| </code></pre></pre> |
| <h3 id="see-also-30"><a class="header" href="#see-also-30">See also:</a></h3> |
| <p><a href="mod/../generics.html">generics</a> and <a href="mod/../fn/methods.html">methods</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="the-use-declaration"><a class="header" href="#the-use-declaration">The <code>use</code> declaration</a></h1> |
| <p>The <code>use</code> declaration can be used to bind a full path to a new name, for easier |
| access. It is often used like this:</p> |
| <pre><code class="language-rust editable ignore">use crate::deeply::nested::{ |
| my_first_function, |
| my_second_function, |
| AndATraitType |
| }; |
| |
| fn main() { |
| my_first_function(); |
| } |
| </code></pre> |
| <p>You can use the <code>as</code> keyword to bind imports to a different name:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Bind the `deeply::nested::function` path to `other_function`. |
| use deeply::nested::function as other_function; |
| |
| fn function() { |
| println!("called `function()`"); |
| } |
| |
| mod deeply { |
| pub mod nested { |
| pub fn function() { |
| println!("called `deeply::nested::function()`"); |
| } |
| } |
| } |
| |
| fn main() { |
| // Easier access to `deeply::nested::function` |
| other_function(); |
| |
| println!("Entering block"); |
| { |
| // This is equivalent to `use deeply::nested::function as function`. |
| // This `function()` will shadow the outer one. |
| use crate::deeply::nested::function; |
| |
| // `use` bindings have a local scope. In this case, the |
| // shadowing of `function()` is only in this block. |
| function(); |
| |
| println!("Leaving block"); |
| } |
| |
| function(); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="super-and-self"><a class="header" href="#super-and-self"><code>super</code> and <code>self</code></a></h1> |
| <p>The <code>super</code> and <code>self</code> keywords can be used in the path to remove ambiguity |
| when accessing items and to prevent unnecessary hardcoding of paths.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn function() { |
| println!("called `function()`"); |
| } |
| |
| mod cool { |
| pub fn function() { |
| println!("called `cool::function()`"); |
| } |
| } |
| |
| mod my { |
| fn function() { |
| println!("called `my::function()`"); |
| } |
| |
| mod cool { |
| pub fn function() { |
| println!("called `my::cool::function()`"); |
| } |
| } |
| |
| pub fn indirect_call() { |
| // Let's access all the functions named `function` from this scope! |
| print!("called `my::indirect_call()`, that\n> "); |
| |
| // The `self` keyword refers to the current module scope - in this case `my`. |
| // Calling `self::function()` and calling `function()` directly both give |
| // the same result, because they refer to the same function. |
| self::function(); |
| function(); |
| |
| // We can also use `self` to access another module inside `my`: |
| self::cool::function(); |
| |
| // The `super` keyword refers to the parent scope (outside the `my` module). |
| super::function(); |
| |
| // This will bind to the `cool::function` in the *crate* scope. |
| // In this case the crate scope is the outermost scope. |
| { |
| use crate::cool::function as root_function; |
| root_function(); |
| } |
| } |
| } |
| |
| fn main() { |
| my::indirect_call(); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="file-hierarchy"><a class="header" href="#file-hierarchy">File hierarchy</a></h1> |
| <p>Modules can be mapped to a file/directory hierarchy. Let's break down the |
| <a href="mod/visibility.html">visibility example</a> in files:</p> |
| <pre><code class="language-shell">$ tree . |
| . |
| |-- my |
| | |-- inaccessible.rs |
| | |-- mod.rs |
| | `-- nested.rs |
| `-- split.rs |
| </code></pre> |
| <p>In <code>split.rs</code>:</p> |
| <pre><code class="language-rust ignore">// This declaration will look for a file named `my.rs` or `my/mod.rs` and will |
| // insert its contents inside a module named `my` under this scope |
| mod my; |
| |
| fn function() { |
| println!("called `function()`"); |
| } |
| |
| fn main() { |
| my::function(); |
| |
| function(); |
| |
| my::indirect_access(); |
| |
| my::nested::function(); |
| } |
| |
| </code></pre> |
| <p>In <code>my/mod.rs</code>:</p> |
| <pre><code class="language-rust ignore">// Similarly `mod inaccessible` and `mod nested` will locate the `nested.rs` |
| // and `inaccessible.rs` files and insert them here under their respective |
| // modules |
| mod inaccessible; |
| pub mod nested; |
| |
| pub fn function() { |
| println!("called `my::function()`"); |
| } |
| |
| fn private_function() { |
| println!("called `my::private_function()`"); |
| } |
| |
| pub fn indirect_access() { |
| print!("called `my::indirect_access()`, that\n> "); |
| |
| private_function(); |
| } |
| </code></pre> |
| <p>In <code>my/nested.rs</code>:</p> |
| <pre><code class="language-rust ignore">pub fn function() { |
| println!("called `my::nested::function()`"); |
| } |
| |
| #[allow(dead_code)] |
| fn private_function() { |
| println!("called `my::nested::private_function()`"); |
| } |
| </code></pre> |
| <p>In <code>my/inaccessible.rs</code>:</p> |
| <pre><code class="language-rust ignore">#[allow(dead_code)] |
| pub fn public_function() { |
| println!("called `my::inaccessible::public_function()`"); |
| } |
| </code></pre> |
| <p>Let's check that things still work as before:</p> |
| <pre><code class="language-shell">$ rustc split.rs && ./split |
| called `my::function()` |
| called `function()` |
| called `my::indirect_access()`, that |
| > called `my::private_function()` |
| called `my::nested::function()` |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="crates"><a class="header" href="#crates">Crates</a></h1> |
| <p>A crate is a compilation unit in Rust. Whenever <code>rustc some_file.rs</code> is called, |
| <code>some_file.rs</code> is treated as the <em>crate file</em>. If <code>some_file.rs</code> has <code>mod</code> |
| declarations in it, then the contents of the module files would be inserted in |
| places where <code>mod</code> declarations in the crate file are found, <em>before</em> running |
| the compiler over it. In other words, modules do <em>not</em> get compiled |
| individually, only crates get compiled.</p> |
| <p>A crate can be compiled into a binary or into a library. By default, <code>rustc</code> |
| will produce a binary from a crate. This behavior can be overridden by passing |
| the <code>--crate-type</code> flag to <code>lib</code>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="creating-a-library"><a class="header" href="#creating-a-library">Creating a Library</a></h1> |
| <p>Let's create a library, and then see how to link it to another crate.</p> |
| <pre><code class="language-rust ignore">pub fn public_function() { |
| println!("called rary's `public_function()`"); |
| } |
| |
| fn private_function() { |
| println!("called rary's `private_function()`"); |
| } |
| |
| pub fn indirect_access() { |
| print!("called rary's `indirect_access()`, that\n> "); |
| |
| private_function(); |
| } |
| </code></pre> |
| <pre><code class="language-shell">$ rustc --crate-type=lib rary.rs |
| $ ls lib* |
| library.rlib |
| </code></pre> |
| <p>Libraries get prefixed with "lib", and by default they get named after their |
| crate file, but this default name can be overridden by passing |
| the <code>--crate-name</code> option to <code>rustc</code> or by using the <a href="crates/../attribute/crate.html"><code>crate_name</code> |
| attribute</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="using-a-library"><a class="header" href="#using-a-library">Using a Library</a></h1> |
| <p>To link a crate to this new library you may use <code>rustc</code>'s <code>--extern</code> flag. All |
| of its items will then be imported under a module named the same as the library. |
| This module generally behaves the same way as any other module.</p> |
| <pre><code class="language-rust ignore">// extern crate rary; // May be required for Rust 2015 edition or earlier |
| |
| fn main() { |
| rary::public_function(); |
| |
| // Error! `private_function` is private |
| //rary::private_function(); |
| |
| rary::indirect_access(); |
| } |
| </code></pre> |
| <pre><code class="language-txt"># Where library.rlib is the path to the compiled library, assumed that it's |
| # in the same directory here: |
| $ rustc executable.rs --extern rary=library.rlib --edition=2018 && ./executable |
| called rary's `public_function()` |
| called rary's `indirect_access()`, that |
| > called rary's `private_function()` |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="cargo"><a class="header" href="#cargo">Cargo</a></h1> |
| <p><code>cargo</code> is the official Rust package management tool. It has lots of really |
| useful features to improve code quality and developer velocity! These include</p> |
| <ul> |
| <li>Dependency management and integration with <a href="https://crates.io">crates.io</a> (the |
| official Rust package registry)</li> |
| <li>Awareness of unit tests</li> |
| <li>Awareness of benchmarks</li> |
| </ul> |
| <p>This chapter will go through some quick basics, but you can find the |
| comprehensive docs in <a href="https://doc.rust-lang.org/cargo/">The Cargo Book</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="dependencies"><a class="header" href="#dependencies">Dependencies</a></h1> |
| <p>Most programs have dependencies on some libraries. If you have ever managed |
| dependencies by hand, you know how much of a pain this can be. Luckily, the Rust |
| ecosystem comes standard with <code>cargo</code>! <code>cargo</code> can manage dependencies for a |
| project.</p> |
| <p>To create a new Rust project,</p> |
| <pre><code class="language-sh"># A binary |
| cargo new foo |
| |
| # OR A library |
| cargo new --lib foo |
| </code></pre> |
| <p>For the rest of this chapter, let's assume we are making a binary, rather than |
| a library, but all of the concepts are the same.</p> |
| <p>After the above commands, you should see a file hierarchy like this:</p> |
| <pre><code class="language-txt">foo |
| ├── Cargo.toml |
| └── src |
| └── main.rs |
| </code></pre> |
| <p>The <code>main.rs</code> is the root source file for your new project -- nothing new there. |
| The <code>Cargo.toml</code> is the config file for <code>cargo</code> for this project (<code>foo</code>). If you |
| look inside it, you should see something like this:</p> |
| <pre><code class="language-toml">[package] |
| name = "foo" |
| version = "0.1.0" |
| authors = ["mark"] |
| |
| [dependencies] |
| </code></pre> |
| <p>The <code>name</code> field under <code>[package]</code> determines the name of the project. This is |
| used by <code>crates.io</code> if you publish the crate (more later). It is also the name |
| of the output binary when you compile.</p> |
| <p>The <code>version</code> field is a crate version number using <a href="http://semver.org/">Semantic |
| Versioning</a>.</p> |
| <p>The <code>authors</code> field is a list of authors used when publishing the crate.</p> |
| <p>The <code>[dependencies]</code> section lets you add dependencies for your project.</p> |
| <p>For example, suppose that we want our program to have a great CLI. You can find |
| lots of great packages on <a href="https://crates.io">crates.io</a> (the official Rust |
| package registry). One popular choice is <a href="https://crates.io/crates/clap">clap</a>. |
| As of this writing, the most recent published version of <code>clap</code> is <code>2.27.1</code>. To |
| add a dependency to our program, we can simply add the following to our |
| <code>Cargo.toml</code> under <code>[dependencies]</code>: <code>clap = "2.27.1"</code>. And that's it! You can start using |
| <code>clap</code> in your program.</p> |
| <p><code>cargo</code> also supports <a href="https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html">other types of dependencies</a>. Here is just |
| a small sampling:</p> |
| <pre><code class="language-toml">[package] |
| name = "foo" |
| version = "0.1.0" |
| authors = ["mark"] |
| |
| [dependencies] |
| clap = "2.27.1" # from crates.io |
| rand = { git = "https://github.com/rust-lang-nursery/rand" } # from online repo |
| bar = { path = "../bar" } # from a path in the local filesystem |
| </code></pre> |
| <p><code>cargo</code> is more than a dependency manager. All of the available |
| configuration options are listed in the <a href="https://doc.rust-lang.org/cargo/reference/manifest.html">format specification</a> of |
| <code>Cargo.toml</code>.</p> |
| <p>To build our project we can execute <code>cargo build</code> anywhere in the project |
| directory (including subdirectories!). We can also do <code>cargo run</code> to build and |
| run. Notice that these commands will resolve all dependencies, download crates |
| if needed, and build everything, including your crate. (Note that it only |
| rebuilds what it has not already built, similar to <code>make</code>).</p> |
| <p>Voila! That's all there is to it!</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="conventions"><a class="header" href="#conventions">Conventions</a></h1> |
| <p>In the previous chapter, we saw the following directory hierarchy:</p> |
| <pre><code class="language-txt">foo |
| ├── Cargo.toml |
| └── src |
| └── main.rs |
| </code></pre> |
| <p>Suppose that we wanted to have two binaries in the same project, though. What |
| then?</p> |
| <p>It turns out that <code>cargo</code> supports this. The default binary name is <code>main</code>, as |
| we saw before, but you can add additional binaries by placing them in a <code>bin/</code> |
| directory:</p> |
| <pre><code class="language-txt">foo |
| ├── Cargo.toml |
| └── src |
| ├── main.rs |
| └── bin |
| └── my_other_bin.rs |
| </code></pre> |
| <p>To tell <code>cargo</code> to compile or run this binary as opposed to the default or other |
| binaries, we just pass <code>cargo</code> the <code>--bin my_other_bin</code> flag, where <code>my_other_bin</code> |
| is the name of the binary we want to work with.</p> |
| <p>In addition to extra binaries, <code>cargo</code> supports <a href="https://doc.rust-lang.org/cargo/guide/project-layout.html">more features</a> such as |
| benchmarks, tests, and examples.</p> |
| <p>In the next chapter, we will look more closely at tests.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="testing"><a class="header" href="#testing">Testing</a></h1> |
| <p>As we know testing is integral to any piece of software! Rust has first-class |
| support for unit and integration testing (<a href="https://doc.rust-lang.org/book/ch11-00-testing.html">see this |
| chapter</a> in |
| TRPL).</p> |
| <p>From the testing chapters linked above, we see how to write unit tests and |
| integration tests. Organizationally, we can place unit tests in the modules they |
| test and integration tests in their own <code>tests/</code> directory:</p> |
| <pre><code class="language-txt">foo |
| ├── Cargo.toml |
| ├── src |
| │ └── main.rs |
| │ └── lib.rs |
| └── tests |
| ├── my_test.rs |
| └── my_other_test.rs |
| </code></pre> |
| <p>Each file in <code>tests</code> is a separate |
| <a href="https://doc.rust-lang.org/book/ch11-03-test-organization.html#integration-tests">integration test</a>, |
| i.e. a test that is meant to test your library as if it were being called from a dependent |
| crate.</p> |
| <p>The <a href="cargo/../testing.html">Testing</a> chapter elaborates on the three different testing styles: |
| <a href="cargo/../testing/unit_testing.html">Unit</a>, <a href="cargo/../testing/doc_testing.html">Doc</a>, and <a href="cargo/../testing/unit_testing.html">Integration</a>. </p> |
| <p><code>cargo</code> naturally provides an easy way to run all of your tests!</p> |
| <pre><code class="language-shell">$ cargo test |
| </code></pre> |
| <p>You should see output like this:</p> |
| <pre><code class="language-shell">$ cargo test |
| Compiling blah v0.1.0 (file:///nobackup/blah) |
| Finished dev [unoptimized + debuginfo] target(s) in 0.89 secs |
| Running target/debug/deps/blah-d3b32b97275ec472 |
| |
| running 3 tests |
| test test_bar ... ok |
| test test_baz ... ok |
| test test_foo_bar ... ok |
| test test_foo ... ok |
| |
| test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| </code></pre> |
| <p>You can also run tests whose name matches a pattern:</p> |
| <pre><code class="language-shell">$ cargo test test_foo |
| </code></pre> |
| <pre><code class="language-shell">$ cargo test test_foo |
| Compiling blah v0.1.0 (file:///nobackup/blah) |
| Finished dev [unoptimized + debuginfo] target(s) in 0.35 secs |
| Running target/debug/deps/blah-d3b32b97275ec472 |
| |
| running 2 tests |
| test test_foo ... ok |
| test test_foo_bar ... ok |
| |
| test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out |
| </code></pre> |
| <p>One word of caution: Cargo may run multiple tests concurrently, so make sure |
| that they don't race with each other. </p> |
| <p>One example of this concurrency causing issues is if two tests output to a |
| file, such as below:</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>#[cfg(test)] |
| mod tests { |
| // Import the necessary modules |
| use std::fs::OpenOptions; |
| use std::io::Write; |
| |
| // This test writes to a file |
| #[test] |
| fn test_file() { |
| // Opens the file ferris.txt or creates one if it doesn't exist. |
| let mut file = OpenOptions::new() |
| .append(true) |
| .create(true) |
| .open("ferris.txt") |
| .expect("Failed to open ferris.txt"); |
| |
| // Print "Ferris" 5 times. |
| for _ in 0..5 { |
| file.write_all("Ferris\n".as_bytes()) |
| .expect("Could not write to ferris.txt"); |
| } |
| } |
| |
| // This test tries to write to the same file |
| #[test] |
| fn test_file_also() { |
| // Opens the file ferris.txt or creates one if it doesn't exist. |
| let mut file = OpenOptions::new() |
| .append(true) |
| .create(true) |
| .open("ferris.txt") |
| .expect("Failed to open ferris.txt"); |
| |
| // Print "Corro" 5 times. |
| for _ in 0..5 { |
| file.write_all("Corro\n".as_bytes()) |
| .expect("Could not write to ferris.txt"); |
| } |
| } |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p>Although the intent is to get the following:</p> |
| <pre><code class="language-shell">$ cat ferris.txt |
| Ferris |
| Ferris |
| Ferris |
| Ferris |
| Ferris |
| Corro |
| Corro |
| Corro |
| Corro |
| Corro |
| </code></pre> |
| <p>What actually gets put into <code>ferris.txt</code> is this:</p> |
| <pre><code class="language-shell">$ cargo test test_foo |
| Corro |
| Ferris |
| Corro |
| Ferris |
| Corro |
| Ferris |
| Corro |
| Ferris |
| Corro |
| Ferris |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="build-scripts"><a class="header" href="#build-scripts">Build Scripts</a></h1> |
| <p>Sometimes a normal build from <code>cargo</code> is not enough. Perhaps your crate needs |
| some pre-requisites before <code>cargo</code> will successfully compile, things like code |
| generation, or some native code that needs to be compiled. To solve this problem |
| we have build scripts that Cargo can run.</p> |
| <p>To add a build script to your package it can either be specified in the |
| <code>Cargo.toml</code> as follows:</p> |
| <pre><code class="language-toml">[package] |
| ... |
| build = "build.rs" |
| </code></pre> |
| <p>Otherwise Cargo will look for a <code>build.rs</code> file in the project directory by |
| default.</p> |
| <h2 id="how-to-use-a-build-script"><a class="header" href="#how-to-use-a-build-script">How to use a build script</a></h2> |
| <p>The build script is simply another Rust file that will be compiled and invoked |
| prior to compiling anything else in the package. Hence it can be used to fulfill |
| pre-requisites of your crate.</p> |
| <p>Cargo provides the script with inputs via environment variables <a href="https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts">specified |
| here</a> that can be used.</p> |
| <p>The script provides output via stdout. All lines printed are written to |
| <code>target/debug/build/<pkg>/output</code>. Further, lines prefixed with <code>cargo:</code> will be |
| interpreted by Cargo directly and hence can be used to define parameters for the |
| package's compilation.</p> |
| <p>For further specification and examples have a read of the |
| <a href="https://doc.rust-lang.org/cargo/reference/build-scripts.html">Cargo specification</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="attributes"><a class="header" href="#attributes">Attributes</a></h1> |
| <p>An attribute is metadata applied to some module, crate or item. This metadata |
| can be used to/for:</p> |
| <!-- TODO: Link these to their respective examples --> |
| <ul> |
| <li><a href="attribute/cfg.html">conditional compilation of code</a></li> |
| <li><a href="attribute/crate.html">set crate name, version and type (binary or library)</a></li> |
| <li>disable <a href="https://en.wikipedia.org/wiki/Lint_%28software%29">lints</a> (warnings)</li> |
| <li>enable compiler features (macros, glob imports, etc.)</li> |
| <li>link to a foreign library</li> |
| <li>mark functions as unit tests</li> |
| <li>mark functions that will be part of a benchmark</li> |
| </ul> |
| <p>When attributes apply to a whole crate, their syntax is <code>#![crate_attribute]</code>, |
| and when they apply to a module or item, the syntax is <code>#[item_attribute]</code> |
| (notice the missing bang <code>!</code>).</p> |
| <p>Attributes can take arguments with different syntaxes:</p> |
| <ul> |
| <li><code>#[attribute = "value"]</code></li> |
| <li><code>#[attribute(key = "value")]</code></li> |
| <li><code>#[attribute(value)]</code></li> |
| </ul> |
| <p>Attributes can have multiple values and can be separated over multiple lines, too:</p> |
| <pre><code class="language-rust ignore">#[attribute(value, value2)] |
| |
| |
| #[attribute(value, value2, value3, |
| value4, value5)] |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="dead_code"><a class="header" href="#dead_code"><code>dead_code</code></a></h1> |
| <p>The compiler provides a <code>dead_code</code> |
| <a href="https://en.wikipedia.org/wiki/Lint_%28software%29"><em>lint</em></a> that will warn |
| about unused functions. An <em>attribute</em> can be used to disable the lint.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn used_function() {} |
| |
| // `#[allow(dead_code)]` is an attribute that disables the `dead_code` lint |
| #[allow(dead_code)] |
| fn unused_function() {} |
| |
| fn noisy_unused_function() {} |
| // FIXME ^ Add an attribute to suppress the warning |
| |
| fn main() { |
| used_function(); |
| } |
| </code></pre></pre> |
| <p>Note that in real programs, you should eliminate dead code. In these examples |
| we'll allow dead code in some places because of the interactive nature of the |
| examples.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="crates-1"><a class="header" href="#crates-1">Crates</a></h1> |
| <p>The <code>crate_type</code> attribute can be used to tell the compiler whether a crate is |
| a binary or a library (and even which type of library), and the <code>crate_name</code> |
| attribute can be used to set the name of the crate.</p> |
| <p>However, it is important to note that both the <code>crate_type</code> and <code>crate_name</code> |
| attributes have <strong>no</strong> effect whatsoever when using Cargo, the Rust package |
| manager. Since Cargo is used for the majority of Rust projects, this means |
| real-world uses of <code>crate_type</code> and <code>crate_name</code> are relatively limited.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// This crate is a library |
| #![crate_type = "lib"] |
| // The library is named "rary" |
| #![crate_name = "rary"] |
| |
| pub fn public_function() { |
| println!("called rary's `public_function()`"); |
| } |
| |
| fn private_function() { |
| println!("called rary's `private_function()`"); |
| } |
| |
| pub fn indirect_access() { |
| print!("called rary's `indirect_access()`, that\n> "); |
| |
| private_function(); |
| } |
| </code></pre></pre> |
| <p>When the <code>crate_type</code> attribute is used, we no longer need to pass the |
| <code>--crate-type</code> flag to <code>rustc</code>.</p> |
| <pre><code class="language-shell">$ rustc lib.rs |
| $ ls lib* |
| library.rlib |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="cfg"><a class="header" href="#cfg"><code>cfg</code></a></h1> |
| <p>Configuration conditional checks are possible through two different operators:</p> |
| <ul> |
| <li>the <code>cfg</code> attribute: <code>#[cfg(...)]</code> in attribute position</li> |
| <li>the <code>cfg!</code> macro: <code>cfg!(...)</code> in boolean expressions</li> |
| </ul> |
| <p>While the former enables conditional compilation, the latter conditionally |
| evaluates to <code>true</code> or <code>false</code> literals allowing for checks at run-time. Both |
| utilize identical argument syntax.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// This function only gets compiled if the target OS is linux |
| #[cfg(target_os = "linux")] |
| fn are_you_on_linux() { |
| println!("You are running linux!"); |
| } |
| |
| // And this function only gets compiled if the target OS is *not* linux |
| #[cfg(not(target_os = "linux"))] |
| fn are_you_on_linux() { |
| println!("You are *not* running linux!"); |
| } |
| |
| fn main() { |
| are_you_on_linux(); |
| |
| println!("Are you sure?"); |
| if cfg!(target_os = "linux") { |
| println!("Yes. It's definitely linux!"); |
| } else { |
| println!("Yes. It's definitely *not* linux!"); |
| } |
| } |
| </code></pre></pre> |
| <h3 id="see-also-31"><a class="header" href="#see-also-31">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/reference/attributes.html#conditional-compilation">the reference</a>, <a href="https://doc.rust-lang.org/std/macro.cfg!.html"><code>cfg!</code></a>, and <a href="attribute/../macros.html">macros</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="custom"><a class="header" href="#custom">Custom</a></h1> |
| <p>Some conditionals like <code>target_os</code> are implicitly provided by <code>rustc</code>, but |
| custom conditionals must be passed to <code>rustc</code> using the <code>--cfg</code> flag.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">#[cfg(some_condition)] |
| fn conditional_function() { |
| println!("condition met!"); |
| } |
| |
| fn main() { |
| conditional_function(); |
| } |
| </code></pre></pre> |
| <p>Try to run this to see what happens without the custom <code>cfg</code> flag.</p> |
| <p>With the custom <code>cfg</code> flag:</p> |
| <pre><code class="language-shell">$ rustc --cfg some_condition custom.rs && ./custom |
| condition met! |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="generics"><a class="header" href="#generics">Generics</a></h1> |
| <p><em>Generics</em> is the topic of generalizing types and functionalities to broader |
| cases. This is extremely useful for reducing code duplication in many ways, |
| but can call for rather involving syntax. Namely, being generic requires |
| taking great care to specify over which types a generic type |
| is actually considered valid. The simplest and most common use of generics |
| is for type parameters.</p> |
| <p>A type parameter is specified as generic by the use of angle brackets and upper |
| <a href="https://en.wikipedia.org/wiki/CamelCase">camel case</a>: <code><Aaa, Bbb, ...></code>. "Generic type parameters" are |
| typically represented as <code><T></code>. In Rust, "generic" also describes anything that |
| accepts one or more generic type parameters <code><T></code>. Any type specified as a |
| generic type parameter is generic, and everything else is concrete (non-generic).</p> |
| <p>For example, defining a <em>generic function</em> named <code>foo</code> that takes an argument |
| <code>T</code> of any type:</p> |
| <pre><code class="language-rust ignore">fn foo<T>(arg: T) { ... } |
| </code></pre> |
| <p>Because <code>T</code> has been specified as a generic type parameter using <code><T></code>, it |
| is considered generic when used here as <code>(arg: T)</code>. This is the case even if <code>T</code> |
| has previously been defined as a <code>struct</code>.</p> |
| <p>This example shows some of the syntax in action:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// A concrete type `A`. |
| struct A; |
| |
| // In defining the type `Single`, the first use of `A` is not preceded by `<A>`. |
| // Therefore, `Single` is a concrete type, and `A` is defined as above. |
| struct Single(A); |
| // ^ Here is `Single`s first use of the type `A`. |
| |
| // Here, `<T>` precedes the first use of `T`, so `SingleGen` is a generic type. |
| // Because the type parameter `T` is generic, it could be anything, including |
| // the concrete type `A` defined at the top. |
| struct SingleGen<T>(T); |
| |
| fn main() { |
| // `Single` is concrete and explicitly takes `A`. |
| let _s = Single(A); |
| |
| // Create a variable `_char` of type `SingleGen<char>` |
| // and give it the value `SingleGen('a')`. |
| // Here, `SingleGen` has a type parameter explicitly specified. |
| let _char: SingleGen<char> = SingleGen('a'); |
| |
| // `SingleGen` can also have a type parameter implicitly specified: |
| let _t = SingleGen(A); // Uses `A` defined at the top. |
| let _i32 = SingleGen(6); // Uses `i32`. |
| let _char = SingleGen('a'); // Uses `char`. |
| } |
| </code></pre></pre> |
| <h3 id="see-also-32"><a class="header" href="#see-also-32">See also:</a></h3> |
| <p><a href="custom_types/structs.html"><code>structs</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="functions-1"><a class="header" href="#functions-1">Functions</a></h1> |
| <p>The same set of rules can be applied to functions: a type <code>T</code> becomes |
| generic when preceded by <code><T></code>.</p> |
| <p>Using generic functions sometimes requires explicitly specifying type |
| parameters. This may be the case if the function is called where the return type |
| is generic, or if the compiler doesn't have enough information to infer |
| the necessary type parameters.</p> |
| <p>A function call with explicitly specified type parameters looks like: |
| <code>fun::<A, B, ...>()</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct A; // Concrete type `A`. |
| struct S(A); // Concrete type `S`. |
| struct SGen<T>(T); // Generic type `SGen`. |
| |
| // The following functions all take ownership of the variable passed into |
| // them and immediately go out of scope, freeing the variable. |
| |
| // Define a function `reg_fn` that takes an argument `_s` of type `S`. |
| // This has no `<T>` so this is not a generic function. |
| fn reg_fn(_s: S) {} |
| |
| // Define a function `gen_spec_t` that takes an argument `_s` of type `SGen<T>`. |
| // It has been explicitly given the type parameter `A`, but because `A` has not |
| // been specified as a generic type parameter for `gen_spec_t`, it is not generic. |
| fn gen_spec_t(_s: SGen<A>) {} |
| |
| // Define a function `gen_spec_i32` that takes an argument `_s` of type `SGen<i32>`. |
| // It has been explicitly given the type parameter `i32`, which is a specific type. |
| // Because `i32` is not a generic type, this function is also not generic. |
| fn gen_spec_i32(_s: SGen<i32>) {} |
| |
| // Define a function `generic` that takes an argument `_s` of type `SGen<T>`. |
| // Because `SGen<T>` is preceded by `<T>`, this function is generic over `T`. |
| fn generic<T>(_s: SGen<T>) {} |
| |
| fn main() { |
| // Using the non-generic functions |
| reg_fn(S(A)); // Concrete type. |
| gen_spec_t(SGen(A)); // Implicitly specified type parameter `A`. |
| gen_spec_i32(SGen(6)); // Implicitly specified type parameter `i32`. |
| |
| // Explicitly specified type parameter `char` to `generic()`. |
| generic::<char>(SGen('a')); |
| |
| // Implicitly specified type parameter `char` to `generic()`. |
| generic(SGen('c')); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-33"><a class="header" href="#see-also-33">See also:</a></h3> |
| <p><a href="generics/../fn.html">functions</a> and <a href="generics/../custom_types/structs.html"><code>struct</code>s</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="implementation"><a class="header" href="#implementation">Implementation</a></h1> |
| <p>Similar to functions, implementations require care to remain generic.</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>struct S; // Concrete type `S` |
| struct GenericVal<T>(T); // Generic type `GenericVal` |
| |
| // impl of GenericVal where we explicitly specify type parameters: |
| impl GenericVal<f32> {} // Specify `f32` |
| impl GenericVal<S> {} // Specify `S` as defined above |
| |
| // `<T>` Must precede the type to remain generic |
| impl<T> GenericVal<T> {} |
| <span class="boring">} |
| </span></code></pre></pre> |
| <pre><pre class="playground"><code class="language-rust editable">struct Val { |
| val: f64, |
| } |
| |
| struct GenVal<T> { |
| gen_val: T, |
| } |
| |
| // impl of Val |
| impl Val { |
| fn value(&self) -> &f64 { |
| &self.val |
| } |
| } |
| |
| // impl of GenVal for a generic type `T` |
| impl<T> GenVal<T> { |
| fn value(&self) -> &T { |
| &self.gen_val |
| } |
| } |
| |
| fn main() { |
| let x = Val { val: 3.0 }; |
| let y = GenVal { gen_val: 3i32 }; |
| |
| println!("{}, {}", x.value(), y.value()); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-34"><a class="header" href="#see-also-34">See also:</a></h3> |
| <p><a href="generics/../scope/lifetime/fn.html">functions returning references</a>, <a href="generics/../fn/methods.html"><code>impl</code></a>, and <a href="generics/../custom_types/structs.html"><code>struct</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="traits"><a class="header" href="#traits">Traits</a></h1> |
| <p>Of course <code>trait</code>s can also be generic. Here we define one which reimplements |
| the <code>Drop</code> <code>trait</code> as a generic method to <code>drop</code> itself and an input.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Non-copyable types. |
| struct Empty; |
| struct Null; |
| |
| // A trait generic over `T`. |
| trait DoubleDrop<T> { |
| // Define a method on the caller type which takes an |
| // additional single parameter `T` and does nothing with it. |
| fn double_drop(self, _: T); |
| } |
| |
| // Implement `DoubleDrop<T>` for any generic parameter `T` and |
| // caller `U`. |
| impl<T, U> DoubleDrop<T> for U { |
| // This method takes ownership of both passed arguments, |
| // deallocating both. |
| fn double_drop(self, _: T) {} |
| } |
| |
| fn main() { |
| let empty = Empty; |
| let null = Null; |
| |
| // Deallocate `empty` and `null`. |
| empty.double_drop(null); |
| |
| //empty; |
| //null; |
| // ^ TODO: Try uncommenting these lines. |
| } |
| </code></pre></pre> |
| <h3 id="see-also-35"><a class="header" href="#see-also-35">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/ops/trait.Drop.html"><code>Drop</code></a>, <a href="generics/../custom_types/structs.html"><code>struct</code></a>, and <a href="generics/../trait.html"><code>trait</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="bounds"><a class="header" href="#bounds">Bounds</a></h1> |
| <p>When working with generics, the type parameters often must use traits as <em>bounds</em> to |
| stipulate what functionality a type implements. For example, the following |
| example uses the trait <code>Display</code> to print and so it requires <code>T</code> to be bound |
| by <code>Display</code>; that is, <code>T</code> <em>must</em> implement <code>Display</code>.</p> |
| <pre><code class="language-rust ignore">// Define a function `printer` that takes a generic type `T` which |
| // must implement trait `Display`. |
| fn printer<T: Display>(t: T) { |
| println!("{}", t); |
| } |
| </code></pre> |
| <p>Bounding restricts the generic to types that conform to the bounds. That is:</p> |
| <pre><code class="language-rust ignore">struct S<T: Display>(T); |
| |
| // Error! `Vec<T>` does not implement `Display`. This |
| // specialization will fail. |
| let s = S(vec![1]); |
| </code></pre> |
| <p>Another effect of bounding is that generic instances are allowed to access the |
| <a href="generics/../fn/methods.html">methods</a> of traits specified in the bounds. For example:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// A trait which implements the print marker: `{:?}`. |
| use std::fmt::Debug; |
| |
| trait HasArea { |
| fn area(&self) -> f64; |
| } |
| |
| impl HasArea for Rectangle { |
| fn area(&self) -> f64 { self.length * self.height } |
| } |
| |
| #[derive(Debug)] |
| struct Rectangle { length: f64, height: f64 } |
| #[allow(dead_code)] |
| struct Triangle { length: f64, height: f64 } |
| |
| // The generic `T` must implement `Debug`. Regardless |
| // of the type, this will work properly. |
| fn print_debug<T: Debug>(t: &T) { |
| println!("{:?}", t); |
| } |
| |
| // `T` must implement `HasArea`. Any type which meets |
| // the bound can access `HasArea`'s function `area`. |
| fn area<T: HasArea>(t: &T) -> f64 { t.area() } |
| |
| fn main() { |
| let rectangle = Rectangle { length: 3.0, height: 4.0 }; |
| let _triangle = Triangle { length: 3.0, height: 4.0 }; |
| |
| print_debug(&rectangle); |
| println!("Area: {}", area(&rectangle)); |
| |
| //print_debug(&_triangle); |
| //println!("Area: {}", area(&_triangle)); |
| // ^ TODO: Try uncommenting these. |
| // | Error: Does not implement either `Debug` or `HasArea`. |
| } |
| </code></pre></pre> |
| <p>As an additional note, <a href="generics/../generics/where.html"><code>where</code></a> clauses can also be used to apply bounds in |
| some cases to be more expressive.</p> |
| <h3 id="see-also-36"><a class="header" href="#see-also-36">See also:</a></h3> |
| <p><a href="generics/../hello/print.html"><code>std::fmt</code></a>, <a href="generics/../custom_types/structs.html"><code>struct</code>s</a>, and <a href="generics/../trait.html"><code>trait</code>s</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="testcase-empty-bounds"><a class="header" href="#testcase-empty-bounds">Testcase: empty bounds</a></h1> |
| <p>A consequence of how bounds work is that even if a <code>trait</code> doesn't |
| include any functionality, you can still use it as a bound. <code>Eq</code> and |
| <code>Copy</code> are examples of such <code>trait</code>s from the <code>std</code> library.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Cardinal; |
| struct BlueJay; |
| struct Turkey; |
| |
| trait Red {} |
| trait Blue {} |
| |
| impl Red for Cardinal {} |
| impl Blue for BlueJay {} |
| |
| // These functions are only valid for types which implement these |
| // traits. The fact that the traits are empty is irrelevant. |
| fn red<T: Red>(_: &T) -> &'static str { "red" } |
| fn blue<T: Blue>(_: &T) -> &'static str { "blue" } |
| |
| fn main() { |
| let cardinal = Cardinal; |
| let blue_jay = BlueJay; |
| let _turkey = Turkey; |
| |
| // `red()` won't work on a blue jay nor vice versa |
| // because of the bounds. |
| println!("A cardinal is {}", red(&cardinal)); |
| println!("A blue jay is {}", blue(&blue_jay)); |
| //println!("A turkey is {}", red(&_turkey)); |
| // ^ TODO: Try uncommenting this line. |
| } |
| </code></pre></pre> |
| <h3 id="see-also-37"><a class="header" href="#see-also-37">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/cmp/trait.Eq.html"><code>std::cmp::Eq</code></a>, <a href="https://doc.rust-lang.org/std/marker/trait.Copy.html"><code>std::marker::Copy</code></a>, and <a href="generics/bounds/../../trait.html"><code>trait</code>s</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="multiple-bounds"><a class="header" href="#multiple-bounds">Multiple bounds</a></h1> |
| <p>Multiple bounds for a single type can be applied with a <code>+</code>. Like normal, different types are |
| separated with <code>,</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::fmt::{Debug, Display}; |
| |
| fn compare_prints<T: Debug + Display>(t: &T) { |
| println!("Debug: `{:?}`", t); |
| println!("Display: `{}`", t); |
| } |
| |
| fn compare_types<T: Debug, U: Debug>(t: &T, u: &U) { |
| println!("t: `{:?}`", t); |
| println!("u: `{:?}`", u); |
| } |
| |
| fn main() { |
| let string = "words"; |
| let array = [1, 2, 3]; |
| let vec = vec![1, 2, 3]; |
| |
| compare_prints(&string); |
| //compare_prints(&array); |
| // TODO ^ Try uncommenting this. |
| |
| compare_types(&array, &vec); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-38"><a class="header" href="#see-also-38">See also:</a></h3> |
| <p><a href="generics/../hello/print.html"><code>std::fmt</code></a> and <a href="generics/../trait.html"><code>trait</code>s</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="where-clauses"><a class="header" href="#where-clauses">Where clauses</a></h1> |
| <p>A bound can also be expressed using a <code>where</code> clause immediately |
| before the opening <code>{</code>, rather than at the type's first mention. |
| Additionally, <code>where</code> clauses can apply bounds to arbitrary types, |
| rather than just to type parameters.</p> |
| <p>Some cases that a <code>where</code> clause is useful:</p> |
| <ul> |
| <li>When specifying generic types and bounds separately is clearer:</li> |
| </ul> |
| <pre><code class="language-rust ignore">impl <A: TraitB + TraitC, D: TraitE + TraitF> MyTrait<A, D> for YourType {} |
| |
| // Expressing bounds with a `where` clause |
| impl <A, D> MyTrait<A, D> for YourType where |
| A: TraitB + TraitC, |
| D: TraitE + TraitF {} |
| </code></pre> |
| <ul> |
| <li>When using a <code>where</code> clause is more expressive than using normal syntax. |
| The <code>impl</code> in this example cannot be directly expressed without a <code>where</code> clause:</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable">use std::fmt::Debug; |
| |
| trait PrintInOption { |
| fn print_in_option(self); |
| } |
| |
| // Because we would otherwise have to express this as `T: Debug` or |
| // use another method of indirect approach, this requires a `where` clause: |
| impl<T> PrintInOption for T where |
| Option<T>: Debug { |
| // We want `Option<T>: Debug` as our bound because that is what's |
| // being printed. Doing otherwise would be using the wrong bound. |
| fn print_in_option(self) { |
| println!("{:?}", Some(self)); |
| } |
| } |
| |
| fn main() { |
| let vec = vec![1, 2, 3]; |
| |
| vec.print_in_option(); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-39"><a class="header" href="#see-also-39">See also:</a></h3> |
| <p><a href="https://github.com/rust-lang/rfcs/blob/master/text/0135-where.md">RFC</a>, <a href="generics/../custom_types/structs.html"><code>struct</code></a>, and <a href="generics/../trait.html"><code>trait</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="new-type-idiom"><a class="header" href="#new-type-idiom">New Type Idiom</a></h1> |
| <p>The <code>newtype</code> idiom gives compile time guarantees that the right type of value is supplied |
| to a program.</p> |
| <p>For example, an age verification function that checks age in years, <em>must</em> be given |
| a value of type <code>Years</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Years(i64); |
| |
| struct Days(i64); |
| |
| impl Years { |
| pub fn to_days(&self) -> Days { |
| Days(self.0 * 365) |
| } |
| } |
| |
| |
| impl Days { |
| /// truncates partial years |
| pub fn to_years(&self) -> Years { |
| Years(self.0 / 365) |
| } |
| } |
| |
| fn old_enough(age: &Years) -> bool { |
| age.0 >= 18 |
| } |
| |
| fn main() { |
| let age = Years(5); |
| let age_days = age.to_days(); |
| println!("Old enough {}", old_enough(&age)); |
| println!("Old enough {}", old_enough(&age_days.to_years())); |
| // println!("Old enough {}", old_enough(&age_days)); |
| } |
| </code></pre></pre> |
| <p>Uncomment the last print statement to observe that the type supplied must be <code>Years</code>.</p> |
| <p>To obtain the <code>newtype</code>'s value as the base type, you may use the tuple or destructuring syntax like so:</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Years(i64); |
| |
| fn main() { |
| let years = Years(42); |
| let years_as_primitive_1: i64 = years.0; // Tuple |
| let Years(years_as_primitive_2) = years; // Destructuring |
| } |
| </code></pre></pre> |
| <h3 id="see-also-40"><a class="header" href="#see-also-40">See also:</a></h3> |
| <p><a href="generics/../custom_types/structs.html"><code>structs</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="associated-items"><a class="header" href="#associated-items">Associated items</a></h1> |
| <p>"Associated Items" refers to a set of rules pertaining to <a href="https://doc.rust-lang.org/reference/items.html"><code>item</code></a>s |
| of various types. It is an extension to <code>trait</code> generics, and allows |
| <code>trait</code>s to internally define new items.</p> |
| <p>One such item is called an <em>associated type</em>, providing simpler usage |
| patterns when the <code>trait</code> is generic over its container type.</p> |
| <h3 id="see-also-41"><a class="header" href="#see-also-41">See also:</a></h3> |
| <p><a href="https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md">RFC</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="the-problem"><a class="header" href="#the-problem">The Problem</a></h1> |
| <p>A <code>trait</code> that is generic over its container type has type specification |
| requirements - users of the <code>trait</code> <em>must</em> specify all of its generic types.</p> |
| <p>In the example below, the <code>Contains</code> <code>trait</code> allows the use of the generic |
| types <code>A</code> and <code>B</code>. The trait is then implemented for the <code>Container</code> type, |
| specifying <code>i32</code> for <code>A</code> and <code>B</code> so that it can be used with <code>fn difference()</code>.</p> |
| <p>Because <code>Contains</code> is generic, we are forced to explicitly state <em>all</em> of the |
| generic types for <code>fn difference()</code>. In practice, we want a way to express that |
| <code>A</code> and <code>B</code> are determined by the <em>input</em> <code>C</code>. As you will see in the next |
| section, associated types provide exactly that capability.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Container(i32, i32); |
| |
| // A trait which checks if 2 items are stored inside of container. |
| // Also retrieves first or last value. |
| trait Contains<A, B> { |
| fn contains(&self, _: &A, _: &B) -> bool; // Explicitly requires `A` and `B`. |
| fn first(&self) -> i32; // Doesn't explicitly require `A` or `B`. |
| fn last(&self) -> i32; // Doesn't explicitly require `A` or `B`. |
| } |
| |
| impl Contains<i32, i32> for Container { |
| // True if the numbers stored are equal. |
| fn contains(&self, number_1: &i32, number_2: &i32) -> bool { |
| (&self.0 == number_1) && (&self.1 == number_2) |
| } |
| |
| // Grab the first number. |
| fn first(&self) -> i32 { self.0 } |
| |
| // Grab the last number. |
| fn last(&self) -> i32 { self.1 } |
| } |
| |
| // `C` contains `A` and `B`. In light of that, having to express `A` and |
| // `B` again is a nuisance. |
| fn difference<A, B, C>(container: &C) -> i32 where |
| C: Contains<A, B> { |
| container.last() - container.first() |
| } |
| |
| fn main() { |
| let number_1 = 3; |
| let number_2 = 10; |
| |
| let container = Container(number_1, number_2); |
| |
| println!("Does container contain {} and {}: {}", |
| &number_1, &number_2, |
| container.contains(&number_1, &number_2)); |
| println!("First number: {}", container.first()); |
| println!("Last number: {}", container.last()); |
| |
| println!("The difference is: {}", difference(&container)); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-42"><a class="header" href="#see-also-42">See also:</a></h3> |
| <p><a href="generics/assoc_items/../../custom_types/structs.html"><code>struct</code>s</a>, and <a href="generics/assoc_items/../../trait.html"><code>trait</code>s</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="associated-types"><a class="header" href="#associated-types">Associated types</a></h1> |
| <p>The use of "Associated types" improves the overall readability of code |
| by moving inner types locally into a trait as <em>output</em> types. Syntax |
| for the <code>trait</code> definition is as follows:</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>// `A` and `B` are defined in the trait via the `type` keyword. |
| // (Note: `type` in this context is different from `type` when used for |
| // aliases). |
| trait Contains { |
| type A; |
| type B; |
| |
| // Updated syntax to refer to these new types generically. |
| fn contains(&self, &Self::A, &Self::B) -> bool; |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p>Note that functions that use the <code>trait</code> <code>Contains</code> are no longer required |
| to express <code>A</code> or <code>B</code> at all:</p> |
| <pre><code class="language-rust ignore">// Without using associated types |
| fn difference<A, B, C>(container: &C) -> i32 where |
| C: Contains<A, B> { ... } |
| |
| // Using associated types |
| fn difference<C: Contains>(container: &C) -> i32 { ... } |
| </code></pre> |
| <p>Let's rewrite the example from the previous section using associated types:</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Container(i32, i32); |
| |
| // A trait which checks if 2 items are stored inside of container. |
| // Also retrieves first or last value. |
| trait Contains { |
| // Define generic types here which methods will be able to utilize. |
| type A; |
| type B; |
| |
| fn contains(&self, _: &Self::A, _: &Self::B) -> bool; |
| fn first(&self) -> i32; |
| fn last(&self) -> i32; |
| } |
| |
| impl Contains for Container { |
| // Specify what types `A` and `B` are. If the `input` type |
| // is `Container(i32, i32)`, the `output` types are determined |
| // as `i32` and `i32`. |
| type A = i32; |
| type B = i32; |
| |
| // `&Self::A` and `&Self::B` are also valid here. |
| fn contains(&self, number_1: &i32, number_2: &i32) -> bool { |
| (&self.0 == number_1) && (&self.1 == number_2) |
| } |
| // Grab the first number. |
| fn first(&self) -> i32 { self.0 } |
| |
| // Grab the last number. |
| fn last(&self) -> i32 { self.1 } |
| } |
| |
| fn difference<C: Contains>(container: &C) -> i32 { |
| container.last() - container.first() |
| } |
| |
| fn main() { |
| let number_1 = 3; |
| let number_2 = 10; |
| |
| let container = Container(number_1, number_2); |
| |
| println!("Does container contain {} and {}: {}", |
| &number_1, &number_2, |
| container.contains(&number_1, &number_2)); |
| println!("First number: {}", container.first()); |
| println!("Last number: {}", container.last()); |
| |
| println!("The difference is: {}", difference(&container)); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="phantom-type-parameters"><a class="header" href="#phantom-type-parameters">Phantom type parameters</a></h1> |
| <p>A phantom type parameter is one that doesn't show up at runtime, |
| but is checked statically (and only) at compile time.</p> |
| <p>Data types can use extra generic type parameters to act as markers |
| or to perform type checking at compile time. These extra parameters |
| hold no storage values, and have no runtime behavior.</p> |
| <p>In the following example, we combine <a href="https://doc.rust-lang.org/std/marker/struct.PhantomData.html">std::marker::PhantomData</a> |
| with the phantom type parameter concept to create tuples containing |
| different data types.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::marker::PhantomData; |
| |
| // A phantom tuple struct which is generic over `A` with hidden parameter `B`. |
| #[derive(PartialEq)] // Allow equality test for this type. |
| struct PhantomTuple<A, B>(A,PhantomData<B>); |
| |
| // A phantom type struct which is generic over `A` with hidden parameter `B`. |
| #[derive(PartialEq)] // Allow equality test for this type. |
| struct PhantomStruct<A, B> { first: A, phantom: PhantomData<B> } |
| |
| // Note: Storage is allocated for generic type `A`, but not for `B`. |
| // Therefore, `B` cannot be used in computations. |
| |
| fn main() { |
| // Here, `f32` and `f64` are the hidden parameters. |
| // PhantomTuple type specified as `<char, f32>`. |
| let _tuple1: PhantomTuple<char, f32> = PhantomTuple('Q', PhantomData); |
| // PhantomTuple type specified as `<char, f64>`. |
| let _tuple2: PhantomTuple<char, f64> = PhantomTuple('Q', PhantomData); |
| |
| // Type specified as `<char, f32>`. |
| let _struct1: PhantomStruct<char, f32> = PhantomStruct { |
| first: 'Q', |
| phantom: PhantomData, |
| }; |
| // Type specified as `<char, f64>`. |
| let _struct2: PhantomStruct<char, f64> = PhantomStruct { |
| first: 'Q', |
| phantom: PhantomData, |
| }; |
| |
| // Compile-time Error! Type mismatch so these cannot be compared: |
| //println!("_tuple1 == _tuple2 yields: {}", |
| // _tuple1 == _tuple2); |
| |
| // Compile-time Error! Type mismatch so these cannot be compared: |
| //println!("_struct1 == _struct2 yields: {}", |
| // _struct1 == _struct2); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-43"><a class="header" href="#see-also-43">See also:</a></h3> |
| <p><a href="generics/../trait/derive.html">Derive</a>, <a href="generics/../custom_types/structs.html">struct</a>, and <a href="generics/../custom_types/structs.html">TupleStructs</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="testcase-unit-clarification"><a class="header" href="#testcase-unit-clarification">Testcase: unit clarification</a></h1> |
| <p>A useful method of unit conversions can be examined by implementing <code>Add</code> |
| with a phantom type parameter. The <code>Add</code> <code>trait</code> is examined below:</p> |
| <pre><code class="language-rust ignore">// This construction would impose: `Self + RHS = Output` |
| // where RHS defaults to Self if not specified in the implementation. |
| pub trait Add<RHS = Self> { |
| type Output; |
| |
| fn add(self, rhs: RHS) -> Self::Output; |
| } |
| |
| // `Output` must be `T<U>` so that `T<U> + T<U> = T<U>`. |
| impl<U> Add for T<U> { |
| type Output = T<U>; |
| ... |
| } |
| </code></pre> |
| <p>The whole implementation:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::ops::Add; |
| use std::marker::PhantomData; |
| |
| /// Create void enumerations to define unit types. |
| #[derive(Debug, Clone, Copy)] |
| enum Inch {} |
| #[derive(Debug, Clone, Copy)] |
| enum Mm {} |
| |
| /// `Length` is a type with phantom type parameter `Unit`, |
| /// and is not generic over the length type (that is `f64`). |
| /// |
| /// `f64` already implements the `Clone` and `Copy` traits. |
| #[derive(Debug, Clone, Copy)] |
| struct Length<Unit>(f64, PhantomData<Unit>); |
| |
| /// The `Add` trait defines the behavior of the `+` operator. |
| impl<Unit> Add for Length<Unit> { |
| type Output = Length<Unit>; |
| |
| // add() returns a new `Length` struct containing the sum. |
| fn add(self, rhs: Length<Unit>) -> Length<Unit> { |
| // `+` calls the `Add` implementation for `f64`. |
| Length(self.0 + rhs.0, PhantomData) |
| } |
| } |
| |
| fn main() { |
| // Specifies `one_foot` to have phantom type parameter `Inch`. |
| let one_foot: Length<Inch> = Length(12.0, PhantomData); |
| // `one_meter` has phantom type parameter `Mm`. |
| let one_meter: Length<Mm> = Length(1000.0, PhantomData); |
| |
| // `+` calls the `add()` method we implemented for `Length<Unit>`. |
| // |
| // Since `Length` implements `Copy`, `add()` does not consume |
| // `one_foot` and `one_meter` but copies them into `self` and `rhs`. |
| let two_feet = one_foot + one_foot; |
| let two_meters = one_meter + one_meter; |
| |
| // Addition works. |
| println!("one foot + one_foot = {:?} in", two_feet.0); |
| println!("one meter + one_meter = {:?} mm", two_meters.0); |
| |
| // Nonsensical operations fail as they should: |
| // Compile-time Error: type mismatch. |
| //let one_feter = one_foot + one_meter; |
| } |
| </code></pre></pre> |
| <h3 id="see-also-44"><a class="header" href="#see-also-44">See also:</a></h3> |
| <p><a href="generics/phantom/../../scope/borrow.html">Borrowing (<code>&</code>)</a>, <a href="generics/phantom/../../generics/bounds.html">Bounds (<code>X: Y</code>)</a>, <a href="generics/phantom/../../custom_types/enum.html">enum</a>, <a href="generics/phantom/../../fn/methods.html">impl & self</a>, |
| <a href="generics/phantom/../../trait/ops.html">Overloading</a>, <a href="generics/phantom/../../scope/borrow/ref.html">ref</a>, <a href="generics/phantom/../../trait.html">Traits (<code>X for Y</code>)</a>, and <a href="generics/phantom/../../custom_types/structs.html">TupleStructs</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="scoping-rules"><a class="header" href="#scoping-rules">Scoping rules</a></h1> |
| <p>Scopes play an important part in ownership, borrowing, and lifetimes. |
| That is, they indicate to the compiler when borrows are valid, when |
| resources can be freed, and when variables are created or destroyed.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="raii"><a class="header" href="#raii">RAII</a></h1> |
| <p>Variables in Rust do more than just hold data in the stack: they also <em>own</em> |
| resources, e.g. <code>Box<T></code> owns memory in the heap. Rust enforces <a href="https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization">RAII</a> |
| (Resource Acquisition Is Initialization), so whenever an object goes out of |
| scope, its destructor is called and its owned resources are freed.</p> |
| <p>This behavior shields against <em>resource leak</em> bugs, so you'll never have to |
| manually free memory or worry about memory leaks again! Here's a quick showcase:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// raii.rs |
| fn create_box() { |
| // Allocate an integer on the heap |
| let _box1 = Box::new(3i32); |
| |
| // `_box1` is destroyed here, and memory gets freed |
| } |
| |
| fn main() { |
| // Allocate an integer on the heap |
| let _box2 = Box::new(5i32); |
| |
| // A nested scope: |
| { |
| // Allocate an integer on the heap |
| let _box3 = Box::new(4i32); |
| |
| // `_box3` is destroyed here, and memory gets freed |
| } |
| |
| // Creating lots of boxes just for fun |
| // There's no need to manually free memory! |
| for _ in 0u32..1_000 { |
| create_box(); |
| } |
| |
| // `_box2` is destroyed here, and memory gets freed |
| } |
| </code></pre></pre> |
| <p>Of course, we can double check for memory errors using <a href="http://valgrind.org/info/"><code>valgrind</code></a>:</p> |
| <pre><code class="language-shell">$ rustc raii.rs && valgrind ./raii |
| ==26873== Memcheck, a memory error detector |
| ==26873== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. |
| ==26873== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info |
| ==26873== Command: ./raii |
| ==26873== |
| ==26873== |
| ==26873== HEAP SUMMARY: |
| ==26873== in use at exit: 0 bytes in 0 blocks |
| ==26873== total heap usage: 1,013 allocs, 1,013 frees, 8,696 bytes allocated |
| ==26873== |
| ==26873== All heap blocks were freed -- no leaks are possible |
| ==26873== |
| ==26873== For counts of detected and suppressed errors, rerun with: -v |
| ==26873== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2) |
| </code></pre> |
| <p>No leaks here!</p> |
| <h2 id="destructor"><a class="header" href="#destructor">Destructor</a></h2> |
| <p>The notion of a destructor in Rust is provided through the <a href="https://doc.rust-lang.org/std/ops/trait.Drop.html"><code>Drop</code></a> trait. The |
| destructor is called when the resource goes out of scope. This trait is not |
| required to be implemented for every type, only implement it for your type if |
| you require its own destructor logic.</p> |
| <p>Run the below example to see how the <a href="https://doc.rust-lang.org/std/ops/trait.Drop.html"><code>Drop</code></a> trait works. When the variable in |
| the <code>main</code> function goes out of scope the custom destructor will be invoked.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct ToDrop; |
| |
| impl Drop for ToDrop { |
| fn drop(&mut self) { |
| println!("ToDrop is being dropped"); |
| } |
| } |
| |
| fn main() { |
| let x = ToDrop; |
| println!("Made a ToDrop!"); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-45"><a class="header" href="#see-also-45">See also:</a></h3> |
| <p><a href="scope/../std/box.html">Box</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="ownership-and-moves"><a class="header" href="#ownership-and-moves">Ownership and moves</a></h1> |
| <p>Because variables are in charge of freeing their own resources, |
| <strong>resources can only have one owner</strong>. This also prevents resources |
| from being freed more than once. Note that not all variables own |
| resources (e.g. <a href="scope/../flow_control/match/destructuring/destructure_pointers.html">references</a>).</p> |
| <p>When doing assignments (<code>let x = y</code>) or passing function arguments by value |
| (<code>foo(x)</code>), the <em>ownership</em> of the resources is transferred. In Rust-speak, |
| this is known as a <em>move</em>.</p> |
| <p>After moving resources, the previous owner can no longer be used. This avoids |
| creating dangling pointers.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// This function takes ownership of the heap allocated memory |
| fn destroy_box(c: Box<i32>) { |
| println!("Destroying a box that contains {}", c); |
| |
| // `c` is destroyed and the memory freed |
| } |
| |
| fn main() { |
| // _Stack_ allocated integer |
| let x = 5u32; |
| |
| // *Copy* `x` into `y` - no resources are moved |
| let y = x; |
| |
| // Both values can be independently used |
| println!("x is {}, and y is {}", x, y); |
| |
| // `a` is a pointer to a _heap_ allocated integer |
| let a = Box::new(5i32); |
| |
| println!("a contains: {}", a); |
| |
| // *Move* `a` into `b` |
| let b = a; |
| // The pointer address of `a` is copied (not the data) into `b`. |
| // Both are now pointers to the same heap allocated data, but |
| // `b` now owns it. |
| |
| // Error! `a` can no longer access the data, because it no longer owns the |
| // heap memory |
| //println!("a contains: {}", a); |
| // TODO ^ Try uncommenting this line |
| |
| // This function takes ownership of the heap allocated memory from `b` |
| destroy_box(b); |
| |
| // Since the heap memory has been freed at this point, this action would |
| // result in dereferencing freed memory, but it's forbidden by the compiler |
| // Error! Same reason as the previous Error |
| //println!("b contains: {}", b); |
| // TODO ^ Try uncommenting this line |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="mutability-1"><a class="header" href="#mutability-1">Mutability</a></h1> |
| <p>Mutability of data can be changed when ownership is transferred.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let immutable_box = Box::new(5u32); |
| |
| println!("immutable_box contains {}", immutable_box); |
| |
| // Mutability error |
| //*immutable_box = 4; |
| |
| // *Move* the box, changing the ownership (and mutability) |
| let mut mutable_box = immutable_box; |
| |
| println!("mutable_box contains {}", mutable_box); |
| |
| // Modify the contents of the box |
| *mutable_box = 4; |
| |
| println!("mutable_box now contains {}", mutable_box); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="partial-moves"><a class="header" href="#partial-moves">Partial moves</a></h1> |
| <p>Within the <a href="scope/move/../../flow_control/match/destructuring.html">destructuring</a> of a single variable, both <code>by-move</code> and |
| <code>by-reference</code> pattern bindings can be used at the same time. Doing |
| this will result in a <em>partial move</em> of the variable, which means |
| that parts of the variable will be moved while other parts stay. In |
| such a case, the parent variable cannot be used afterwards as a |
| whole, however the parts that are only referenced (and not moved) |
| can still be used.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| #[derive(Debug)] |
| struct Person { |
| name: String, |
| age: u8, |
| } |
| |
| let person = Person { |
| name: String::from("Alice"), |
| age: 20, |
| }; |
| |
| // `name` is moved out of person, but `age` is referenced |
| let Person { name, ref age } = person; |
| |
| println!("The person's age is {}", age); |
| |
| println!("The person's name is {}", name); |
| |
| // Error! borrow of partially moved value: `person` partial move occurs |
| //println!("The person struct is {:?}", person); |
| |
| // `person` cannot be used but `person.age` can be used as it is not moved |
| println!("The person's age from person struct is {}", person.age); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-46"><a class="header" href="#see-also-46">See also:</a></h3> |
| <p><a href="scope/move/../../flow_control/match/destructuring.html">destructuring</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="borrowing"><a class="header" href="#borrowing">Borrowing</a></h1> |
| <p>Most of the time, we'd like to access data without taking ownership over |
| it. To accomplish this, Rust uses a <em>borrowing</em> mechanism. Instead of |
| passing objects by value (<code>T</code>), objects can be passed by reference (<code>&T</code>).</p> |
| <p>The compiler statically guarantees (via its borrow checker) that references |
| <em>always</em> point to valid objects. That is, while references to an object |
| exist, the object cannot be destroyed.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">// This function takes ownership of a box and destroys it |
| fn eat_box_i32(boxed_i32: Box<i32>) { |
| println!("Destroying box that contains {}", boxed_i32); |
| } |
| |
| // This function borrows an i32 |
| fn borrow_i32(borrowed_i32: &i32) { |
| println!("This int is: {}", borrowed_i32); |
| } |
| |
| fn main() { |
| // Create a boxed i32, and a stacked i32 |
| let boxed_i32 = Box::new(5_i32); |
| let stacked_i32 = 6_i32; |
| |
| // Borrow the contents of the box. Ownership is not taken, |
| // so the contents can be borrowed again. |
| borrow_i32(&boxed_i32); |
| borrow_i32(&stacked_i32); |
| |
| { |
| // Take a reference to the data contained inside the box |
| let _ref_to_i32: &i32 = &boxed_i32; |
| |
| // Error! |
| // Can't destroy `boxed_i32` while the inner value is borrowed later in scope. |
| eat_box_i32(boxed_i32); |
| // FIXME ^ Comment out this line |
| |
| // Attempt to borrow `_ref_to_i32` after inner value is destroyed |
| borrow_i32(_ref_to_i32); |
| // `_ref_to_i32` goes out of scope and is no longer borrowed. |
| } |
| |
| // `boxed_i32` can now give up ownership to `eat_box` and be destroyed |
| eat_box_i32(boxed_i32); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="mutability-2"><a class="header" href="#mutability-2">Mutability</a></h1> |
| <p>Mutable data can be mutably borrowed using <code>&mut T</code>. This is called |
| a <em>mutable reference</em> and gives read/write access to the borrower. |
| In contrast, <code>&T</code> borrows the data via an immutable reference, and |
| the borrower can read the data but not modify it:</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">#[allow(dead_code)] |
| #[derive(Clone, Copy)] |
| struct Book { |
| // `&'static str` is a reference to a string allocated in read only memory |
| author: &'static str, |
| title: &'static str, |
| year: u32, |
| } |
| |
| // This function takes a reference to a book |
| fn borrow_book(book: &Book) { |
| println!("I immutably borrowed {} - {} edition", book.title, book.year); |
| } |
| |
| // This function takes a reference to a mutable book and changes `year` to 2014 |
| fn new_edition(book: &mut Book) { |
| book.year = 2014; |
| println!("I mutably borrowed {} - {} edition", book.title, book.year); |
| } |
| |
| fn main() { |
| // Create an immutable Book named `immutabook` |
| let immutabook = Book { |
| // string literals have type `&'static str` |
| author: "Douglas Hofstadter", |
| title: "Gödel, Escher, Bach", |
| year: 1979, |
| }; |
| |
| // Create a mutable copy of `immutabook` and call it `mutabook` |
| let mut mutabook = immutabook; |
| |
| // Immutably borrow an immutable object |
| borrow_book(&immutabook); |
| |
| // Immutably borrow a mutable object |
| borrow_book(&mutabook); |
| |
| // Borrow a mutable object as mutable |
| new_edition(&mut mutabook); |
| |
| // Error! Cannot borrow an immutable object as mutable |
| new_edition(&mut immutabook); |
| // FIXME ^ Comment out this line |
| } |
| </code></pre></pre> |
| <h3 id="see-also-47"><a class="header" href="#see-also-47">See also:</a></h3> |
| <p><a href="scope/borrow/../lifetime/static_lifetime.html"><code>static</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="aliasing-1"><a class="header" href="#aliasing-1">Aliasing</a></h1> |
| <p>Data can be immutably borrowed any number of times, but while immutably |
| borrowed, the original data can't be mutably borrowed. On the other hand, only |
| <em>one</em> mutable borrow is allowed at a time. The original data can be borrowed |
| again only <em>after</em> the mutable reference has been used for the last time.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Point { x: i32, y: i32, z: i32 } |
| |
| fn main() { |
| let mut point = Point { x: 0, y: 0, z: 0 }; |
| |
| let borrowed_point = &point; |
| let another_borrow = &point; |
| |
| // Data can be accessed via the references and the original owner |
| println!("Point has coordinates: ({}, {}, {})", |
| borrowed_point.x, another_borrow.y, point.z); |
| |
| // Error! Can't borrow `point` as mutable because it's currently |
| // borrowed as immutable. |
| // let mutable_borrow = &mut point; |
| // TODO ^ Try uncommenting this line |
| |
| // The borrowed values are used again here |
| println!("Point has coordinates: ({}, {}, {})", |
| borrowed_point.x, another_borrow.y, point.z); |
| |
| // The immutable references are no longer used for the rest of the code so |
| // it is possible to reborrow with a mutable reference. |
| let mutable_borrow = &mut point; |
| |
| // Change data via mutable reference |
| mutable_borrow.x = 5; |
| mutable_borrow.y = 2; |
| mutable_borrow.z = 1; |
| |
| // Error! Can't borrow `point` as immutable because it's currently |
| // borrowed as mutable. |
| // let y = &point.y; |
| // TODO ^ Try uncommenting this line |
| |
| // Error! Can't print because `println!` takes an immutable reference. |
| // println!("Point Z coordinate is {}", point.z); |
| // TODO ^ Try uncommenting this line |
| |
| // Ok! Mutable references can be passed as immutable to `println!` |
| println!("Point has coordinates: ({}, {}, {})", |
| mutable_borrow.x, mutable_borrow.y, mutable_borrow.z); |
| |
| // The mutable reference is no longer used for the rest of the code so it |
| // is possible to reborrow |
| let new_borrowed_point = &point; |
| println!("Point now has coordinates: ({}, {}, {})", |
| new_borrowed_point.x, new_borrowed_point.y, new_borrowed_point.z); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="the-ref-pattern"><a class="header" href="#the-ref-pattern">The ref pattern</a></h1> |
| <p>When doing pattern matching or destructuring via the <code>let</code> binding, the <code>ref</code> |
| keyword can be used to take references to the fields of a struct/tuple. The |
| example below shows a few instances where this can be useful:</p> |
| <pre><pre class="playground"><code class="language-rust editable">#[derive(Clone, Copy)] |
| struct Point { x: i32, y: i32 } |
| |
| fn main() { |
| let c = 'Q'; |
| |
| // A `ref` borrow on the left side of an assignment is equivalent to |
| // an `&` borrow on the right side. |
| let ref ref_c1 = c; |
| let ref_c2 = &c; |
| |
| println!("ref_c1 equals ref_c2: {}", *ref_c1 == *ref_c2); |
| |
| let point = Point { x: 0, y: 0 }; |
| |
| // `ref` is also valid when destructuring a struct. |
| let _copy_of_x = { |
| // `ref_to_x` is a reference to the `x` field of `point`. |
| let Point { x: ref ref_to_x, y: _ } = point; |
| |
| // Return a copy of the `x` field of `point`. |
| *ref_to_x |
| }; |
| |
| // A mutable copy of `point` |
| let mut mutable_point = point; |
| |
| { |
| // `ref` can be paired with `mut` to take mutable references. |
| let Point { x: _, y: ref mut mut_ref_to_y } = mutable_point; |
| |
| // Mutate the `y` field of `mutable_point` via a mutable reference. |
| *mut_ref_to_y = 1; |
| } |
| |
| println!("point is ({}, {})", point.x, point.y); |
| println!("mutable_point is ({}, {})", mutable_point.x, mutable_point.y); |
| |
| // A mutable tuple that includes a pointer |
| let mut mutable_tuple = (Box::new(5u32), 3u32); |
| |
| { |
| // Destructure `mutable_tuple` to change the value of `last`. |
| let (_, ref mut last) = mutable_tuple; |
| *last = 2u32; |
| } |
| |
| println!("tuple is {:?}", mutable_tuple); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="lifetimes"><a class="header" href="#lifetimes">Lifetimes</a></h1> |
| <p>A <em>lifetime</em> is a construct the compiler (or more specifically, its <em>borrow |
| checker</em>) uses to ensure all borrows are valid. Specifically, a variable's |
| lifetime begins when it is created and ends when it is destroyed. While |
| lifetimes and scopes are often referred to together, they are not the same.</p> |
| <p>Take, for example, the case where we borrow a variable via <code>&</code>. The |
| borrow has a lifetime that is determined by where it is declared. As a result, |
| the borrow is valid as long as it ends before the lender is destroyed. However, |
| the scope of the borrow is determined by where the reference is used.</p> |
| <p>In the following example and in the rest of this section, we will see how |
| lifetimes relate to scopes, as well as how the two differ.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Lifetimes are annotated below with lines denoting the creation |
| // and destruction of each variable. |
| // `i` has the longest lifetime because its scope entirely encloses |
| // both `borrow1` and `borrow2`. The duration of `borrow1` compared |
| // to `borrow2` is irrelevant since they are disjoint. |
| fn main() { |
| let i = 3; // Lifetime for `i` starts. ────────────────┐ |
| // │ |
| { // │ |
| let borrow1 = &i; // `borrow1` lifetime starts. ──┐│ |
| // ││ |
| println!("borrow1: {}", borrow1); // ││ |
| } // `borrow1 ends. ──────────────────────────────────┘│ |
| // │ |
| // │ |
| { // │ |
| let borrow2 = &i; // `borrow2` lifetime starts. ──┐│ |
| // ││ |
| println!("borrow2: {}", borrow2); // ││ |
| } // `borrow2` ends. ─────────────────────────────────┘│ |
| // │ |
| } // Lifetime ends. ─────────────────────────────────────┘ |
| </code></pre></pre> |
| <p>Note that no names or types are assigned to label lifetimes. |
| This restricts how lifetimes will be able to be used as we will see.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="explicit-annotation"><a class="header" href="#explicit-annotation">Explicit annotation</a></h1> |
| <p>The borrow checker uses explicit lifetime annotations to determine |
| how long references should be valid. In cases where lifetimes are not |
| elided<sup class="footnote-reference"><a href="#1">1</a></sup>, Rust requires explicit annotations to determine what the |
| lifetime of a reference should be. The syntax for explicitly annotating |
| a lifetime uses an apostrophe character as follows: </p> |
| <pre><code class="language-rust ignore">foo<'a> |
| // `foo` has a lifetime parameter `'a` |
| </code></pre> |
| <p>Similar to <a href="scope/lifetime/../../fn/closures/anonymity.html">closures</a>, using lifetimes requires generics. |
| Additionally, this lifetime syntax indicates that the lifetime of <code>foo</code> |
| may not exceed that of <code>'a</code>. Explicit annotation of a type has the form |
| <code>&'a T</code> where <code>'a</code> has already been introduced.</p> |
| <p>In cases with multiple lifetimes, the syntax is similar:</p> |
| <pre><code class="language-rust ignore">foo<'a, 'b> |
| // `foo` has lifetime parameters `'a` and `'b` |
| </code></pre> |
| <p>In this case, the lifetime of <code>foo</code> cannot exceed that of either <code>'a</code> <em>or</em> <code>'b</code>.</p> |
| <p>See the following example for explicit lifetime annotation in use:</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">// `print_refs` takes two references to `i32` which have different |
| // lifetimes `'a` and `'b`. These two lifetimes must both be at |
| // least as long as the function `print_refs`. |
| fn print_refs<'a, 'b>(x: &'a i32, y: &'b i32) { |
| println!("x is {} and y is {}", x, y); |
| } |
| |
| // A function which takes no arguments, but has a lifetime parameter `'a`. |
| fn failed_borrow<'a>() { |
| let _x = 12; |
| |
| // ERROR: `_x` does not live long enough |
| let y: &'a i32 = &_x; |
| // Attempting to use the lifetime `'a` as an explicit type annotation |
| // inside the function will fail because the lifetime of `&_x` is shorter |
| // than that of `y`. A short lifetime cannot be coerced into a longer one. |
| } |
| |
| fn main() { |
| // Create variables to be borrowed below. |
| let (four, nine) = (4, 9); |
| |
| // Borrows (`&`) of both variables are passed into the function. |
| print_refs(&four, &nine); |
| // Any input which is borrowed must outlive the borrower. |
| // In other words, the lifetime of `four` and `nine` must |
| // be longer than that of `print_refs`. |
| |
| failed_borrow(); |
| // `failed_borrow` contains no references to force `'a` to be |
| // longer than the lifetime of the function, but `'a` is longer. |
| // Because the lifetime is never constrained, it defaults to `'static`. |
| } |
| </code></pre></pre> |
| <div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup> |
| <p><a href="scope/lifetime/elision.html">elision</a> implicitly annotates lifetimes and so is different.</p> |
| </div> |
| <h3 id="see-also-48"><a class="header" href="#see-also-48">See also:</a></h3> |
| <p><a href="scope/lifetime/../../generics.html">generics</a> and <a href="scope/lifetime/../../fn/closures.html">closures</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="functions-2"><a class="header" href="#functions-2">Functions</a></h1> |
| <p>Ignoring <a href="scope/lifetime/elision.html">elision</a>, function signatures with lifetimes have a few constraints: </p> |
| <ul> |
| <li>any reference <em>must</em> have an annotated lifetime.</li> |
| <li>any reference being returned <em>must</em> have the same lifetime as an input or |
| be <code>static</code>.</li> |
| </ul> |
| <p>Additionally, note that returning references without input is banned if it |
| would result in returning references to invalid data. The following example shows |
| off some valid forms of functions with lifetimes:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// One input reference with lifetime `'a` which must live |
| // at least as long as the function. |
| fn print_one<'a>(x: &'a i32) { |
| println!("`print_one`: x is {}", x); |
| } |
| |
| // Mutable references are possible with lifetimes as well. |
| fn add_one<'a>(x: &'a mut i32) { |
| *x += 1; |
| } |
| |
| // Multiple elements with different lifetimes. In this case, it |
| // would be fine for both to have the same lifetime `'a`, but |
| // in more complex cases, different lifetimes may be required. |
| fn print_multi<'a, 'b>(x: &'a i32, y: &'b i32) { |
| println!("`print_multi`: x is {}, y is {}", x, y); |
| } |
| |
| // Returning references that have been passed in is acceptable. |
| // However, the correct lifetime must be returned. |
| fn pass_x<'a, 'b>(x: &'a i32, _: &'b i32) -> &'a i32 { x } |
| |
| //fn invalid_output<'a>() -> &'a String { &String::from("foo") } |
| // The above is invalid: `'a` must live longer than the function. |
| // Here, `&String::from("foo")` would create a `String`, followed by a |
| // reference. Then the data is dropped upon exiting the scope, leaving |
| // a reference to invalid data to be returned. |
| |
| fn main() { |
| let x = 7; |
| let y = 9; |
| |
| print_one(&x); |
| print_multi(&x, &y); |
| |
| let z = pass_x(&x, &y); |
| print_one(z); |
| |
| let mut t = 3; |
| add_one(&mut t); |
| print_one(&t); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-49"><a class="header" href="#see-also-49">See also:</a></h3> |
| <p><a href="scope/lifetime/fn.html">functions</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="methods-1"><a class="header" href="#methods-1">Methods</a></h1> |
| <p>Methods are annotated similarly to functions:</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Owner(i32); |
| |
| impl Owner { |
| // Annotate lifetimes as in a standalone function. |
| fn add_one<'a>(&'a mut self) { self.0 += 1; } |
| fn print<'a>(&'a self) { |
| println!("`print`: {}", self.0); |
| } |
| } |
| |
| fn main() { |
| let mut owner = Owner(18); |
| |
| owner.add_one(); |
| owner.print(); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-50"><a class="header" href="#see-also-50">See also:</a></h3> |
| <p><a href="scope/lifetime/../../fn/methods.html">methods</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="structs-1"><a class="header" href="#structs-1">Structs</a></h1> |
| <p>Annotation of lifetimes in structures are also similar to functions:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// A type `Borrowed` which houses a reference to an |
| // `i32`. The reference to `i32` must outlive `Borrowed`. |
| #[derive(Debug)] |
| struct Borrowed<'a>(&'a i32); |
| |
| // Similarly, both references here must outlive this structure. |
| #[derive(Debug)] |
| struct NamedBorrowed<'a> { |
| x: &'a i32, |
| y: &'a i32, |
| } |
| |
| // An enum which is either an `i32` or a reference to one. |
| #[derive(Debug)] |
| enum Either<'a> { |
| Num(i32), |
| Ref(&'a i32), |
| } |
| |
| fn main() { |
| let x = 18; |
| let y = 15; |
| |
| let single = Borrowed(&x); |
| let double = NamedBorrowed { x: &x, y: &y }; |
| let reference = Either::Ref(&x); |
| let number = Either::Num(y); |
| |
| println!("x is borrowed in {:?}", single); |
| println!("x and y are borrowed in {:?}", double); |
| println!("x is borrowed in {:?}", reference); |
| println!("y is *not* borrowed in {:?}", number); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-51"><a class="header" href="#see-also-51">See also:</a></h3> |
| <p><a href="scope/lifetime/../../custom_types/structs.html"><code>struct</code>s</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="traits-1"><a class="header" href="#traits-1">Traits</a></h1> |
| <p>Annotation of lifetimes in trait methods basically are similar to functions. |
| Note that <code>impl</code> may have annotation of lifetimes too.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// A struct with annotation of lifetimes. |
| #[derive(Debug)] |
| struct Borrowed<'a> { |
| x: &'a i32, |
| } |
| |
| // Annotate lifetimes to impl. |
| impl<'a> Default for Borrowed<'a> { |
| fn default() -> Self { |
| Self { |
| x: &10, |
| } |
| } |
| } |
| |
| fn main() { |
| let b: Borrowed = Default::default(); |
| println!("b is {:?}", b); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-52"><a class="header" href="#see-also-52">See also:</a></h3> |
| <p><a href="scope/lifetime/../../trait.html"><code>trait</code>s</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="bounds-1"><a class="header" href="#bounds-1">Bounds</a></h1> |
| <p>Just like generic types can be bounded, lifetimes (themselves generic) |
| use bounds as well. The <code>:</code> character has a slightly different meaning here, |
| but <code>+</code> is the same. Note how the following read:</p> |
| <ol> |
| <li><code>T: 'a</code>: <em>All</em> references in <code>T</code> must outlive lifetime <code>'a</code>.</li> |
| <li><code>T: Trait + 'a</code>: Type <code>T</code> must implement trait <code>Trait</code> and <em>all</em> references |
| in <code>T</code> must outlive <code>'a</code>.</li> |
| </ol> |
| <p>The example below shows the above syntax in action used after keyword <code>where</code>:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::fmt::Debug; // Trait to bound with. |
| |
| #[derive(Debug)] |
| struct Ref<'a, T: 'a>(&'a T); |
| // `Ref` contains a reference to a generic type `T` that has |
| // an unknown lifetime `'a`. `T` is bounded such that any |
| // *references* in `T` must outlive `'a`. Additionally, the lifetime |
| // of `Ref` may not exceed `'a`. |
| |
| // A generic function which prints using the `Debug` trait. |
| fn print<T>(t: T) where |
| T: Debug { |
| println!("`print`: t is {:?}", t); |
| } |
| |
| // Here a reference to `T` is taken where `T` implements |
| // `Debug` and all *references* in `T` outlive `'a`. In |
| // addition, `'a` must outlive the function. |
| fn print_ref<'a, T>(t: &'a T) where |
| T: Debug + 'a { |
| println!("`print_ref`: t is {:?}", t); |
| } |
| |
| fn main() { |
| let x = 7; |
| let ref_x = Ref(&x); |
| |
| print_ref(&ref_x); |
| print(ref_x); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-53"><a class="header" href="#see-also-53">See also:</a></h3> |
| <p><a href="scope/lifetime/../../generics.html">generics</a>, <a href="scope/lifetime/../../generics/bounds.html">bounds in generics</a>, and |
| <a href="scope/lifetime/../../generics/multi_bounds.html">multiple bounds in generics</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="coercion"><a class="header" href="#coercion">Coercion</a></h1> |
| <p>A longer lifetime can be coerced into a shorter one |
| so that it works inside a scope it normally wouldn't work in. |
| This comes in the form of inferred coercion by the Rust compiler, |
| and also in the form of declaring a lifetime difference:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Here, Rust infers a lifetime that is as short as possible. |
| // The two references are then coerced to that lifetime. |
| fn multiply<'a>(first: &'a i32, second: &'a i32) -> i32 { |
| first * second |
| } |
| |
| // `<'a: 'b, 'b>` reads as lifetime `'a` is at least as long as `'b`. |
| // Here, we take in an `&'a i32` and return a `&'b i32` as a result of coercion. |
| fn choose_first<'a: 'b, 'b>(first: &'a i32, _: &'b i32) -> &'b i32 { |
| first |
| } |
| |
| fn main() { |
| let first = 2; // Longer lifetime |
| |
| { |
| let second = 3; // Shorter lifetime |
| |
| println!("The product is {}", multiply(&first, &second)); |
| println!("{} is the first", choose_first(&first, &second)); |
| }; |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="static"><a class="header" href="#static">Static</a></h1> |
| <p>Rust has a few reserved lifetime names. One of those is <code>'static</code>. You |
| might encounter it in two situations:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// A reference with 'static lifetime: |
| let s: &'static str = "hello world"; |
| |
| // 'static as part of a trait bound: |
| fn generic<T>(x: T) where T: 'static {} |
| </code></pre></pre> |
| <p>Both are related but subtly different and this is a common source for |
| confusion when learning Rust. Here are some examples for each situation:</p> |
| <h2 id="reference-lifetime"><a class="header" href="#reference-lifetime">Reference lifetime</a></h2> |
| <p>As a reference lifetime <code>'static</code> indicates that the data pointed to by |
| the reference lives for the entire lifetime of the running program. |
| It can still be coerced to a shorter lifetime.</p> |
| <p>There are two ways to make a variable with <code>'static</code> lifetime, and both |
| are stored in the read-only memory of the binary:</p> |
| <ul> |
| <li>Make a constant with the <code>static</code> declaration.</li> |
| <li>Make a <code>string</code> literal which has type: <code>&'static str</code>.</li> |
| </ul> |
| <p>See the following example for a display of each method:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Make a constant with `'static` lifetime. |
| static NUM: i32 = 18; |
| |
| // Returns a reference to `NUM` where its `'static` |
| // lifetime is coerced to that of the input argument. |
| fn coerce_static<'a>(_: &'a i32) -> &'a i32 { |
| &NUM |
| } |
| |
| fn main() { |
| { |
| // Make a `string` literal and print it: |
| let static_string = "I'm in read-only memory"; |
| println!("static_string: {}", static_string); |
| |
| // When `static_string` goes out of scope, the reference |
| // can no longer be used, but the data remains in the binary. |
| } |
| |
| { |
| // Make an integer to use for `coerce_static`: |
| let lifetime_num = 9; |
| |
| // Coerce `NUM` to lifetime of `lifetime_num`: |
| let coerced_static = coerce_static(&lifetime_num); |
| |
| println!("coerced_static: {}", coerced_static); |
| } |
| |
| println!("NUM: {} stays accessible!", NUM); |
| } |
| </code></pre></pre> |
| <h2 id="trait-bound"><a class="header" href="#trait-bound">Trait bound</a></h2> |
| <p>As a trait bound, it means the type does not contain any non-static |
| references. Eg. the receiver can hold on to the type for as long as |
| they want and it will never become invalid until they drop it.</p> |
| <p>It's important to understand this means that any owned data always passes |
| a <code>'static</code> lifetime bound, but a reference to that owned data generally |
| does not:</p> |
| <pre><pre class="playground"><code class="language-rust editable compile_fail">use std::fmt::Debug; |
| |
| fn print_it( input: impl Debug + 'static ) { |
| println!( "'static value passed in is: {:?}", input ); |
| } |
| |
| fn main() { |
| // i is owned and contains no references, thus it's 'static: |
| let i = 5; |
| print_it(i); |
| |
| // oops, &i only has the lifetime defined by the scope of |
| // main(), so it's not 'static: |
| print_it(&i); |
| } |
| </code></pre></pre> |
| <p>The compiler will tell you:</p> |
| <pre><code class="language-ignore">error[E0597]: `i` does not live long enough |
| --> src/lib.rs:15:15 |
| | |
| 15 | print_it(&i); |
| | ---------^^-- |
| | | | |
| | | borrowed value does not live long enough |
| | argument requires that `i` is borrowed for `'static` |
| 16 | } |
| | - `i` dropped here while still borrowed |
| </code></pre> |
| <h3 id="see-also-54"><a class="header" href="#see-also-54">See also:</a></h3> |
| <p><a href="scope/lifetime/../../custom_types/constants.html"><code>'static</code> constants</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="elision"><a class="header" href="#elision">Elision</a></h1> |
| <p>Some lifetime patterns are overwhelmingly common and so the borrow checker |
| will allow you to omit them to save typing and to improve readability. |
| This is known as elision. Elision exists in Rust solely because these patterns |
| are common.</p> |
| <p>The following code shows a few examples of elision. For a more comprehensive |
| description of elision, see <a href="https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision">lifetime elision</a> in the book.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// `elided_input` and `annotated_input` essentially have identical signatures |
| // because the lifetime of `elided_input` is inferred by the compiler: |
| fn elided_input(x: &i32) { |
| println!("`elided_input`: {}", x); |
| } |
| |
| fn annotated_input<'a>(x: &'a i32) { |
| println!("`annotated_input`: {}", x); |
| } |
| |
| // Similarly, `elided_pass` and `annotated_pass` have identical signatures |
| // because the lifetime is added implicitly to `elided_pass`: |
| fn elided_pass(x: &i32) -> &i32 { x } |
| |
| fn annotated_pass<'a>(x: &'a i32) -> &'a i32 { x } |
| |
| fn main() { |
| let x = 3; |
| |
| elided_input(&x); |
| annotated_input(&x); |
| |
| println!("`elided_pass`: {}", elided_pass(&x)); |
| println!("`annotated_pass`: {}", annotated_pass(&x)); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-55"><a class="header" href="#see-also-55">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html#lifetime-elision">elision</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="traits-2"><a class="header" href="#traits-2">Traits</a></h1> |
| <p>A <code>trait</code> is a collection of methods defined for an unknown type: |
| <code>Self</code>. They can access other methods declared in the same trait.</p> |
| <p>Traits can be implemented for any data type. In the example below, |
| we define <code>Animal</code>, a group of methods. The <code>Animal</code> <code>trait</code> is |
| then implemented for the <code>Sheep</code> data type, allowing the use of |
| methods from <code>Animal</code> with a <code>Sheep</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Sheep { naked: bool, name: &'static str } |
| |
| trait Animal { |
| // Static method signature; `Self` refers to the implementor type. |
| fn new(name: &'static str) -> Self; |
| |
| // Instance method signatures; these will return a string. |
| fn name(&self) -> &'static str; |
| fn noise(&self) -> &'static str; |
| |
| // Traits can provide default method definitions. |
| fn talk(&self) { |
| println!("{} says {}", self.name(), self.noise()); |
| } |
| } |
| |
| impl Sheep { |
| fn is_naked(&self) -> bool { |
| self.naked |
| } |
| |
| fn shear(&mut self) { |
| if self.is_naked() { |
| // Implementor methods can use the implementor's trait methods. |
| println!("{} is already naked...", self.name()); |
| } else { |
| println!("{} gets a haircut!", self.name); |
| |
| self.naked = true; |
| } |
| } |
| } |
| |
| // Implement the `Animal` trait for `Sheep`. |
| impl Animal for Sheep { |
| // `Self` is the implementor type: `Sheep`. |
| fn new(name: &'static str) -> Sheep { |
| Sheep { name: name, naked: false } |
| } |
| |
| fn name(&self) -> &'static str { |
| self.name |
| } |
| |
| fn noise(&self) -> &'static str { |
| if self.is_naked() { |
| "baaaaah?" |
| } else { |
| "baaaaah!" |
| } |
| } |
| |
| // Default trait methods can be overridden. |
| fn talk(&self) { |
| // For example, we can add some quiet contemplation. |
| println!("{} pauses briefly... {}", self.name, self.noise()); |
| } |
| } |
| |
| fn main() { |
| // Type annotation is necessary in this case. |
| let mut dolly: Sheep = Animal::new("Dolly"); |
| // TODO ^ Try removing the type annotations. |
| |
| dolly.talk(); |
| dolly.shear(); |
| dolly.talk(); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="derive"><a class="header" href="#derive">Derive</a></h1> |
| <p>The compiler is capable of providing basic implementations for some traits via |
| the <code>#[derive]</code> <a href="trait/../attribute.html">attribute</a>. These traits can still be |
| manually implemented if a more complex behavior is required.</p> |
| <p>The following is a list of derivable traits:</p> |
| <ul> |
| <li>Comparison traits: |
| <a href="https://doc.rust-lang.org/std/cmp/trait.Eq.html"><code>Eq</code></a>, <a href="https://doc.rust-lang.org/std/cmp/trait.PartialEq.html"><code>PartialEq</code></a>, <a href="https://doc.rust-lang.org/std/cmp/trait.Ord.html"><code>Ord</code></a>, <a href="https://doc.rust-lang.org/std/cmp/trait.PartialOrd.html"><code>PartialOrd</code></a>.</li> |
| <li><a href="https://doc.rust-lang.org/std/clone/trait.Clone.html"><code>Clone</code></a>, to create <code>T</code> from <code>&T</code> via a copy.</li> |
| <li><a href="https://doc.rust-lang.org/core/marker/trait.Copy.html"><code>Copy</code></a>, to give a type 'copy semantics' instead of 'move semantics'.</li> |
| <li><a href="https://doc.rust-lang.org/std/hash/trait.Hash.html"><code>Hash</code></a>, to compute a hash from <code>&T</code>.</li> |
| <li><a href="https://doc.rust-lang.org/std/default/trait.Default.html"><code>Default</code></a>, to create an empty instance of a data type.</li> |
| <li><a href="https://doc.rust-lang.org/std/fmt/trait.Debug.html"><code>Debug</code></a>, to format a value using the <code>{:?}</code> formatter.</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable">// `Centimeters`, a tuple struct that can be compared |
| #[derive(PartialEq, PartialOrd)] |
| struct Centimeters(f64); |
| |
| // `Inches`, a tuple struct that can be printed |
| #[derive(Debug)] |
| struct Inches(i32); |
| |
| impl Inches { |
| fn to_centimeters(&self) -> Centimeters { |
| let &Inches(inches) = self; |
| |
| Centimeters(inches as f64 * 2.54) |
| } |
| } |
| |
| // `Seconds`, a tuple struct with no additional attributes |
| struct Seconds(i32); |
| |
| fn main() { |
| let _one_second = Seconds(1); |
| |
| // Error: `Seconds` can't be printed; it doesn't implement the `Debug` trait |
| //println!("One second looks like: {:?}", _one_second); |
| // TODO ^ Try uncommenting this line |
| |
| // Error: `Seconds` can't be compared; it doesn't implement the `PartialEq` trait |
| //let _this_is_true = (_one_second == _one_second); |
| // TODO ^ Try uncommenting this line |
| |
| let foot = Inches(12); |
| |
| println!("One foot equals {:?}", foot); |
| |
| let meter = Centimeters(100.0); |
| |
| let cmp = |
| if foot.to_centimeters() < meter { |
| "smaller" |
| } else { |
| "bigger" |
| }; |
| |
| println!("One foot is {} than one meter.", cmp); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-56"><a class="header" href="#see-also-56">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/reference/attributes.html#derive"><code>derive</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="returning-traits-with-dyn"><a class="header" href="#returning-traits-with-dyn">Returning Traits with <code>dyn</code></a></h1> |
| <p>The Rust compiler needs to know how much space every function's return type requires. This means all your functions have to return a concrete type. Unlike other languages, if you have a trait like <code>Animal</code>, you can't write a function that returns <code>Animal</code>, because its different implementations will need different amounts of memory. </p> |
| <p>However, there's an easy workaround. Instead of returning a trait object directly, our functions return a <code>Box</code> which <em>contains</em> some <code>Animal</code>. A <code>box</code> is just a reference to some memory in the heap. Because a reference has a statically-known size, and the compiler can guarantee it points to a heap-allocated <code>Animal</code>, we can return a trait from our function!</p> |
| <p>Rust tries to be as explicit as possible whenever it allocates memory on the heap. So if your function returns a pointer-to-trait-on-heap in this way, you need to write the return type with the <code>dyn</code> keyword, e.g. <code>Box<dyn Animal></code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Sheep {} |
| struct Cow {} |
| |
| trait Animal { |
| // Instance method signature |
| fn noise(&self) -> &'static str; |
| } |
| |
| // Implement the `Animal` trait for `Sheep`. |
| impl Animal for Sheep { |
| fn noise(&self) -> &'static str { |
| "baaaaah!" |
| } |
| } |
| |
| // Implement the `Animal` trait for `Cow`. |
| impl Animal for Cow { |
| fn noise(&self) -> &'static str { |
| "moooooo!" |
| } |
| } |
| |
| // Returns some struct that implements Animal, but we don't know which one at compile time. |
| fn random_animal(random_number: f64) -> Box<dyn Animal> { |
| if random_number < 0.5 { |
| Box::new(Sheep {}) |
| } else { |
| Box::new(Cow {}) |
| } |
| } |
| |
| fn main() { |
| let random_number = 0.234; |
| let animal = random_animal(random_number); |
| println!("You've randomly chosen an animal, and it says {}", animal.noise()); |
| } |
| |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="operator-overloading"><a class="header" href="#operator-overloading">Operator Overloading</a></h1> |
| <p>In Rust, many of the operators can be overloaded via traits. That is, some operators can |
| be used to accomplish different tasks based on their input arguments. This is possible |
| because operators are syntactic sugar for method calls. For example, the <code>+</code> operator in |
| <code>a + b</code> calls the <code>add</code> method (as in <code>a.add(b)</code>). This <code>add</code> method is part of the <code>Add</code> |
| trait. Hence, the <code>+</code> operator can be used by any implementor of the <code>Add</code> trait.</p> |
| <p>A list of the traits, such as <code>Add</code>, that overload operators can be found in <a href="https://doc.rust-lang.org/core/ops/"><code>core::ops</code></a>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::ops; |
| |
| struct Foo; |
| struct Bar; |
| |
| #[derive(Debug)] |
| struct FooBar; |
| |
| #[derive(Debug)] |
| struct BarFoo; |
| |
| // The `std::ops::Add` trait is used to specify the functionality of `+`. |
| // Here, we make `Add<Bar>` - the trait for addition with a RHS of type `Bar`. |
| // The following block implements the operation: Foo + Bar = FooBar |
| impl ops::Add<Bar> for Foo { |
| type Output = FooBar; |
| |
| fn add(self, _rhs: Bar) -> FooBar { |
| println!("> Foo.add(Bar) was called"); |
| |
| FooBar |
| } |
| } |
| |
| // By reversing the types, we end up implementing non-commutative addition. |
| // Here, we make `Add<Foo>` - the trait for addition with a RHS of type `Foo`. |
| // This block implements the operation: Bar + Foo = BarFoo |
| impl ops::Add<Foo> for Bar { |
| type Output = BarFoo; |
| |
| fn add(self, _rhs: Foo) -> BarFoo { |
| println!("> Bar.add(Foo) was called"); |
| |
| BarFoo |
| } |
| } |
| |
| fn main() { |
| println!("Foo + Bar = {:?}", Foo + Bar); |
| println!("Bar + Foo = {:?}", Bar + Foo); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-57"><a class="header" href="#see-also-57">See Also</a></h3> |
| <p><a href="https://doc.rust-lang.org/core/ops/trait.Add.html">Add</a>, <a href="https://doc.rust-lang.org/book/appendix-02-operators.html">Syntax Index</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="drop"><a class="header" href="#drop">Drop</a></h1> |
| <p>The <a href="https://doc.rust-lang.org/std/ops/trait.Drop.html"><code>Drop</code></a> trait only has one method: <code>drop</code>, which is called automatically |
| when an object goes out of scope. The main use of the <code>Drop</code> trait is to free the |
| resources that the implementor instance owns.</p> |
| <p><code>Box</code>, <code>Vec</code>, <code>String</code>, <code>File</code>, and <code>Process</code> are some examples of types that |
| implement the <code>Drop</code> trait to free resources. The <code>Drop</code> trait can also be |
| manually implemented for any custom data type.</p> |
| <p>The following example adds a print to console to the <code>drop</code> function to announce |
| when it is called.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Droppable { |
| name: &'static str, |
| } |
| |
| // This trivial implementation of `drop` adds a print to console. |
| impl Drop for Droppable { |
| fn drop(&mut self) { |
| println!("> Dropping {}", self.name); |
| } |
| } |
| |
| fn main() { |
| let _a = Droppable { name: "a" }; |
| |
| // block A |
| { |
| let _b = Droppable { name: "b" }; |
| |
| // block B |
| { |
| let _c = Droppable { name: "c" }; |
| let _d = Droppable { name: "d" }; |
| |
| println!("Exiting block B"); |
| } |
| println!("Just exited block B"); |
| |
| println!("Exiting block A"); |
| } |
| println!("Just exited block A"); |
| |
| // Variable can be manually dropped using the `drop` function |
| drop(_a); |
| // TODO ^ Try commenting this line |
| |
| println!("end of the main function"); |
| |
| // `_a` *won't* be `drop`ed again here, because it already has been |
| // (manually) `drop`ed |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="iterators"><a class="header" href="#iterators">Iterators</a></h1> |
| <p>The <a href="https://doc.rust-lang.org/core/iter/trait.Iterator.html"><code>Iterator</code></a> trait is used to implement iterators over collections such as arrays.</p> |
| <p>The trait requires only a method to be defined for the <code>next</code> element, |
| which may be manually defined in an <code>impl</code> block or automatically |
| defined (as in arrays and ranges).</p> |
| <p>As a point of convenience for common situations, the <code>for</code> construct |
| turns some collections into iterators using the <a href="https://doc.rust-lang.org/std/iter/trait.IntoIterator.html"><code>.into_iter()</code></a> method.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Fibonacci { |
| curr: u32, |
| next: u32, |
| } |
| |
| // Implement `Iterator` for `Fibonacci`. |
| // The `Iterator` trait only requires a method to be defined for the `next` element. |
| impl Iterator for Fibonacci { |
| // We can refer to this type using Self::Item |
| type Item = u32; |
| |
| // Here, we define the sequence using `.curr` and `.next`. |
| // The return type is `Option<T>`: |
| // * When the `Iterator` is finished, `None` is returned. |
| // * Otherwise, the next value is wrapped in `Some` and returned. |
| // We use Self::Item in the return type, so we can change |
| // the type without having to update the function signatures. |
| fn next(&mut self) -> Option<Self::Item> { |
| let new_next = self.curr + self.next; |
| |
| self.curr = self.next; |
| self.next = new_next; |
| |
| // Since there's no endpoint to a Fibonacci sequence, the `Iterator` |
| // will never return `None`, and `Some` is always returned. |
| Some(self.curr) |
| } |
| } |
| |
| // Returns a Fibonacci sequence generator |
| fn fibonacci() -> Fibonacci { |
| Fibonacci { curr: 0, next: 1 } |
| } |
| |
| fn main() { |
| // `0..3` is an `Iterator` that generates: 0, 1, and 2. |
| let mut sequence = 0..3; |
| |
| println!("Four consecutive `next` calls on 0..3"); |
| println!("> {:?}", sequence.next()); |
| println!("> {:?}", sequence.next()); |
| println!("> {:?}", sequence.next()); |
| println!("> {:?}", sequence.next()); |
| |
| // `for` works through an `Iterator` until it returns `None`. |
| // Each `Some` value is unwrapped and bound to a variable (here, `i`). |
| println!("Iterate through 0..3 using `for`"); |
| for i in 0..3 { |
| println!("> {}", i); |
| } |
| |
| // The `take(n)` method reduces an `Iterator` to its first `n` terms. |
| println!("The first four terms of the Fibonacci sequence are: "); |
| for i in fibonacci().take(4) { |
| println!("> {}", i); |
| } |
| |
| // The `skip(n)` method shortens an `Iterator` by dropping its first `n` terms. |
| println!("The next four terms of the Fibonacci sequence are: "); |
| for i in fibonacci().skip(4).take(4) { |
| println!("> {}", i); |
| } |
| |
| let array = [1u32, 3, 3, 7]; |
| |
| // The `iter` method produces an `Iterator` over an array/slice. |
| println!("Iterate the following array {:?}", &array); |
| for i in array.iter() { |
| println!("> {}", i); |
| } |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="impl-trait"><a class="header" href="#impl-trait"><code>impl Trait</code></a></h1> |
| <p>If your function returns a type that implements <code>MyTrait</code>, you can write its |
| return type as <code>-> impl MyTrait</code>. This can help simplify your type signatures quite a lot!</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::iter; |
| use std::vec::IntoIter; |
| |
| // This function combines two `Vec<i32>` and returns an iterator over it. |
| // Look how complicated its return type is! |
| fn combine_vecs_explicit_return_type( |
| v: Vec<i32>, |
| u: Vec<i32>, |
| ) -> iter::Cycle<iter::Chain<IntoIter<i32>, IntoIter<i32>>> { |
| v.into_iter().chain(u.into_iter()).cycle() |
| } |
| |
| // This is the exact same function, but its return type uses `impl Trait`. |
| // Look how much simpler it is! |
| fn combine_vecs( |
| v: Vec<i32>, |
| u: Vec<i32>, |
| ) -> impl Iterator<Item=i32> { |
| v.into_iter().chain(u.into_iter()).cycle() |
| } |
| |
| fn main() { |
| let v1 = vec![1, 2, 3]; |
| let v2 = vec![4, 5]; |
| let mut v3 = combine_vecs(v1, v2); |
| assert_eq!(Some(1), v3.next()); |
| assert_eq!(Some(2), v3.next()); |
| assert_eq!(Some(3), v3.next()); |
| assert_eq!(Some(4), v3.next()); |
| assert_eq!(Some(5), v3.next()); |
| println!("all done"); |
| } |
| </code></pre></pre> |
| <p>More importantly, some Rust types can't be written out. For example, every |
| closure has its own unnamed concrete type. Before <code>impl Trait</code> syntax, you had |
| to allocate on the heap in order to return a closure. But now you can do it all |
| statically, like this:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// Returns a function that adds `y` to its input |
| fn make_adder_function(y: i32) -> impl Fn(i32) -> i32 { |
| let closure = move |x: i32| { x + y }; |
| closure |
| } |
| |
| fn main() { |
| let plus_one = make_adder_function(1); |
| assert_eq!(plus_one(2), 3); |
| } |
| </code></pre></pre> |
| <p>You can also use <code>impl Trait</code> to return an iterator that uses <code>map</code> or <code>filter</code> |
| closures! This makes using <code>map</code> and <code>filter</code> easier. Because closure types don't |
| have names, you can't write out an explicit return type if your function returns |
| iterators with closures. But with <code>impl Trait</code> you can do this easily:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn double_positives<'a>(numbers: &'a Vec<i32>) -> impl Iterator<Item = i32> + 'a { |
| numbers |
| .iter() |
| .filter(|x| x > &&0) |
| .map(|x| x * 2) |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="clone"><a class="header" href="#clone">Clone</a></h1> |
| <p>When dealing with resources, the default behavior is to transfer them during |
| assignments or function calls. However, sometimes we need to make a |
| copy of the resource as well.</p> |
| <p>The <a href="https://doc.rust-lang.org/std/clone/trait.Clone.html"><code>Clone</code></a> trait helps us do exactly this. Most commonly, we can |
| use the <code>.clone()</code> method defined by the <code>Clone</code> trait.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// A unit struct without resources |
| #[derive(Debug, Clone, Copy)] |
| struct Unit; |
| |
| // A tuple struct with resources that implements the `Clone` trait |
| #[derive(Clone, Debug)] |
| struct Pair(Box<i32>, Box<i32>); |
| |
| fn main() { |
| // Instantiate `Unit` |
| let unit = Unit; |
| // Copy `Unit`, there are no resources to move |
| let copied_unit = unit; |
| |
| // Both `Unit`s can be used independently |
| println!("original: {:?}", unit); |
| println!("copy: {:?}", copied_unit); |
| |
| // Instantiate `Pair` |
| let pair = Pair(Box::new(1), Box::new(2)); |
| println!("original: {:?}", pair); |
| |
| // Move `pair` into `moved_pair`, moves resources |
| let moved_pair = pair; |
| println!("moved: {:?}", moved_pair); |
| |
| // Error! `pair` has lost its resources |
| //println!("original: {:?}", pair); |
| // TODO ^ Try uncommenting this line |
| |
| // Clone `moved_pair` into `cloned_pair` (resources are included) |
| let cloned_pair = moved_pair.clone(); |
| // Drop the original pair using std::mem::drop |
| drop(moved_pair); |
| |
| // Error! `moved_pair` has been dropped |
| //println!("copy: {:?}", moved_pair); |
| // TODO ^ Try uncommenting this line |
| |
| // The result from .clone() can still be used! |
| println!("clone: {:?}", cloned_pair); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="supertraits"><a class="header" href="#supertraits">Supertraits</a></h1> |
| <p>Rust doesn't have "inheritance", but you can define a trait as being a superset |
| of another trait. For example:</p> |
| <pre><pre class="playground"><code class="language-rust editable">trait Person { |
| fn name(&self) -> String; |
| } |
| |
| // Person is a supertrait of Student. |
| // Implementing Student requires you to also impl Person. |
| trait Student: Person { |
| fn university(&self) -> String; |
| } |
| |
| trait Programmer { |
| fn fav_language(&self) -> String; |
| } |
| |
| // CompSciStudent (computer science student) is a subtrait of both Programmer |
| // and Student. Implementing CompSciStudent requires you to impl both supertraits. |
| trait CompSciStudent: Programmer + Student { |
| fn git_username(&self) -> String; |
| } |
| |
| fn comp_sci_student_greeting(student: &dyn CompSciStudent) -> String { |
| format!( |
| "My name is {} and I attend {}. My favorite language is {}. My Git username is {}", |
| student.name(), |
| student.university(), |
| student.fav_language(), |
| student.git_username() |
| ) |
| } |
| |
| fn main() {} |
| </code></pre></pre> |
| <h3 id="see-also-58"><a class="header" href="#see-also-58">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#using-supertraits-to-require-one-traits-functionality-within-another-trait">The Rust Programming Language chapter on supertraits</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="disambiguating-overlapping-traits"><a class="header" href="#disambiguating-overlapping-traits">Disambiguating overlapping traits</a></h1> |
| <p>A type can implement many different traits. What if two traits both require the same name? For example, many traits might have a method named <code>get()</code>. They might even have different return types! </p> |
| <p>Good news: because each trait implementation gets its own <code>impl</code> block, it's |
| clear which trait's <code>get</code> method you're implementing. </p> |
| <p>What about when it comes time to <em>call</em> those methods? To disambiguate between |
| them, we have to use Fully Qualified Syntax.</p> |
| <pre><pre class="playground"><code class="language-rust editable">trait UsernameWidget { |
| // Get the selected username out of this widget |
| fn get(&self) -> String; |
| } |
| |
| trait AgeWidget { |
| // Get the selected age out of this widget |
| fn get(&self) -> u8; |
| } |
| |
| // A form with both a UsernameWidget and an AgeWidget |
| struct Form { |
| username: String, |
| age: u8, |
| } |
| |
| impl UsernameWidget for Form { |
| fn get(&self) -> String { |
| self.username.clone() |
| } |
| } |
| |
| impl AgeWidget for Form { |
| fn get(&self) -> u8 { |
| self.age |
| } |
| } |
| |
| fn main() { |
| let form = Form{ |
| username: "rustacean".to_owned(), |
| age: 28, |
| }; |
| |
| // If you uncomment this line, you'll get an error saying |
| // "multiple `get` found". Because, after all, there are multiple methods |
| // named `get`. |
| // println!("{}", form.get()); |
| |
| let username = <Form as UsernameWidget>::get(&form); |
| assert_eq!("rustacean".to_owned(), username); |
| let age = <Form as AgeWidget>::get(&form); |
| assert_eq!(28, age); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-59"><a class="header" href="#see-also-59">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name">The Rust Programming Language chapter on Fully Qualified syntax</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="macro_rules"><a class="header" href="#macro_rules">macro_rules!</a></h1> |
| <p>Rust provides a powerful macro system that allows metaprogramming. As you've |
| seen in previous chapters, macros look like functions, except that their name |
| ends with a bang <code>!</code>, but instead of generating a function call, macros are |
| expanded into source code that gets compiled with the rest of the program. |
| However, unlike macros in C and other languages, Rust macros are expanded into |
| abstract syntax trees, rather than string preprocessing, so you don't get |
| unexpected precedence bugs.</p> |
| <p>Macros are created using the <code>macro_rules!</code> macro.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// This is a simple macro named `say_hello`. |
| macro_rules! say_hello { |
| // `()` indicates that the macro takes no argument. |
| () => { |
| // The macro will expand into the contents of this block. |
| println!("Hello!"); |
| }; |
| } |
| |
| fn main() { |
| // This call will expand into `println!("Hello");` |
| say_hello!() |
| } |
| </code></pre></pre> |
| <p>So why are macros useful?</p> |
| <ol> |
| <li> |
| <p>Don't repeat yourself. There are many cases where you may need similar |
| functionality in multiple places but with different types. Often, writing a |
| macro is a useful way to avoid repeating code. (More on this later)</p> |
| </li> |
| <li> |
| <p>Domain-specific languages. Macros allow you to define special syntax for a |
| specific purpose. (More on this later)</p> |
| </li> |
| <li> |
| <p>Variadic interfaces. Sometimes you want to define an interface that takes a |
| variable number of arguments. An example is <code>println!</code> which could take any |
| number of arguments, depending on the format string!. (More on this later)</p> |
| </li> |
| </ol> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="syntax"><a class="header" href="#syntax">Syntax</a></h1> |
| <p>In following subsections, we will show how to define macros in Rust. |
| There are three basic ideas:</p> |
| <ul> |
| <li><a href="macros/designators.html">Patterns and Designators</a></li> |
| <li><a href="macros/overload.html">Overloading</a></li> |
| <li><a href="macros/repeat.html">Repetition</a></li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="designators"><a class="header" href="#designators">Designators</a></h1> |
| <p>The arguments of a macro are prefixed by a dollar sign <code>$</code> and type annotated |
| with a <em>designator</em>:</p> |
| <pre><pre class="playground"><code class="language-rust editable">macro_rules! create_function { |
| // This macro takes an argument of designator `ident` and |
| // creates a function named `$func_name`. |
| // The `ident` designator is used for variable/function names. |
| ($func_name:ident) => { |
| fn $func_name() { |
| // The `stringify!` macro converts an `ident` into a string. |
| println!("You called {:?}()", |
| stringify!($func_name)); |
| } |
| }; |
| } |
| |
| // Create functions named `foo` and `bar` with the above macro. |
| create_function!(foo); |
| create_function!(bar); |
| |
| macro_rules! print_result { |
| // This macro takes an expression of type `expr` and prints |
| // it as a string along with its result. |
| // The `expr` designator is used for expressions. |
| ($expression:expr) => { |
| // `stringify!` will convert the expression *as it is* into a string. |
| println!("{:?} = {:?}", |
| stringify!($expression), |
| $expression); |
| }; |
| } |
| |
| fn main() { |
| foo(); |
| bar(); |
| |
| print_result!(1u32 + 1); |
| |
| // Recall that blocks are expressions too! |
| print_result!({ |
| let x = 1u32; |
| |
| x * x + 2 * x - 1 |
| }); |
| } |
| </code></pre></pre> |
| <p>These are some of the available designators:</p> |
| <ul> |
| <li><code>block</code></li> |
| <li><code>expr</code> is used for expressions</li> |
| <li><code>ident</code> is used for variable/function names</li> |
| <li><code>item</code></li> |
| <li><code>literal</code> is used for literal constants</li> |
| <li><code>pat</code> (<em>pattern</em>)</li> |
| <li><code>path</code></li> |
| <li><code>stmt</code> (<em>statement</em>)</li> |
| <li><code>tt</code> (<em>token tree</em>)</li> |
| <li><code>ty</code> (<em>type</em>)</li> |
| <li><code>vis</code> (<em>visibility qualifier</em>)</li> |
| </ul> |
| <p>For a complete list, see the <a href="https://doc.rust-lang.org/reference/macros-by-example.html">Rust Reference</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="overload"><a class="header" href="#overload">Overload</a></h1> |
| <p>Macros can be overloaded to accept different combinations of arguments. |
| In that regard, <code>macro_rules!</code> can work similarly to a match block:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// `test!` will compare `$left` and `$right` |
| // in different ways depending on how you invoke it: |
| macro_rules! test { |
| // Arguments don't need to be separated by a comma. |
| // Any template can be used! |
| ($left:expr; and $right:expr) => { |
| println!("{:?} and {:?} is {:?}", |
| stringify!($left), |
| stringify!($right), |
| $left && $right) |
| }; |
| // ^ each arm must end with a semicolon. |
| ($left:expr; or $right:expr) => { |
| println!("{:?} or {:?} is {:?}", |
| stringify!($left), |
| stringify!($right), |
| $left || $right) |
| }; |
| } |
| |
| fn main() { |
| test!(1i32 + 1 == 2i32; and 2i32 * 2 == 4i32); |
| test!(true; or false); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="repeat"><a class="header" href="#repeat">Repeat</a></h1> |
| <p>Macros can use <code>+</code> in the argument list to indicate that an argument may |
| repeat at least once, or <code>*</code>, to indicate that the argument may repeat zero or |
| more times.</p> |
| <p>In the following example, surrounding the matcher with <code>$(...),+</code> will |
| match one or more expression, separated by commas. |
| Also note that the semicolon is optional on the last case.</p> |
| <pre><pre class="playground"><code class="language-rust editable">// `find_min!` will calculate the minimum of any number of arguments. |
| macro_rules! find_min { |
| // Base case: |
| ($x:expr) => ($x); |
| // `$x` followed by at least one `$y,` |
| ($x:expr, $($y:expr),+) => ( |
| // Call `find_min!` on the tail `$y` |
| std::cmp::min($x, find_min!($($y),+)) |
| ) |
| } |
| |
| fn main() { |
| println!("{}", find_min!(1u32)); |
| println!("{}", find_min!(1u32 + 2, 2u32)); |
| println!("{}", find_min!(5u32, 2u32 * 3, 4u32)); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="dry-dont-repeat-yourself"><a class="header" href="#dry-dont-repeat-yourself">DRY (Don't Repeat Yourself)</a></h1> |
| <p>Macros allow writing DRY code by factoring out the common parts of functions |
| and/or test suites. Here is an example that implements and tests the <code>+=</code>, <code>*=</code> |
| and <code>-=</code> operators on <code>Vec<T></code>:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::ops::{Add, Mul, Sub}; |
| |
| macro_rules! assert_equal_len { |
| // The `tt` (token tree) designator is used for |
| // operators and tokens. |
| ($a:expr, $b:expr, $func:ident, $op:tt) => { |
| assert!($a.len() == $b.len(), |
| "{:?}: dimension mismatch: {:?} {:?} {:?}", |
| stringify!($func), |
| ($a.len(),), |
| stringify!($op), |
| ($b.len(),)); |
| }; |
| } |
| |
| macro_rules! op { |
| ($func:ident, $bound:ident, $op:tt, $method:ident) => { |
| fn $func<T: $bound<T, Output=T> + Copy>(xs: &mut Vec<T>, ys: &Vec<T>) { |
| assert_equal_len!(xs, ys, $func, $op); |
| |
| for (x, y) in xs.iter_mut().zip(ys.iter()) { |
| *x = $bound::$method(*x, *y); |
| // *x = x.$method(*y); |
| } |
| } |
| }; |
| } |
| |
| // Implement `add_assign`, `mul_assign`, and `sub_assign` functions. |
| op!(add_assign, Add, +=, add); |
| op!(mul_assign, Mul, *=, mul); |
| op!(sub_assign, Sub, -=, sub); |
| |
| mod test { |
| use std::iter; |
| macro_rules! test { |
| ($func:ident, $x:expr, $y:expr, $z:expr) => { |
| #[test] |
| fn $func() { |
| for size in 0usize..10 { |
| let mut x: Vec<_> = iter::repeat($x).take(size).collect(); |
| let y: Vec<_> = iter::repeat($y).take(size).collect(); |
| let z: Vec<_> = iter::repeat($z).take(size).collect(); |
| |
| super::$func(&mut x, &y); |
| |
| assert_eq!(x, z); |
| } |
| } |
| }; |
| } |
| |
| // Test `add_assign`, `mul_assign`, and `sub_assign`. |
| test!(add_assign, 1u32, 2u32, 3u32); |
| test!(mul_assign, 2u32, 3u32, 6u32); |
| test!(sub_assign, 3u32, 2u32, 1u32); |
| } |
| </code></pre></pre> |
| <pre><code class="language-shell">$ rustc --test dry.rs && ./dry |
| running 3 tests |
| test test::mul_assign ... ok |
| test test::add_assign ... ok |
| test test::sub_assign ... ok |
| |
| test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="domain-specific-languages-dsls"><a class="header" href="#domain-specific-languages-dsls">Domain Specific Languages (DSLs)</a></h1> |
| <p>A DSL is a mini "language" embedded in a Rust macro. It is completely valid |
| Rust because the macro system expands into normal Rust constructs, but it looks |
| like a small language. This allows you to define concise or intuitive syntax for |
| some special functionality (within bounds).</p> |
| <p>Suppose that I want to define a little calculator API. I would like to supply |
| an expression and have the output printed to console.</p> |
| <pre><pre class="playground"><code class="language-rust editable">macro_rules! calculate { |
| (eval $e:expr) => {{ |
| { |
| let val: usize = $e; // Force types to be integers |
| println!("{} = {}", stringify!{$e}, val); |
| } |
| }}; |
| } |
| |
| fn main() { |
| calculate! { |
| eval 1 + 2 // hehehe `eval` is _not_ a Rust keyword! |
| } |
| |
| calculate! { |
| eval (1 + 2) * (3 / 4) |
| } |
| } |
| </code></pre></pre> |
| <p>Output:</p> |
| <pre><code class="language-txt">1 + 2 = 3 |
| (1 + 2) * (3 / 4) = 0 |
| </code></pre> |
| <p>This was a very simple example, but much more complex interfaces have been |
| developed, such as <a href="https://crates.io/crates/lazy_static"><code>lazy_static</code></a> or |
| <a href="https://crates.io/crates/clap"><code>clap</code></a>.</p> |
| <p>Also, note the two pairs of braces in the macro. The outer ones are |
| part of the syntax of <code>macro_rules!</code>, in addition to <code>()</code> or <code>[]</code>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="variadic-interfaces"><a class="header" href="#variadic-interfaces">Variadic Interfaces</a></h1> |
| <p>A <em>variadic</em> interface takes an arbitrary number of arguments. For example, |
| <code>println!</code> can take an arbitrary number of arguments, as determined by the |
| format string.</p> |
| <p>We can extend our <code>calculate!</code> macro from the previous section to be variadic:</p> |
| <pre><pre class="playground"><code class="language-rust editable">macro_rules! calculate { |
| // The pattern for a single `eval` |
| (eval $e:expr) => {{ |
| { |
| let val: usize = $e; // Force types to be integers |
| println!("{} = {}", stringify!{$e}, val); |
| } |
| }}; |
| |
| // Decompose multiple `eval`s recursively |
| (eval $e:expr, $(eval $es:expr),+) => {{ |
| calculate! { eval $e } |
| calculate! { $(eval $es),+ } |
| }}; |
| } |
| |
| fn main() { |
| calculate! { // Look ma! Variadic `calculate!`! |
| eval 1 + 2, |
| eval 3 + 4, |
| eval (2 * 3) + 1 |
| } |
| } |
| </code></pre></pre> |
| <p>Output:</p> |
| <pre><code class="language-txt">1 + 2 = 3 |
| 3 + 4 = 7 |
| (2 * 3) + 1 = 7 |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="error-handling"><a class="header" href="#error-handling">Error handling</a></h1> |
| <p>Error handling is the process of handling the possibility of failure. For |
| example, failing to read a file and then continuing to use that <em>bad</em> input |
| would clearly be problematic. Noticing and explicitly managing those errors |
| saves the rest of the program from various pitfalls.</p> |
| <p>There are various ways to deal with errors in Rust, which are described in the |
| following subchapters. They all have more or less subtle differences and different |
| use cases. As a rule of thumb:</p> |
| <p>An explicit <code>panic</code> is mainly useful for tests and dealing with unrecoverable errors. |
| For prototyping it can be useful, for example when dealing with functions that |
| haven't been implemented yet, but in those cases the more descriptive <code>unimplemented</code> |
| is better. In tests <code>panic</code> is a reasonable way to explicitly fail.</p> |
| <p>The <code>Option</code> type is for when a value is optional or when the lack of a value is |
| not an error condition. For example the parent of a directory - <code>/</code> and <code>C:</code> don't |
| have one. When dealing with <code>Option</code>s, <code>unwrap</code> is fine for prototyping and cases |
| where it's absolutely certain that there is guaranteed to be a value. However <code>expect</code> |
| is more useful since it lets you specify an error message in case something goes |
| wrong anyway.</p> |
| <p>When there is a chance that things do go wrong and the caller has to deal with the |
| problem, use <code>Result</code>. You can <code>unwrap</code> and <code>expect</code> them as well (please don't |
| do that unless it's a test or quick prototype).</p> |
| <p>For a more rigorous discussion of error handling, refer to the error |
| handling section in the <a href="https://doc.rust-lang.org/book/ch09-00-error-handling.html">official book</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="panic"><a class="header" href="#panic"><code>panic</code></a></h1> |
| <p>The simplest error handling mechanism we will see is <code>panic</code>. It prints an |
| error message, starts unwinding the stack, and usually exits the program. |
| Here, we explicitly call <code>panic</code> on our error condition:</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn drink(beverage: &str) { |
| // You shouldn't drink too much sugary beverages. |
| if beverage == "lemonade" { panic!("AAAaaaaa!!!!"); } |
| |
| println!("Some refreshing {} is all I need.", beverage); |
| } |
| |
| fn main() { |
| drink("water"); |
| drink("lemonade"); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="option--unwrap"><a class="header" href="#option--unwrap"><code>Option</code> & <code>unwrap</code></a></h1> |
| <p>In the last example, we showed that we can induce program failure at will. |
| We told our program to <code>panic</code> if we drink a sugary lemonade. |
| But what if we expect <em>some</em> drink but don't receive one? |
| That case would be just as bad, so it needs to be handled!</p> |
| <p>We <em>could</em> test this against the null string (<code>""</code>) as we do with a lemonade. |
| Since we're using Rust, let's instead have the compiler point out cases |
| where there's no drink.</p> |
| <p>An <code>enum</code> called <code>Option<T></code> in the <code>std</code> library is used when absence is a |
| possibility. It manifests itself as one of two "options":</p> |
| <ul> |
| <li><code>Some(T)</code>: An element of type <code>T</code> was found</li> |
| <li><code>None</code>: No element was found</li> |
| </ul> |
| <p>These cases can either be explicitly handled via <code>match</code> or implicitly with |
| <code>unwrap</code>. Implicit handling will either return the inner element or <code>panic</code>.</p> |
| <p>Note that it's possible to manually customize <code>panic</code> with <a href="https://doc.rust-lang.org/std/option/enum.Option.html#method.expect">expect</a>, |
| but <code>unwrap</code> otherwise leaves us with a less meaningful output than explicit |
| handling. In the following example, explicit handling yields a more |
| controlled result while retaining the option to <code>panic</code> if desired.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">// The adult has seen it all, and can handle any drink well. |
| // All drinks are handled explicitly using `match`. |
| fn give_adult(drink: Option<&str>) { |
| // Specify a course of action for each case. |
| match drink { |
| Some("lemonade") => println!("Yuck! Too sugary."), |
| Some(inner) => println!("{}? How nice.", inner), |
| None => println!("No drink? Oh well."), |
| } |
| } |
| |
| // Others will `panic` before drinking sugary drinks. |
| // All drinks are handled implicitly using `unwrap`. |
| fn drink(drink: Option<&str>) { |
| // `unwrap` returns a `panic` when it receives a `None`. |
| let inside = drink.unwrap(); |
| if inside == "lemonade" { panic!("AAAaaaaa!!!!"); } |
| |
| println!("I love {}s!!!!!", inside); |
| } |
| |
| fn main() { |
| let water = Some("water"); |
| let lemonade = Some("lemonade"); |
| let void = None; |
| |
| give_adult(water); |
| give_adult(lemonade); |
| give_adult(void); |
| |
| let coffee = Some("coffee"); |
| let nothing = None; |
| |
| drink(coffee); |
| drink(nothing); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="unpacking-options-with-"><a class="header" href="#unpacking-options-with-">Unpacking options with <code>?</code></a></h1> |
| <p>You can unpack <code>Option</code>s by using <code>match</code> statements, but it's often easier to |
| use the <code>?</code> operator. If <code>x</code> is an <code>Option</code>, then evaluating <code>x?</code> will return |
| the underlying value if <code>x</code> is <code>Some</code>, otherwise it will terminate whatever |
| function is being executed and return <code>None</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn next_birthday(current_age: Option<u8>) -> Option<String> { |
| // If `current_age` is `None`, this returns `None`. |
| // If `current_age` is `Some`, the inner `u8` gets assigned to `next_age` |
| let next_age: u8 = current_age?; |
| Some(format!("Next year I will be {}", next_age)) |
| } |
| </code></pre></pre> |
| <p>You can chain many <code>?</code>s together to make your code much more readable.</p> |
| <pre><pre class="playground"><code class="language-rust editable">struct Person { |
| job: Option<Job>, |
| } |
| |
| #[derive(Clone, Copy)] |
| struct Job { |
| phone_number: Option<PhoneNumber>, |
| } |
| |
| #[derive(Clone, Copy)] |
| struct PhoneNumber { |
| area_code: Option<u8>, |
| number: u32, |
| } |
| |
| impl Person { |
| |
| // Gets the area code of the phone number of the person's job, if it exists. |
| fn work_phone_area_code(&self) -> Option<u8> { |
| // This would need many nested `match` statements without the `?` operator. |
| // It would take a lot more code - try writing it yourself and see which |
| // is easier. |
| self.job?.phone_number?.area_code |
| } |
| } |
| |
| fn main() { |
| let p = Person { |
| job: Some(Job { |
| phone_number: Some(PhoneNumber { |
| area_code: Some(61), |
| number: 439222222, |
| }), |
| }), |
| }; |
| |
| assert_eq!(p.work_phone_area_code(), Some(61)); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="combinators-map"><a class="header" href="#combinators-map">Combinators: <code>map</code></a></h1> |
| <p><code>match</code> is a valid method for handling <code>Option</code>s. However, you may |
| eventually find heavy usage tedious, especially with operations only valid |
| with an input. In these cases, <a href="https://doc.rust-lang.org/reference/glossary.html#combinator">combinators</a> can be used to |
| manage control flow in a modular fashion.</p> |
| <p><code>Option</code> has a built in method called <code>map()</code>, a combinator for the simple |
| mapping of <code>Some -> Some</code> and <code>None -> None</code>. Multiple <code>map()</code> calls can be |
| chained together for even more flexibility.</p> |
| <p>In the following example, <code>process()</code> replaces all functions previous |
| to it while staying compact.</p> |
| <pre><pre class="playground"><code class="language-rust editable">#![allow(dead_code)] |
| |
| #[derive(Debug)] enum Food { Apple, Carrot, Potato } |
| |
| #[derive(Debug)] struct Peeled(Food); |
| #[derive(Debug)] struct Chopped(Food); |
| #[derive(Debug)] struct Cooked(Food); |
| |
| // Peeling food. If there isn't any, then return `None`. |
| // Otherwise, return the peeled food. |
| fn peel(food: Option<Food>) -> Option<Peeled> { |
| match food { |
| Some(food) => Some(Peeled(food)), |
| None => None, |
| } |
| } |
| |
| // Chopping food. If there isn't any, then return `None`. |
| // Otherwise, return the chopped food. |
| fn chop(peeled: Option<Peeled>) -> Option<Chopped> { |
| match peeled { |
| Some(Peeled(food)) => Some(Chopped(food)), |
| None => None, |
| } |
| } |
| |
| // Cooking food. Here, we showcase `map()` instead of `match` for case handling. |
| fn cook(chopped: Option<Chopped>) -> Option<Cooked> { |
| chopped.map(|Chopped(food)| Cooked(food)) |
| } |
| |
| // A function to peel, chop, and cook food all in sequence. |
| // We chain multiple uses of `map()` to simplify the code. |
| fn process(food: Option<Food>) -> Option<Cooked> { |
| food.map(|f| Peeled(f)) |
| .map(|Peeled(f)| Chopped(f)) |
| .map(|Chopped(f)| Cooked(f)) |
| } |
| |
| // Check whether there's food or not before trying to eat it! |
| fn eat(food: Option<Cooked>) { |
| match food { |
| Some(food) => println!("Mmm. I love {:?}", food), |
| None => println!("Oh no! It wasn't edible."), |
| } |
| } |
| |
| fn main() { |
| let apple = Some(Food::Apple); |
| let carrot = Some(Food::Carrot); |
| let potato = None; |
| |
| let cooked_apple = cook(chop(peel(apple))); |
| let cooked_carrot = cook(chop(peel(carrot))); |
| // Let's try the simpler looking `process()` now. |
| let cooked_potato = process(potato); |
| |
| eat(cooked_apple); |
| eat(cooked_carrot); |
| eat(cooked_potato); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-60"><a class="header" href="#see-also-60">See also:</a></h3> |
| <p><a href="error/option_unwrap/../../fn/closures.html">closures</a>, <a href="https://doc.rust-lang.org/std/option/enum.Option.html"><code>Option</code></a>, <a href="https://doc.rust-lang.org/std/option/enum.Option.html#method.map"><code>Option::map()</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="combinators-and_then"><a class="header" href="#combinators-and_then">Combinators: <code>and_then</code></a></h1> |
| <p><code>map()</code> was described as a chainable way to simplify <code>match</code> statements. |
| However, using <code>map()</code> on a function that returns an <code>Option<T></code> results |
| in the nested <code>Option<Option<T>></code>. Chaining multiple calls together can |
| then become confusing. That's where another combinator called <code>and_then()</code>, |
| known in some languages as flatmap, comes in.</p> |
| <p><code>and_then()</code> calls its function input with the wrapped value and returns the result. If the <code>Option</code> is <code>None</code>, then it returns <code>None</code> instead.</p> |
| <p>In the following example, <code>cookable_v2()</code> results in an <code>Option<Food></code>. |
| Using <code>map()</code> instead of <code>and_then()</code> would have given an |
| <code>Option<Option<Food>></code>, which is an invalid type for <code>eat()</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">#![allow(dead_code)] |
| |
| #[derive(Debug)] enum Food { CordonBleu, Steak, Sushi } |
| #[derive(Debug)] enum Day { Monday, Tuesday, Wednesday } |
| |
| // We don't have the ingredients to make Sushi. |
| fn have_ingredients(food: Food) -> Option<Food> { |
| match food { |
| Food::Sushi => None, |
| _ => Some(food), |
| } |
| } |
| |
| // We have the recipe for everything except Cordon Bleu. |
| fn have_recipe(food: Food) -> Option<Food> { |
| match food { |
| Food::CordonBleu => None, |
| _ => Some(food), |
| } |
| } |
| |
| // To make a dish, we need both the recipe and the ingredients. |
| // We can represent the logic with a chain of `match`es: |
| fn cookable_v1(food: Food) -> Option<Food> { |
| match have_recipe(food) { |
| None => None, |
| Some(food) => match have_ingredients(food) { |
| None => None, |
| Some(food) => Some(food), |
| }, |
| } |
| } |
| |
| // This can conveniently be rewritten more compactly with `and_then()`: |
| fn cookable_v2(food: Food) -> Option<Food> { |
| have_recipe(food).and_then(have_ingredients) |
| } |
| |
| fn eat(food: Food, day: Day) { |
| match cookable_v2(food) { |
| Some(food) => println!("Yay! On {:?} we get to eat {:?}.", day, food), |
| None => println!("Oh no. We don't get to eat on {:?}?", day), |
| } |
| } |
| |
| fn main() { |
| let (cordon_bleu, steak, sushi) = (Food::CordonBleu, Food::Steak, Food::Sushi); |
| |
| eat(cordon_bleu, Day::Monday); |
| eat(steak, Day::Tuesday); |
| eat(sushi, Day::Wednesday); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-61"><a class="header" href="#see-also-61">See also:</a></h3> |
| <p><a href="error/option_unwrap/../../fn/closures.html">closures</a>, <a href="https://doc.rust-lang.org/std/option/enum.Option.html"><code>Option</code></a>, and <a href="https://doc.rust-lang.org/std/option/enum.Option.html#method.and_then"><code>Option::and_then()</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="result"><a class="header" href="#result"><code>Result</code></a></h1> |
| <p><a href="https://doc.rust-lang.org/std/result/enum.Result.html"><code>Result</code></a> is a richer version of the <a href="https://doc.rust-lang.org/std/option/enum.Option.html"><code>Option</code></a> type that |
| describes possible <em>error</em> instead of possible <em>absence</em>.</p> |
| <p>That is, <code>Result<T, E></code> could have one of two outcomes:</p> |
| <ul> |
| <li><code>Ok(T)</code>: An element <code>T</code> was found</li> |
| <li><code>Err(E)</code>: An error was found with element <code>E</code></li> |
| </ul> |
| <p>By convention, the expected outcome is <code>Ok</code> while the unexpected outcome is <code>Err</code>.</p> |
| <p>Like <code>Option</code>, <code>Result</code> has many methods associated with it. <code>unwrap()</code>, for |
| example, either yields the element <code>T</code> or <code>panic</code>s. For case handling, |
| there are many combinators between <code>Result</code> and <code>Option</code> that overlap.</p> |
| <p>In working with Rust, you will likely encounter methods that return the |
| <code>Result</code> type, such as the <a href="https://doc.rust-lang.org/std/primitive.str.html#method.parse"><code>parse()</code></a> method. It might not always |
| be possible to parse a string into the other type, so <code>parse()</code> returns a |
| <code>Result</code> indicating possible failure.</p> |
| <p>Let's see what happens when we successfully and unsuccessfully <code>parse()</code> a string:</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn multiply(first_number_str: &str, second_number_str: &str) -> i32 { |
| // Let's try using `unwrap()` to get the number out. Will it bite us? |
| let first_number = first_number_str.parse::<i32>().unwrap(); |
| let second_number = second_number_str.parse::<i32>().unwrap(); |
| first_number * second_number |
| } |
| |
| fn main() { |
| let twenty = multiply("10", "2"); |
| println!("double is {}", twenty); |
| |
| let tt = multiply("t", "2"); |
| println!("double is {}", tt); |
| } |
| </code></pre></pre> |
| <p>In the unsuccessful case, <code>parse()</code> leaves us with an error for <code>unwrap()</code> |
| to <code>panic</code> on. Additionally, the <code>panic</code> exits our program and provides an |
| unpleasant error message.</p> |
| <p>To improve the quality of our error message, we should be more specific |
| about the return type and consider explicitly handling the error.</p> |
| <h2 id="using-result-in-main"><a class="header" href="#using-result-in-main">Using <code>Result</code> in <code>main</code></a></h2> |
| <p>The <code>Result</code> type can also be the return type of the <code>main</code> function if |
| specified explicitly. Typically the <code>main</code> function will be of the form:</p> |
| <pre><pre class="playground"><code class="language-rust">fn main() { |
| println!("Hello World!"); |
| } |
| </code></pre></pre> |
| <p>However <code>main</code> is also able to have a return type of <code>Result</code>. If an error |
| occurs within the <code>main</code> function it will return an error code and print a debug |
| representation of the error (using the <a href="https://doc.rust-lang.org/std/fmt/trait.Debug.html"><code>Debug</code></a> trait). The following example |
| shows such a scenario and touches on aspects covered in <a href="error/result/early_returns.html">the following section</a>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::num::ParseIntError; |
| |
| fn main() -> Result<(), ParseIntError> { |
| let number_str = "10"; |
| let number = match number_str.parse::<i32>() { |
| Ok(number) => number, |
| Err(e) => return Err(e), |
| }; |
| println!("{}", number); |
| Ok(()) |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="map-for-result"><a class="header" href="#map-for-result"><code>map</code> for <code>Result</code></a></h1> |
| <p>Panicking in the previous example's <code>multiply</code> does not make for robust code. |
| Generally, we want to return the error to the caller so it can decide what is |
| the right way to respond to errors.</p> |
| <p>We first need to know what kind of error type we are dealing with. To determine |
| the <code>Err</code> type, we look to <a href="https://doc.rust-lang.org/std/primitive.str.html#method.parse"><code>parse()</code></a>, which is implemented with the |
| <a href="https://doc.rust-lang.org/std/str/trait.FromStr.html"><code>FromStr</code></a> trait for <a href="https://doc.rust-lang.org/std/primitive.i32.html"><code>i32</code></a>. As a result, the <code>Err</code> type is |
| specified as <a href="https://doc.rust-lang.org/std/num/struct.ParseIntError.html"><code>ParseIntError</code></a>.</p> |
| <p>In the example below, the straightforward <code>match</code> statement leads to code |
| that is overall more cumbersome.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::num::ParseIntError; |
| |
| // With the return type rewritten, we use pattern matching without `unwrap()`. |
| fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { |
| match first_number_str.parse::<i32>() { |
| Ok(first_number) => { |
| match second_number_str.parse::<i32>() { |
| Ok(second_number) => { |
| Ok(first_number * second_number) |
| }, |
| Err(e) => Err(e), |
| } |
| }, |
| Err(e) => Err(e), |
| } |
| } |
| |
| fn print(result: Result<i32, ParseIntError>) { |
| match result { |
| Ok(n) => println!("n is {}", n), |
| Err(e) => println!("Error: {}", e), |
| } |
| } |
| |
| fn main() { |
| // This still presents a reasonable answer. |
| let twenty = multiply("10", "2"); |
| print(twenty); |
| |
| // The following now provides a much more helpful error message. |
| let tt = multiply("t", "2"); |
| print(tt); |
| } |
| </code></pre></pre> |
| <p>Luckily, <code>Option</code>'s <code>map</code>, <code>and_then</code>, and many other combinators are also |
| implemented for <code>Result</code>. <a href="https://doc.rust-lang.org/std/result/enum.Result.html"><code>Result</code></a> contains a complete listing.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::num::ParseIntError; |
| |
| // As with `Option`, we can use combinators such as `map()`. |
| // This function is otherwise identical to the one above and reads: |
| // Modify n if the value is valid, otherwise pass on the error. |
| fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { |
| first_number_str.parse::<i32>().and_then(|first_number| { |
| second_number_str.parse::<i32>().map(|second_number| first_number * second_number) |
| }) |
| } |
| |
| fn print(result: Result<i32, ParseIntError>) { |
| match result { |
| Ok(n) => println!("n is {}", n), |
| Err(e) => println!("Error: {}", e), |
| } |
| } |
| |
| fn main() { |
| // This still presents a reasonable answer. |
| let twenty = multiply("10", "2"); |
| print(twenty); |
| |
| // The following now provides a much more helpful error message. |
| let tt = multiply("t", "2"); |
| print(tt); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="aliases-for-result"><a class="header" href="#aliases-for-result">aliases for <code>Result</code></a></h1> |
| <p>How about when we want to reuse a specific <code>Result</code> type many times? |
| Recall that Rust allows us to create <a href="error/result/../../types/alias.html">aliases</a>. Conveniently, |
| we can define one for the specific <code>Result</code> in question.</p> |
| <p>At a module level, creating aliases can be particularly helpful. Errors |
| found in a specific module often have the same <code>Err</code> type, so a single alias |
| can succinctly define <em>all</em> associated <code>Results</code>. This is so useful that the |
| <code>std</code> library even supplies one: <a href="https://doc.rust-lang.org/std/io/type.Result.html"><code>io::Result</code></a>!</p> |
| <p>Here's a quick example to show off the syntax:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::num::ParseIntError; |
| |
| // Define a generic alias for a `Result` with the error type `ParseIntError`. |
| type AliasedResult<T> = Result<T, ParseIntError>; |
| |
| // Use the above alias to refer to our specific `Result` type. |
| fn multiply(first_number_str: &str, second_number_str: &str) -> AliasedResult<i32> { |
| first_number_str.parse::<i32>().and_then(|first_number| { |
| second_number_str.parse::<i32>().map(|second_number| first_number * second_number) |
| }) |
| } |
| |
| // Here, the alias again allows us to save some space. |
| fn print(result: AliasedResult<i32>) { |
| match result { |
| Ok(n) => println!("n is {}", n), |
| Err(e) => println!("Error: {}", e), |
| } |
| } |
| |
| fn main() { |
| print(multiply("10", "2")); |
| print(multiply("t", "2")); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-62"><a class="header" href="#see-also-62">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/io/type.Result.html"><code>io::Result</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="early-returns"><a class="header" href="#early-returns">Early returns</a></h1> |
| <p>In the previous example, we explicitly handled the errors using combinators. |
| Another way to deal with this case analysis is to use a combination of |
| <code>match</code> statements and <em>early returns</em>.</p> |
| <p>That is, we can simply stop executing the function and return the error if |
| one occurs. For some, this form of code can be easier to both read and |
| write. Consider this version of the previous example, rewritten using early returns:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::num::ParseIntError; |
| |
| fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { |
| let first_number = match first_number_str.parse::<i32>() { |
| Ok(first_number) => first_number, |
| Err(e) => return Err(e), |
| }; |
| |
| let second_number = match second_number_str.parse::<i32>() { |
| Ok(second_number) => second_number, |
| Err(e) => return Err(e), |
| }; |
| |
| Ok(first_number * second_number) |
| } |
| |
| fn print(result: Result<i32, ParseIntError>) { |
| match result { |
| Ok(n) => println!("n is {}", n), |
| Err(e) => println!("Error: {}", e), |
| } |
| } |
| |
| fn main() { |
| print(multiply("10", "2")); |
| print(multiply("t", "2")); |
| } |
| </code></pre></pre> |
| <p>At this point, we've learned to explicitly handle errors using combinators |
| and early returns. While we generally want to avoid panicking, explicitly |
| handling all of our errors is cumbersome.</p> |
| <p>In the next section, we'll introduce <code>?</code> for the cases where we simply |
| need to <code>unwrap</code> without possibly inducing <code>panic</code>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="introducing-"><a class="header" href="#introducing-">Introducing <code>?</code></a></h1> |
| <p>Sometimes we just want the simplicity of <code>unwrap</code> without the possibility of |
| a <code>panic</code>. Until now, <code>unwrap</code> has forced us to nest deeper and deeper when |
| what we really wanted was to get the variable <em>out</em>. This is exactly the purpose of <code>?</code>.</p> |
| <p>Upon finding an <code>Err</code>, there are two valid actions to take:</p> |
| <ol> |
| <li><code>panic!</code> which we already decided to try to avoid if possible</li> |
| <li><code>return</code> because an <code>Err</code> means it cannot be handled</li> |
| </ol> |
| <p><code>?</code> is <em>almost</em><sup class="footnote-reference"><a href="#†">1</a></sup> exactly equivalent to an <code>unwrap</code> which <code>return</code>s |
| instead of <code>panic</code>king on <code>Err</code>s. Let's see how we can simplify the earlier |
| example that used combinators:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::num::ParseIntError; |
| |
| fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { |
| let first_number = first_number_str.parse::<i32>()?; |
| let second_number = second_number_str.parse::<i32>()?; |
| |
| Ok(first_number * second_number) |
| } |
| |
| fn print(result: Result<i32, ParseIntError>) { |
| match result { |
| Ok(n) => println!("n is {}", n), |
| Err(e) => println!("Error: {}", e), |
| } |
| } |
| |
| fn main() { |
| print(multiply("10", "2")); |
| print(multiply("t", "2")); |
| } |
| </code></pre></pre> |
| <h2 id="the-try-macro"><a class="header" href="#the-try-macro">The <code>try!</code> macro</a></h2> |
| <p>Before there was <code>?</code>, the same functionality was achieved with the <code>try!</code> macro. |
| The <code>?</code> operator is now recommended, but you may still find <code>try!</code> when looking |
| at older code. The same <code>multiply</code> function from the previous example |
| would look like this using <code>try!</code>:</p> |
| <pre><pre class="playground"><code class="language-rust editable">// To compile and run this example without errors, while using Cargo, change the value |
| // of the `edition` field, in the `[package]` section of the `Cargo.toml` file, to "2015". |
| |
| use std::num::ParseIntError; |
| |
| fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { |
| let first_number = try!(first_number_str.parse::<i32>()); |
| let second_number = try!(second_number_str.parse::<i32>()); |
| |
| Ok(first_number * second_number) |
| } |
| |
| fn print(result: Result<i32, ParseIntError>) { |
| match result { |
| Ok(n) => println!("n is {}", n), |
| Err(e) => println!("Error: {}", e), |
| } |
| } |
| |
| fn main() { |
| print(multiply("10", "2")); |
| print(multiply("t", "2")); |
| } |
| </code></pre></pre> |
| <div class="footnote-definition" id="†"><sup class="footnote-definition-label">1</sup> |
| <p>See <a href="error/result/../multiple_error_types/reenter_question_mark.html">re-enter ?</a> for more details.</p> |
| </div> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="multiple-error-types"><a class="header" href="#multiple-error-types">Multiple error types</a></h1> |
| <p>The previous examples have always been very convenient; <code>Result</code>s interact |
| with other <code>Result</code>s and <code>Option</code>s interact with other <code>Option</code>s.</p> |
| <p>Sometimes an <code>Option</code> needs to interact with a <code>Result</code>, or a |
| <code>Result<T, Error1></code> needs to interact with a <code>Result<T, Error2></code>. In those |
| cases, we want to manage our different error types in a way that makes them |
| composable and easy to interact with.</p> |
| <p>In the following code, two instances of <code>unwrap</code> generate different error |
| types. <code>Vec::first</code> returns an <code>Option</code>, while <code>parse::<i32></code> returns a |
| <code>Result<i32, ParseIntError></code>:</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn double_first(vec: Vec<&str>) -> i32 { |
| let first = vec.first().unwrap(); // Generate error 1 |
| 2 * first.parse::<i32>().unwrap() // Generate error 2 |
| } |
| |
| fn main() { |
| let numbers = vec!["42", "93", "18"]; |
| let empty = vec![]; |
| let strings = vec!["tofu", "93", "18"]; |
| |
| println!("The first doubled is {}", double_first(numbers)); |
| |
| println!("The first doubled is {}", double_first(empty)); |
| // Error 1: the input vector is empty |
| |
| println!("The first doubled is {}", double_first(strings)); |
| // Error 2: the element doesn't parse to a number |
| } |
| </code></pre></pre> |
| <p>Over the next sections, we'll see several strategies for handling these kind of problems.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="pulling-results-out-of-options"><a class="header" href="#pulling-results-out-of-options">Pulling <code>Result</code>s out of <code>Option</code>s</a></h1> |
| <p>The most basic way of handling mixed error types is to just embed them in each |
| other.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::num::ParseIntError; |
| |
| fn double_first(vec: Vec<&str>) -> Option<Result<i32, ParseIntError>> { |
| vec.first().map(|first| { |
| first.parse::<i32>().map(|n| 2 * n) |
| }) |
| } |
| |
| fn main() { |
| let numbers = vec!["42", "93", "18"]; |
| let empty = vec![]; |
| let strings = vec!["tofu", "93", "18"]; |
| |
| println!("The first doubled is {:?}", double_first(numbers)); |
| |
| println!("The first doubled is {:?}", double_first(empty)); |
| // Error 1: the input vector is empty |
| |
| println!("The first doubled is {:?}", double_first(strings)); |
| // Error 2: the element doesn't parse to a number |
| } |
| </code></pre></pre> |
| <p>There are times when we'll want to stop processing on errors (like with |
| <a href="error/multiple_error_types/../result/enter_question_mark.html"><code>?</code></a>) but keep going when the <code>Option</code> is <code>None</code>. A |
| couple of combinators come in handy to swap the <code>Result</code> and <code>Option</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::num::ParseIntError; |
| |
| fn double_first(vec: Vec<&str>) -> Result<Option<i32>, ParseIntError> { |
| let opt = vec.first().map(|first| { |
| first.parse::<i32>().map(|n| 2 * n) |
| }); |
| |
| opt.map_or(Ok(None), |r| r.map(Some)) |
| } |
| |
| fn main() { |
| let numbers = vec!["42", "93", "18"]; |
| let empty = vec![]; |
| let strings = vec!["tofu", "93", "18"]; |
| |
| println!("The first doubled is {:?}", double_first(numbers)); |
| println!("The first doubled is {:?}", double_first(empty)); |
| println!("The first doubled is {:?}", double_first(strings)); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="defining-an-error-type"><a class="header" href="#defining-an-error-type">Defining an error type</a></h1> |
| <p>Sometimes it simplifies the code to mask all of the different errors with a |
| single type of error. We'll show this with a custom error.</p> |
| <p>Rust allows us to define our own error types. In general, a "good" error type:</p> |
| <ul> |
| <li>Represents different errors with the same type</li> |
| <li>Presents nice error messages to the user</li> |
| <li>Is easy to compare with other types |
| <ul> |
| <li>Good: <code>Err(EmptyVec)</code></li> |
| <li>Bad: <code>Err("Please use a vector with at least one element".to_owned())</code></li> |
| </ul> |
| </li> |
| <li>Can hold information about the error |
| <ul> |
| <li>Good: <code>Err(BadChar(c, position))</code></li> |
| <li>Bad: <code>Err("+ cannot be used here".to_owned())</code></li> |
| </ul> |
| </li> |
| <li>Composes well with other errors</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable">use std::fmt; |
| |
| type Result<T> = std::result::Result<T, DoubleError>; |
| |
| // Define our error types. These may be customized for our error handling cases. |
| // Now we will be able to write our own errors, defer to an underlying error |
| // implementation, or do something in between. |
| #[derive(Debug, Clone)] |
| struct DoubleError; |
| |
| // Generation of an error is completely separate from how it is displayed. |
| // There's no need to be concerned about cluttering complex logic with the display style. |
| // |
| // Note that we don't store any extra info about the errors. This means we can't state |
| // which string failed to parse without modifying our types to carry that information. |
| impl fmt::Display for DoubleError { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| write!(f, "invalid first item to double") |
| } |
| } |
| |
| fn double_first(vec: Vec<&str>) -> Result<i32> { |
| vec.first() |
| // Change the error to our new type. |
| .ok_or(DoubleError) |
| .and_then(|s| { |
| s.parse::<i32>() |
| // Update to the new error type here also. |
| .map_err(|_| DoubleError) |
| .map(|i| 2 * i) |
| }) |
| } |
| |
| fn print(result: Result<i32>) { |
| match result { |
| Ok(n) => println!("The first doubled is {}", n), |
| Err(e) => println!("Error: {}", e), |
| } |
| } |
| |
| fn main() { |
| let numbers = vec!["42", "93", "18"]; |
| let empty = vec![]; |
| let strings = vec!["tofu", "93", "18"]; |
| |
| print(double_first(numbers)); |
| print(double_first(empty)); |
| print(double_first(strings)); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="boxing-errors"><a class="header" href="#boxing-errors"><code>Box</code>ing errors</a></h1> |
| <p>A way to write simple code while preserving the original errors is to <a href="https://doc.rust-lang.org/std/boxed/struct.Box.html"><code>Box</code></a> |
| them. The drawback is that the underlying error type is only known at runtime and not |
| <a href="https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch">statically determined</a>.</p> |
| <p>The stdlib helps in boxing our errors by having <code>Box</code> implement conversion from |
| any type that implements the <code>Error</code> trait into the trait object <code>Box<Error></code>, |
| via <a href="https://doc.rust-lang.org/std/convert/trait.From.html"><code>From</code></a>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::error; |
| use std::fmt; |
| |
| // Change the alias to `Box<error::Error>`. |
| type Result<T> = std::result::Result<T, Box<dyn error::Error>>; |
| |
| #[derive(Debug, Clone)] |
| struct EmptyVec; |
| |
| impl fmt::Display for EmptyVec { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| write!(f, "invalid first item to double") |
| } |
| } |
| |
| impl error::Error for EmptyVec {} |
| |
| fn double_first(vec: Vec<&str>) -> Result<i32> { |
| vec.first() |
| .ok_or_else(|| EmptyVec.into()) // Converts to Box |
| .and_then(|s| { |
| s.parse::<i32>() |
| .map_err(|e| e.into()) // Converts to Box |
| .map(|i| 2 * i) |
| }) |
| } |
| |
| fn print(result: Result<i32>) { |
| match result { |
| Ok(n) => println!("The first doubled is {}", n), |
| Err(e) => println!("Error: {}", e), |
| } |
| } |
| |
| fn main() { |
| let numbers = vec!["42", "93", "18"]; |
| let empty = vec![]; |
| let strings = vec!["tofu", "93", "18"]; |
| |
| print(double_first(numbers)); |
| print(double_first(empty)); |
| print(double_first(strings)); |
| } |
| </code></pre></pre> |
| <h3 id="see-also-63"><a class="header" href="#see-also-63">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch">Dynamic dispatch</a> and <a href="https://doc.rust-lang.org/std/error/trait.Error.html"><code>Error</code> trait</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="other-uses-of-"><a class="header" href="#other-uses-of-">Other uses of <code>?</code></a></h1> |
| <p>Notice in the previous example that our immediate reaction to calling |
| <code>parse</code> is to <code>map</code> the error from a library error into a boxed |
| error:</p> |
| <pre><code class="language-rust ignore">.and_then(|s| s.parse::<i32>() |
| .map_err(|e| e.into()) |
| </code></pre> |
| <p>Since this is a simple and common operation, it would be convenient if it |
| could be elided. Alas, because <code>and_then</code> is not sufficiently flexible, it |
| cannot. However, we can instead use <code>?</code>.</p> |
| <p><code>?</code> was previously explained as either <code>unwrap</code> or <code>return Err(err)</code>. |
| This is only mostly true. It actually means <code>unwrap</code> or |
| <code>return Err(From::from(err))</code>. Since <code>From::from</code> is a conversion utility |
| between different types, this means that if you <code>?</code> where the error is |
| convertible to the return type, it will convert automatically.</p> |
| <p>Here, we rewrite the previous example using <code>?</code>. As a result, the |
| <code>map_err</code> will go away when <code>From::from</code> is implemented for our error type:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::error; |
| use std::fmt; |
| |
| // Change the alias to `Box<dyn error::Error>`. |
| type Result<T> = std::result::Result<T, Box<dyn error::Error>>; |
| |
| #[derive(Debug)] |
| struct EmptyVec; |
| |
| impl fmt::Display for EmptyVec { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| write!(f, "invalid first item to double") |
| } |
| } |
| |
| impl error::Error for EmptyVec {} |
| |
| // The same structure as before but rather than chain all `Results` |
| // and `Options` along, we `?` to get the inner value out immediately. |
| fn double_first(vec: Vec<&str>) -> Result<i32> { |
| let first = vec.first().ok_or(EmptyVec)?; |
| let parsed = first.parse::<i32>()?; |
| Ok(2 * parsed) |
| } |
| |
| fn print(result: Result<i32>) { |
| match result { |
| Ok(n) => println!("The first doubled is {}", n), |
| Err(e) => println!("Error: {}", e), |
| } |
| } |
| |
| fn main() { |
| let numbers = vec!["42", "93", "18"]; |
| let empty = vec![]; |
| let strings = vec!["tofu", "93", "18"]; |
| |
| print(double_first(numbers)); |
| print(double_first(empty)); |
| print(double_first(strings)); |
| } |
| </code></pre></pre> |
| <p>This is actually fairly clean now. Compared with the original <code>panic</code>, it |
| is very similar to replacing the <code>unwrap</code> calls with <code>?</code> except that the |
| return types are <code>Result</code>. As a result, they must be destructured at the |
| top level.</p> |
| <h3 id="see-also-64"><a class="header" href="#see-also-64">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/convert/trait.From.html"><code>From::from</code></a> and <a href="https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator"><code>?</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="wrapping-errors"><a class="header" href="#wrapping-errors">Wrapping errors</a></h1> |
| <p>An alternative to boxing errors is to wrap them in your own error type.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::error; |
| use std::error::Error as _; |
| use std::num::ParseIntError; |
| use std::fmt; |
| |
| type Result<T> = std::result::Result<T, DoubleError>; |
| |
| #[derive(Debug)] |
| enum DoubleError { |
| EmptyVec, |
| // We will defer to the parse error implementation for their error. |
| // Supplying extra info requires adding more data to the type. |
| Parse(ParseIntError), |
| } |
| |
| impl fmt::Display for DoubleError { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| match *self { |
| DoubleError::EmptyVec => |
| write!(f, "please use a vector with at least one element"), |
| // The wrapped error contains additional information and is available |
| // via the source() method. |
| DoubleError::Parse(..) => |
| write!(f, "the provided string could not be parsed as int"), |
| } |
| } |
| } |
| |
| impl error::Error for DoubleError { |
| fn source(&self) -> Option<&(dyn error::Error + 'static)> { |
| match *self { |
| DoubleError::EmptyVec => None, |
| // The cause is the underlying implementation error type. Is implicitly |
| // cast to the trait object `&error::Error`. This works because the |
| // underlying type already implements the `Error` trait. |
| DoubleError::Parse(ref e) => Some(e), |
| } |
| } |
| } |
| |
| // Implement the conversion from `ParseIntError` to `DoubleError`. |
| // This will be automatically called by `?` if a `ParseIntError` |
| // needs to be converted into a `DoubleError`. |
| impl From<ParseIntError> for DoubleError { |
| fn from(err: ParseIntError) -> DoubleError { |
| DoubleError::Parse(err) |
| } |
| } |
| |
| fn double_first(vec: Vec<&str>) -> Result<i32> { |
| let first = vec.first().ok_or(DoubleError::EmptyVec)?; |
| // Here we implicitly use the `ParseIntError` implementation of `From` (which |
| // we defined above) in order to create a `DoubleError`. |
| let parsed = first.parse::<i32>()?; |
| |
| Ok(2 * parsed) |
| } |
| |
| fn print(result: Result<i32>) { |
| match result { |
| Ok(n) => println!("The first doubled is {}", n), |
| Err(e) => { |
| println!("Error: {}", e); |
| if let Some(source) = e.source() { |
| println!(" Caused by: {}", source); |
| } |
| }, |
| } |
| } |
| |
| fn main() { |
| let numbers = vec!["42", "93", "18"]; |
| let empty = vec![]; |
| let strings = vec!["tofu", "93", "18"]; |
| |
| print(double_first(numbers)); |
| print(double_first(empty)); |
| print(double_first(strings)); |
| } |
| </code></pre></pre> |
| <p>This adds a bit more boilerplate for handling errors and might not be needed in |
| all applications. There are some libraries that can take care of the boilerplate |
| for you.</p> |
| <h3 id="see-also-65"><a class="header" href="#see-also-65">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/convert/trait.From.html"><code>From::from</code></a> and <a href="error/multiple_error_types/../../custom_types/enum.html"><code>Enums</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="iterating-over-results"><a class="header" href="#iterating-over-results">Iterating over <code>Result</code>s</a></h1> |
| <p>An <code>Iter::map</code> operation might fail, for example:</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let strings = vec!["tofu", "93", "18"]; |
| let numbers: Vec<_> = strings |
| .into_iter() |
| .map(|s| s.parse::<i32>()) |
| .collect(); |
| println!("Results: {:?}", numbers); |
| } |
| </code></pre></pre> |
| <p>Let's step through strategies for handling this.</p> |
| <h2 id="ignore-the-failed-items-with-filter_map"><a class="header" href="#ignore-the-failed-items-with-filter_map">Ignore the failed items with <code>filter_map()</code></a></h2> |
| <p><code>filter_map</code> calls a function and filters out the results that are <code>None</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let strings = vec!["tofu", "93", "18"]; |
| let numbers: Vec<_> = strings |
| .into_iter() |
| .filter_map(|s| s.parse::<i32>().ok()) |
| .collect(); |
| println!("Results: {:?}", numbers); |
| } |
| </code></pre></pre> |
| <h2 id="fail-the-entire-operation-with-collect"><a class="header" href="#fail-the-entire-operation-with-collect">Fail the entire operation with <code>collect()</code></a></h2> |
| <p><code>Result</code> implements <code>FromIter</code> so that a vector of results (<code>Vec<Result<T, E>></code>) |
| can be turned into a result with a vector (<code>Result<Vec<T>, E></code>). Once an |
| <code>Result::Err</code> is found, the iteration will terminate.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let strings = vec!["tofu", "93", "18"]; |
| let numbers: Result<Vec<_>, _> = strings |
| .into_iter() |
| .map(|s| s.parse::<i32>()) |
| .collect(); |
| println!("Results: {:?}", numbers); |
| } |
| </code></pre></pre> |
| <p>This same technique can be used with <code>Option</code>.</p> |
| <h2 id="collect-all-valid-values-and-failures-with-partition"><a class="header" href="#collect-all-valid-values-and-failures-with-partition">Collect all valid values and failures with <code>partition()</code></a></h2> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let strings = vec!["tofu", "93", "18"]; |
| let (numbers, errors): (Vec<_>, Vec<_>) = strings |
| .into_iter() |
| .map(|s| s.parse::<i32>()) |
| .partition(Result::is_ok); |
| println!("Numbers: {:?}", numbers); |
| println!("Errors: {:?}", errors); |
| } |
| </code></pre></pre> |
| <p>When you look at the results, you'll note that everything is still wrapped in |
| <code>Result</code>. A little more boilerplate is needed for this.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let strings = vec!["tofu", "93", "18"]; |
| let (numbers, errors): (Vec<_>, Vec<_>) = strings |
| .into_iter() |
| .map(|s| s.parse::<i32>()) |
| .partition(Result::is_ok); |
| let numbers: Vec<_> = numbers.into_iter().map(Result::unwrap).collect(); |
| let errors: Vec<_> = errors.into_iter().map(Result::unwrap_err).collect(); |
| println!("Numbers: {:?}", numbers); |
| println!("Errors: {:?}", errors); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="std-library-types"><a class="header" href="#std-library-types">Std library types</a></h1> |
| <p>The <code>std</code> library provides many custom types which expands drastically on |
| the <code>primitives</code>. Some of these include:</p> |
| <ul> |
| <li>growable <code>String</code>s like: <code>"hello world"</code></li> |
| <li>growable vectors: <code>[1, 2, 3]</code></li> |
| <li>optional types: <code>Option<i32></code></li> |
| <li>error handling types: <code>Result<i32, i32></code></li> |
| <li>heap allocated pointers: <code>Box<i32></code></li> |
| </ul> |
| <h3 id="see-also-66"><a class="header" href="#see-also-66">See also:</a></h3> |
| <p><a href="primitives.html">primitives</a> and <a href="https://doc.rust-lang.org/std/">the std library</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="box-stack-and-heap"><a class="header" href="#box-stack-and-heap">Box, stack and heap</a></h1> |
| <p>All values in Rust are stack allocated by default. Values can be <em>boxed</em> |
| (allocated on the heap) by creating a <code>Box<T></code>. A box is a smart pointer to a |
| heap allocated value of type <code>T</code>. When a box goes out of scope, its destructor |
| is called, the inner object is destroyed, and the memory on the heap is freed.</p> |
| <p>Boxed values can be dereferenced using the <code>*</code> operator; this removes one layer |
| of indirection. </p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::mem; |
| |
| #[allow(dead_code)] |
| #[derive(Debug, Clone, Copy)] |
| struct Point { |
| x: f64, |
| y: f64, |
| } |
| |
| // A Rectangle can be specified by where its top left and bottom right |
| // corners are in space |
| #[allow(dead_code)] |
| struct Rectangle { |
| top_left: Point, |
| bottom_right: Point, |
| } |
| |
| fn origin() -> Point { |
| Point { x: 0.0, y: 0.0 } |
| } |
| |
| fn boxed_origin() -> Box<Point> { |
| // Allocate this point on the heap, and return a pointer to it |
| Box::new(Point { x: 0.0, y: 0.0 }) |
| } |
| |
| fn main() { |
| // (all the type annotations are superfluous) |
| // Stack allocated variables |
| let point: Point = origin(); |
| let rectangle: Rectangle = Rectangle { |
| top_left: origin(), |
| bottom_right: Point { x: 3.0, y: -4.0 } |
| }; |
| |
| // Heap allocated rectangle |
| let boxed_rectangle: Box<Rectangle> = Box::new(Rectangle { |
| top_left: origin(), |
| bottom_right: Point { x: 3.0, y: -4.0 }, |
| }); |
| |
| // The output of functions can be boxed |
| let boxed_point: Box<Point> = Box::new(origin()); |
| |
| // Double indirection |
| let box_in_a_box: Box<Box<Point>> = Box::new(boxed_origin()); |
| |
| println!("Point occupies {} bytes on the stack", |
| mem::size_of_val(&point)); |
| println!("Rectangle occupies {} bytes on the stack", |
| mem::size_of_val(&rectangle)); |
| |
| // box size == pointer size |
| println!("Boxed point occupies {} bytes on the stack", |
| mem::size_of_val(&boxed_point)); |
| println!("Boxed rectangle occupies {} bytes on the stack", |
| mem::size_of_val(&boxed_rectangle)); |
| println!("Boxed box occupies {} bytes on the stack", |
| mem::size_of_val(&box_in_a_box)); |
| |
| // Copy the data contained in `boxed_point` into `unboxed_point` |
| let unboxed_point: Point = *boxed_point; |
| println!("Unboxed point occupies {} bytes on the stack", |
| mem::size_of_val(&unboxed_point)); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="vectors"><a class="header" href="#vectors">Vectors</a></h1> |
| <p>Vectors are re-sizable arrays. Like slices, their size is not known at compile |
| time, but they can grow or shrink at any time. A vector is represented using |
| 3 parameters: </p> |
| <ul> |
| <li>pointer to the data</li> |
| <li>length</li> |
| <li>capacity </li> |
| </ul> |
| <p>The capacity indicates how much memory is reserved for the vector. The vector |
| can grow as long as the length is smaller than the capacity. When this threshold |
| needs to be surpassed, the vector is reallocated with a larger capacity.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">fn main() { |
| // Iterators can be collected into vectors |
| let collected_iterator: Vec<i32> = (0..10).collect(); |
| println!("Collected (0..10) into: {:?}", collected_iterator); |
| |
| // The `vec!` macro can be used to initialize a vector |
| let mut xs = vec![1i32, 2, 3]; |
| println!("Initial vector: {:?}", xs); |
| |
| // Insert new element at the end of the vector |
| println!("Push 4 into the vector"); |
| xs.push(4); |
| println!("Vector: {:?}", xs); |
| |
| // Error! Immutable vectors can't grow |
| collected_iterator.push(0); |
| // FIXME ^ Comment out this line |
| |
| // The `len` method yields the number of elements currently stored in a vector |
| println!("Vector length: {}", xs.len()); |
| |
| // Indexing is done using the square brackets (indexing starts at 0) |
| println!("Second element: {}", xs[1]); |
| |
| // `pop` removes the last element from the vector and returns it |
| println!("Pop last element: {:?}", xs.pop()); |
| |
| // Out of bounds indexing yields a panic |
| println!("Fourth element: {}", xs[3]); |
| // FIXME ^ Comment out this line |
| |
| // `Vector`s can be easily iterated over |
| println!("Contents of xs:"); |
| for x in xs.iter() { |
| println!("> {}", x); |
| } |
| |
| // A `Vector` can also be iterated over while the iteration |
| // count is enumerated in a separate variable (`i`) |
| for (i, x) in xs.iter().enumerate() { |
| println!("In position {} we have value {}", i, x); |
| } |
| |
| // Thanks to `iter_mut`, mutable `Vector`s can also be iterated |
| // over in a way that allows modifying each value |
| for x in xs.iter_mut() { |
| *x *= 3; |
| } |
| println!("Updated vector: {:?}", xs); |
| } |
| </code></pre></pre> |
| <p>More <code>Vec</code> methods can be found under the |
| <a href="https://doc.rust-lang.org/std/vec/">std::vec</a> module</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="strings"><a class="header" href="#strings">Strings</a></h1> |
| <p>There are two types of strings in Rust: <code>String</code> and <code>&str</code>.</p> |
| <p>A <code>String</code> is stored as a vector of bytes (<code>Vec<u8></code>), but guaranteed to |
| always be a valid UTF-8 sequence. <code>String</code> is heap allocated, growable and not |
| null terminated.</p> |
| <p><code>&str</code> is a slice (<code>&[u8]</code>) that always points to a valid UTF-8 sequence, and |
| can be used to view into a <code>String</code>, just like <code>&[T]</code> is a view into <code>Vec<T></code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // (all the type annotations are superfluous) |
| // A reference to a string allocated in read only memory |
| let pangram: &'static str = "the quick brown fox jumps over the lazy dog"; |
| println!("Pangram: {}", pangram); |
| |
| // Iterate over words in reverse, no new string is allocated |
| println!("Words in reverse"); |
| for word in pangram.split_whitespace().rev() { |
| println!("> {}", word); |
| } |
| |
| // Copy chars into a vector, sort and remove duplicates |
| let mut chars: Vec<char> = pangram.chars().collect(); |
| chars.sort(); |
| chars.dedup(); |
| |
| // Create an empty and growable `String` |
| let mut string = String::new(); |
| for c in chars { |
| // Insert a char at the end of string |
| string.push(c); |
| // Insert a string at the end of string |
| string.push_str(", "); |
| } |
| |
| // The trimmed string is a slice to the original string, hence no new |
| // allocation is performed |
| let chars_to_trim: &[char] = &[' ', ',']; |
| let trimmed_str: &str = string.trim_matches(chars_to_trim); |
| println!("Used characters: {}", trimmed_str); |
| |
| // Heap allocate a string |
| let alice = String::from("I like dogs"); |
| // Allocate new memory and store the modified string there |
| let bob: String = alice.replace("dog", "cat"); |
| |
| println!("Alice says: {}", alice); |
| println!("Bob says: {}", bob); |
| } |
| </code></pre></pre> |
| <p>More <code>str</code>/<code>String</code> methods can be found under the |
| <a href="https://doc.rust-lang.org/std/str/">std::str</a> and |
| <a href="https://doc.rust-lang.org/std/string/">std::string</a> |
| modules</p> |
| <h2 id="literals-and-escapes"><a class="header" href="#literals-and-escapes">Literals and escapes</a></h2> |
| <p>There are multiple ways to write string literals with special characters in them. |
| All result in a similar <code>&str</code> so it's best to use the form that is the most |
| convenient to write. Similarly there are multiple ways to write byte string literals, |
| which all result in <code>&[u8; N]</code>.</p> |
| <p>Generally special characters are escaped with a backslash character: <code>\</code>. |
| This way you can add any character to your string, even unprintable ones |
| and ones that you don't know how to type. If you want a literal backslash, |
| escape it with another one: <code>\\</code></p> |
| <p>String or character literal delimiters occuring within a literal must be escaped: <code>"\""</code>, <code>'\''</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| // You can use escapes to write bytes by their hexadecimal values... |
| let byte_escape = "I'm writing \x52\x75\x73\x74!"; |
| println!("What are you doing\x3F (\\x3F means ?) {}", byte_escape); |
| |
| // ...or Unicode code points. |
| let unicode_codepoint = "\u{211D}"; |
| let character_name = "\"DOUBLE-STRUCK CAPITAL R\""; |
| |
| println!("Unicode character {} (U+211D) is called {}", |
| unicode_codepoint, character_name ); |
| |
| |
| let long_string = "String literals |
| can span multiple lines. |
| The linebreak and indentation here ->\ |
| <- can be escaped too!"; |
| println!("{}", long_string); |
| } |
| </code></pre></pre> |
| <p>Sometimes there are just too many characters that need to be escaped or it's just |
| much more convenient to write a string out as-is. This is where raw string literals come into play.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let raw_str = r"Escapes don't work here: \x3F \u{211D}"; |
| println!("{}", raw_str); |
| |
| // If you need quotes in a raw string, add a pair of #s |
| let quotes = r#"And then I said: "There is no escape!""#; |
| println!("{}", quotes); |
| |
| // If you need "# in your string, just use more #s in the delimiter. |
| // There is no limit for the number of #s you can use. |
| let longer_delimiter = r###"A string with "# in it. And even "##!"###; |
| println!("{}", longer_delimiter); |
| } |
| </code></pre></pre> |
| <p>Want a string that's not UTF-8? (Remember, <code>str</code> and <code>String</code> must be valid UTF-8). |
| Or maybe you want an array of bytes that's mostly text? Byte strings to the rescue!</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::str; |
| |
| fn main() { |
| // Note that this is not actually a `&str` |
| let bytestring: &[u8; 21] = b"this is a byte string"; |
| |
| // Byte arrays don't have the `Display` trait, so printing them is a bit limited |
| println!("A byte string: {:?}", bytestring); |
| |
| // Byte strings can have byte escapes... |
| let escaped = b"\x52\x75\x73\x74 as bytes"; |
| // ...but no unicode escapes |
| // let escaped = b"\u{211D} is not allowed"; |
| println!("Some escaped bytes: {:?}", escaped); |
| |
| |
| // Raw byte strings work just like raw strings |
| let raw_bytestring = br"\u{211D} is not escaped here"; |
| println!("{:?}", raw_bytestring); |
| |
| // Converting a byte array to `str` can fail |
| if let Ok(my_str) = str::from_utf8(raw_bytestring) { |
| println!("And the same as text: '{}'", my_str); |
| } |
| |
| let _quotes = br#"You can also use "fancier" formatting, \ |
| like with normal raw strings"#; |
| |
| // Byte strings don't have to be UTF-8 |
| let shift_jis = b"\x82\xe6\x82\xa8\x82\xb1\x82\xbb"; // "ようこそ" in SHIFT-JIS |
| |
| // But then they can't always be converted to `str` |
| match str::from_utf8(shift_jis) { |
| Ok(my_str) => println!("Conversion successful: '{}'", my_str), |
| Err(e) => println!("Conversion failed: {:?}", e), |
| }; |
| } |
| </code></pre></pre> |
| <p>For conversions between character encodings check out the <a href="https://crates.io/crates/encoding">encoding</a> crate.</p> |
| <p>A more detailed listing of the ways to write string literals and escape characters |
| is given in the <a href="https://doc.rust-lang.org/reference/tokens.html">'Tokens' chapter</a> of the Rust Reference.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="option"><a class="header" href="#option"><code>Option</code></a></h1> |
| <p>Sometimes it's desirable to catch the failure of some parts of a program |
| instead of calling <code>panic!</code>; this can be accomplished using the <code>Option</code> enum.</p> |
| <p>The <code>Option<T></code> enum has two variants:</p> |
| <ul> |
| <li><code>None</code>, to indicate failure or lack of value, and</li> |
| <li><code>Some(value)</code>, a tuple struct that wraps a <code>value</code> with type <code>T</code>.</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">// An integer division that doesn't `panic!` |
| fn checked_division(dividend: i32, divisor: i32) -> Option<i32> { |
| if divisor == 0 { |
| // Failure is represented as the `None` variant |
| None |
| } else { |
| // Result is wrapped in a `Some` variant |
| Some(dividend / divisor) |
| } |
| } |
| |
| // This function handles a division that may not succeed |
| fn try_division(dividend: i32, divisor: i32) { |
| // `Option` values can be pattern matched, just like other enums |
| match checked_division(dividend, divisor) { |
| None => println!("{} / {} failed!", dividend, divisor), |
| Some(quotient) => { |
| println!("{} / {} = {}", dividend, divisor, quotient) |
| }, |
| } |
| } |
| |
| fn main() { |
| try_division(4, 2); |
| try_division(1, 0); |
| |
| // Binding `None` to a variable needs to be type annotated |
| let none: Option<i32> = None; |
| let _equivalent_none = None::<i32>; |
| |
| let optional_float = Some(0f32); |
| |
| // Unwrapping a `Some` variant will extract the value wrapped. |
| println!("{:?} unwraps to {:?}", optional_float, optional_float.unwrap()); |
| |
| // Unwrapping a `None` variant will `panic!` |
| println!("{:?} unwraps to {:?}", none, none.unwrap()); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="result-1"><a class="header" href="#result-1"><code>Result</code></a></h1> |
| <p>We've seen that the <code>Option</code> enum can be used as a return value from functions |
| that may fail, where <code>None</code> can be returned to indicate failure. However, |
| sometimes it is important to express <em>why</em> an operation failed. To do this we |
| have the <code>Result</code> enum.</p> |
| <p>The <code>Result<T, E></code> enum has two variants:</p> |
| <ul> |
| <li><code>Ok(value)</code> which indicates that the operation succeeded, and wraps the |
| <code>value</code> returned by the operation. (<code>value</code> has type <code>T</code>)</li> |
| <li><code>Err(why)</code>, which indicates that the operation failed, and wraps <code>why</code>, |
| which (hopefully) explains the cause of the failure. (<code>why</code> has type <code>E</code>)</li> |
| </ul> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">mod checked { |
| // Mathematical "errors" we want to catch |
| #[derive(Debug)] |
| pub enum MathError { |
| DivisionByZero, |
| NonPositiveLogarithm, |
| NegativeSquareRoot, |
| } |
| |
| pub type MathResult = Result<f64, MathError>; |
| |
| pub fn div(x: f64, y: f64) -> MathResult { |
| if y == 0.0 { |
| // This operation would `fail`, instead let's return the reason of |
| // the failure wrapped in `Err` |
| Err(MathError::DivisionByZero) |
| } else { |
| // This operation is valid, return the result wrapped in `Ok` |
| Ok(x / y) |
| } |
| } |
| |
| pub fn sqrt(x: f64) -> MathResult { |
| if x < 0.0 { |
| Err(MathError::NegativeSquareRoot) |
| } else { |
| Ok(x.sqrt()) |
| } |
| } |
| |
| pub fn ln(x: f64) -> MathResult { |
| if x <= 0.0 { |
| Err(MathError::NonPositiveLogarithm) |
| } else { |
| Ok(x.ln()) |
| } |
| } |
| } |
| |
| // `op(x, y)` === `sqrt(ln(x / y))` |
| fn op(x: f64, y: f64) -> f64 { |
| // This is a three level match pyramid! |
| match checked::div(x, y) { |
| Err(why) => panic!("{:?}", why), |
| Ok(ratio) => match checked::ln(ratio) { |
| Err(why) => panic!("{:?}", why), |
| Ok(ln) => match checked::sqrt(ln) { |
| Err(why) => panic!("{:?}", why), |
| Ok(sqrt) => sqrt, |
| }, |
| }, |
| } |
| } |
| |
| fn main() { |
| // Will this fail? |
| println!("{}", op(1.0, 10.0)); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id=""><a class="header" href="#"><code>?</code></a></h1> |
| <p>Chaining results using match can get pretty untidy; luckily, the <code>?</code> operator |
| can be used to make things pretty again. <code>?</code> is used at the end of an expression |
| returning a <code>Result</code>, and is equivalent to a match expression, where the |
| <code>Err(err)</code> branch expands to an early <code>Err(From::from(err))</code>, and the <code>Ok(ok)</code> |
| branch expands to an <code>ok</code> expression.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">mod checked { |
| #[derive(Debug)] |
| enum MathError { |
| DivisionByZero, |
| NonPositiveLogarithm, |
| NegativeSquareRoot, |
| } |
| |
| type MathResult = Result<f64, MathError>; |
| |
| fn div(x: f64, y: f64) -> MathResult { |
| if y == 0.0 { |
| Err(MathError::DivisionByZero) |
| } else { |
| Ok(x / y) |
| } |
| } |
| |
| fn sqrt(x: f64) -> MathResult { |
| if x < 0.0 { |
| Err(MathError::NegativeSquareRoot) |
| } else { |
| Ok(x.sqrt()) |
| } |
| } |
| |
| fn ln(x: f64) -> MathResult { |
| if x <= 0.0 { |
| Err(MathError::NonPositiveLogarithm) |
| } else { |
| Ok(x.ln()) |
| } |
| } |
| |
| // Intermediate function |
| fn op_(x: f64, y: f64) -> MathResult { |
| // if `div` "fails", then `DivisionByZero` will be `return`ed |
| let ratio = div(x, y)?; |
| |
| // if `ln` "fails", then `NonPositiveLogarithm` will be `return`ed |
| let ln = ln(ratio)?; |
| |
| sqrt(ln) |
| } |
| |
| pub fn op(x: f64, y: f64) { |
| match op_(x, y) { |
| Err(why) => panic!("{}", match why { |
| MathError::NonPositiveLogarithm |
| => "logarithm of non-positive number", |
| MathError::DivisionByZero |
| => "division by zero", |
| MathError::NegativeSquareRoot |
| => "square root of negative number", |
| }), |
| Ok(value) => println!("{}", value), |
| } |
| } |
| } |
| |
| fn main() { |
| checked::op(1.0, 10.0); |
| } |
| </code></pre></pre> |
| <p>Be sure to check the <a href="https://doc.rust-lang.org/std/result/index.html">documentation</a>, |
| as there are many methods to map/compose <code>Result</code>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="panic-1"><a class="header" href="#panic-1"><code>panic!</code></a></h1> |
| <p>The <code>panic!</code> macro can be used to generate a panic and start unwinding |
| its stack. While unwinding, the runtime will take care of freeing all the |
| resources <em>owned</em> by the thread by calling the destructor of all its objects.</p> |
| <p>Since we are dealing with programs with only one thread, <code>panic!</code> will cause the |
| program to report the panic message and exit.</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">// Re-implementation of integer division (/) |
| fn division(dividend: i32, divisor: i32) -> i32 { |
| if divisor == 0 { |
| // Division by zero triggers a panic |
| panic!("division by zero"); |
| } else { |
| dividend / divisor |
| } |
| } |
| |
| // The `main` task |
| fn main() { |
| // Heap allocated integer |
| let _x = Box::new(0i32); |
| |
| // This operation will trigger a task failure |
| division(3, 0); |
| |
| println!("This point won't be reached!"); |
| |
| // `_x` should get destroyed at this point |
| } |
| </code></pre></pre> |
| <p>Let's check that <code>panic!</code> doesn't leak memory.</p> |
| <pre><code class="language-shell">$ rustc panic.rs && valgrind ./panic |
| ==4401== Memcheck, a memory error detector |
| ==4401== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. |
| ==4401== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info |
| ==4401== Command: ./panic |
| ==4401== |
| thread '<main>' panicked at 'division by zero', panic.rs:5 |
| ==4401== |
| ==4401== HEAP SUMMARY: |
| ==4401== in use at exit: 0 bytes in 0 blocks |
| ==4401== total heap usage: 18 allocs, 18 frees, 1,648 bytes allocated |
| ==4401== |
| ==4401== All heap blocks were freed -- no leaks are possible |
| ==4401== |
| ==4401== For counts of detected and suppressed errors, rerun with: -v |
| ==4401== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="hashmap"><a class="header" href="#hashmap">HashMap</a></h1> |
| <p>Where vectors store values by an integer index, <code>HashMap</code>s store values by key. |
| <code>HashMap</code> keys can be booleans, integers, strings, |
| or any other type that implements the <code>Eq</code> and <code>Hash</code> traits. |
| More on this in the next section.</p> |
| <p>Like vectors, <code>HashMap</code>s are growable, but HashMaps can also shrink themselves |
| when they have excess space. |
| You can create a HashMap with a certain starting capacity using |
| <code>HashMap::with_capacity(uint)</code>, or use <code>HashMap::new()</code> to get a HashMap |
| with a default initial capacity (recommended).</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::collections::HashMap; |
| |
| fn call(number: &str) -> &str { |
| match number { |
| "798-1364" => "We're sorry, the call cannot be completed as dialed. |
| Please hang up and try again.", |
| "645-7689" => "Hello, this is Mr. Awesome's Pizza. My name is Fred. |
| What can I get for you today?", |
| _ => "Hi! Who is this again?" |
| } |
| } |
| |
| fn main() { |
| let mut contacts = HashMap::new(); |
| |
| contacts.insert("Daniel", "798-1364"); |
| contacts.insert("Ashley", "645-7689"); |
| contacts.insert("Katie", "435-8291"); |
| contacts.insert("Robert", "956-1745"); |
| |
| // Takes a reference and returns Option<&V> |
| match contacts.get(&"Daniel") { |
| Some(&number) => println!("Calling Daniel: {}", call(number)), |
| _ => println!("Don't have Daniel's number."), |
| } |
| |
| // `HashMap::insert()` returns `None` |
| // if the inserted value is new, `Some(value)` otherwise |
| contacts.insert("Daniel", "164-6743"); |
| |
| match contacts.get(&"Ashley") { |
| Some(&number) => println!("Calling Ashley: {}", call(number)), |
| _ => println!("Don't have Ashley's number."), |
| } |
| |
| contacts.remove(&"Ashley"); |
| |
| // `HashMap::iter()` returns an iterator that yields |
| // (&'a key, &'a value) pairs in arbitrary order. |
| for (contact, &number) in contacts.iter() { |
| println!("Calling {}: {}", contact, call(number)); |
| } |
| } |
| </code></pre></pre> |
| <p>For more information on how hashing and hash maps |
| (sometimes called hash tables) work, have a look at |
| <a href="https://en.wikipedia.org/wiki/Hash_table">Hash Table Wikipedia</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="alternatecustom-key-types"><a class="header" href="#alternatecustom-key-types">Alternate/custom key types</a></h1> |
| <p>Any type that implements the <code>Eq</code> and <code>Hash</code> traits can be a key in <code>HashMap</code>. |
| This includes:</p> |
| <ul> |
| <li><code>bool</code> (though not very useful since there is only two possible keys)</li> |
| <li><code>int</code>, <code>uint</code>, and all variations thereof</li> |
| <li><code>String</code> and <code>&str</code> (protip: you can have a <code>HashMap</code> keyed by <code>String</code> |
| and call <code>.get()</code> with an <code>&str</code>)</li> |
| </ul> |
| <p>Note that <code>f32</code> and <code>f64</code> do <em>not</em> implement <code>Hash</code>, |
| likely because <a href="https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems">floating-point precision errors</a> |
| would make using them as hashmap keys horribly error-prone.</p> |
| <p>All collection classes implement <code>Eq</code> and <code>Hash</code> |
| if their contained type also respectively implements <code>Eq</code> and <code>Hash</code>. |
| For example, <code>Vec<T></code> will implement <code>Hash</code> if <code>T</code> implements <code>Hash</code>.</p> |
| <p>You can easily implement <code>Eq</code> and <code>Hash</code> for a custom type with just one line: |
| <code>#[derive(PartialEq, Eq, Hash)]</code></p> |
| <p>The compiler will do the rest. If you want more control over the details, |
| you can implement <code>Eq</code> and/or <code>Hash</code> yourself. |
| This guide will not cover the specifics of implementing <code>Hash</code>. </p> |
| <p>To play around with using a <code>struct</code> in <code>HashMap</code>, |
| let's try making a very simple user logon system:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::collections::HashMap; |
| |
| // Eq requires that you derive PartialEq on the type. |
| #[derive(PartialEq, Eq, Hash)] |
| struct Account<'a>{ |
| username: &'a str, |
| password: &'a str, |
| } |
| |
| struct AccountInfo<'a>{ |
| name: &'a str, |
| email: &'a str, |
| } |
| |
| type Accounts<'a> = HashMap<Account<'a>, AccountInfo<'a>>; |
| |
| fn try_logon<'a>(accounts: &Accounts<'a>, |
| username: &'a str, password: &'a str){ |
| println!("Username: {}", username); |
| println!("Password: {}", password); |
| println!("Attempting logon..."); |
| |
| let logon = Account { |
| username, |
| password, |
| }; |
| |
| match accounts.get(&logon) { |
| Some(account_info) => { |
| println!("Successful logon!"); |
| println!("Name: {}", account_info.name); |
| println!("Email: {}", account_info.email); |
| }, |
| _ => println!("Login failed!"), |
| } |
| } |
| |
| fn main(){ |
| let mut accounts: Accounts = HashMap::new(); |
| |
| let account = Account { |
| username: "j.everyman", |
| password: "password123", |
| }; |
| |
| let account_info = AccountInfo { |
| name: "John Everyman", |
| email: "j.everyman@email.com", |
| }; |
| |
| accounts.insert(account, account_info); |
| |
| try_logon(&accounts, "j.everyman", "psasword123"); |
| |
| try_logon(&accounts, "j.everyman", "password123"); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="hashset"><a class="header" href="#hashset">HashSet</a></h1> |
| <p>Consider a <code>HashSet</code> as a <code>HashMap</code> where we just care about the keys ( |
| <code>HashSet<T></code> is, in actuality, just a wrapper around <code>HashMap<T, ()></code>).</p> |
| <p>"What's the point of that?" you ask. "I could just store the keys in a <code>Vec</code>."</p> |
| <p>A <code>HashSet</code>'s unique feature is that |
| it is guaranteed to not have duplicate elements. |
| That's the contract that any set collection fulfills. |
| <code>HashSet</code> is just one implementation. (see also: <a href="https://doc.rust-lang.org/std/collections/struct.BTreeSet.html"><code>BTreeSet</code></a>)</p> |
| <p>If you insert a value that is already present in the <code>HashSet</code>, |
| (i.e. the new value is equal to the existing and they both have the same hash), |
| then the new value will replace the old.</p> |
| <p>This is great for when you never want more than one of something, |
| or when you want to know if you've already got something.</p> |
| <p>But sets can do more than that. </p> |
| <p>Sets have 4 primary operations (all of the following calls return an iterator):</p> |
| <ul> |
| <li> |
| <p><code>union</code>: get all the unique elements in both sets.</p> |
| </li> |
| <li> |
| <p><code>difference</code>: get all the elements that are in the first set but not the second.</p> |
| </li> |
| <li> |
| <p><code>intersection</code>: get all the elements that are only in <em>both</em> sets.</p> |
| </li> |
| <li> |
| <p><code>symmetric_difference</code>: |
| get all the elements that are in one set or the other, but <em>not</em> both.</p> |
| </li> |
| </ul> |
| <p>Try all of these in the following example:</p> |
| <pre><pre class="playground"><code class="language-rust editable ignore mdbook-runnable">use std::collections::HashSet; |
| |
| fn main() { |
| let mut a: HashSet<i32> = vec![1i32, 2, 3].into_iter().collect(); |
| let mut b: HashSet<i32> = vec![2i32, 3, 4].into_iter().collect(); |
| |
| assert!(a.insert(4)); |
| assert!(a.contains(&4)); |
| |
| // `HashSet::insert()` returns false if |
| // there was a value already present. |
| assert!(b.insert(4), "Value 4 is already in set B!"); |
| // FIXME ^ Comment out this line |
| |
| b.insert(5); |
| |
| // If a collection's element type implements `Debug`, |
| // then the collection implements `Debug`. |
| // It usually prints its elements in the format `[elem1, elem2, ...]` |
| println!("A: {:?}", a); |
| println!("B: {:?}", b); |
| |
| // Print [1, 2, 3, 4, 5] in arbitrary order |
| println!("Union: {:?}", a.union(&b).collect::<Vec<&i32>>()); |
| |
| // This should print [1] |
| println!("Difference: {:?}", a.difference(&b).collect::<Vec<&i32>>()); |
| |
| // Print [2, 3, 4] in arbitrary order. |
| println!("Intersection: {:?}", a.intersection(&b).collect::<Vec<&i32>>()); |
| |
| // Print [1, 5] |
| println!("Symmetric Difference: {:?}", |
| a.symmetric_difference(&b).collect::<Vec<&i32>>()); |
| } |
| </code></pre></pre> |
| <p>(Examples are adapted from the <a href="https://doc.rust-lang.org/std/collections/struct.HashSet.html#method.difference">documentation.</a>)</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="rc"><a class="header" href="#rc"><code>Rc</code></a></h1> |
| <p>When multiple ownership is needed, <code>Rc</code>(Reference Counting) can be used. <code>Rc</code> keeps track of the number of the references which means the number of owners of the value wrapped inside an <code>Rc</code>. </p> |
| <p>Reference count of an <code>Rc</code> increases by 1 whenever an <code>Rc</code> is cloned, and decreases by 1 whenever one cloned <code>Rc</code> is dropped out of the scope. When an <code>Rc</code>'s reference count becomes zero, which means there are no owners remained, both the <code>Rc</code> and the value are all dropped. </p> |
| <p>Cloning an <code>Rc</code> never performs a deep copy. Cloning creates just another pointer to the wrapped value, and increments the count.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::rc::Rc; |
| |
| fn main() { |
| let rc_examples = "Rc examples".to_string(); |
| { |
| println!("--- rc_a is created ---"); |
| |
| let rc_a: Rc<String> = Rc::new(rc_examples); |
| println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); |
| |
| { |
| println!("--- rc_a is cloned to rc_b ---"); |
| |
| let rc_b: Rc<String> = Rc::clone(&rc_a); |
| println!("Reference Count of rc_b: {}", Rc::strong_count(&rc_b)); |
| println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); |
| |
| // Two `Rc`s are equal if their inner values are equal |
| println!("rc_a and rc_b are equal: {}", rc_a.eq(&rc_b)); |
| |
| // We can use methods of a value directly |
| println!("Length of the value inside rc_a: {}", rc_a.len()); |
| println!("Value of rc_b: {}", rc_b); |
| |
| println!("--- rc_b is dropped out of scope ---"); |
| } |
| |
| println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); |
| |
| println!("--- rc_a is dropped out of scope ---"); |
| } |
| |
| // Error! `rc_examples` already moved into `rc_a` |
| // And when `rc_a` is dropped, `rc_examples` is dropped together |
| // println!("rc_examples: {}", rc_examples); |
| // TODO ^ Try uncommenting this line |
| } |
| </code></pre></pre> |
| <h3 id="see-also-67"><a class="header" href="#see-also-67">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/rc/index.html">std::rc</a> and <a href="https://doc.rust-lang.org/std/sync/struct.Arc.html">std::sync::arc</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="arc"><a class="header" href="#arc">Arc</a></h1> |
| <p>When shared ownership between threads is needed, <code>Arc</code>(Atomic Reference Counted) can be used. This struct, via the <code>Clone</code> implementation can create a reference pointer for the location of a value in the memory heap while increasing the reference counter. As it shares ownership between threads, when the last reference pointer to a value is out of scope, the variable is dropped.</p> |
| <pre><pre class="playground"><code class="language-rust editable"> |
| fn main() { |
| use std::sync::Arc; |
| use std::thread; |
| |
| // This variable declaration is where its value is specified. |
| let apple = Arc::new("the same apple"); |
| |
| for _ in 0..10 { |
| // Here there is no value specification as it is a pointer to a reference |
| // in the memory heap. |
| let apple = Arc::clone(&apple); |
| |
| thread::spawn(move || { |
| // As Arc was used, threads can be spawned using the value allocated |
| // in the Arc variable pointer's location. |
| println!("{:?}", apple); |
| }); |
| } |
| } |
| |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="std-misc"><a class="header" href="#std-misc">Std misc</a></h1> |
| <p>Many other types are provided by the std library to support |
| things such as:</p> |
| <ul> |
| <li>Threads</li> |
| <li>Channels</li> |
| <li>File I/O</li> |
| </ul> |
| <p>These expand beyond what the <a href="primitives.html">primitives</a> provide.</p> |
| <h3 id="see-also-68"><a class="header" href="#see-also-68">See also:</a></h3> |
| <p><a href="primitives.html">primitives</a> and <a href="https://doc.rust-lang.org/std/">the std library</a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="threads"><a class="header" href="#threads">Threads</a></h1> |
| <p>Rust provides a mechanism for spawning native OS threads via the <code>spawn</code> |
| function, the argument of this function is a moving closure.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::thread; |
| |
| const NTHREADS: u32 = 10; |
| |
| // This is the `main` thread |
| fn main() { |
| // Make a vector to hold the children which are spawned. |
| let mut children = vec![]; |
| |
| for i in 0..NTHREADS { |
| // Spin up another thread |
| children.push(thread::spawn(move || { |
| println!("this is thread number {}", i); |
| })); |
| } |
| |
| for child in children { |
| // Wait for the thread to finish. Returns a result. |
| let _ = child.join(); |
| } |
| } |
| </code></pre></pre> |
| <p>These threads will be scheduled by the OS.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="testcase-map-reduce"><a class="header" href="#testcase-map-reduce">Testcase: map-reduce</a></h1> |
| <p>Rust makes it very easy to parallelise data processing, without many of the headaches traditionally associated with such an attempt.</p> |
| <p>The standard library provides great threading primitives out of the box. |
| These, combined with Rust's concept of Ownership and aliasing rules, automatically prevent |
| data races.</p> |
| <p>The aliasing rules (one writable reference XOR many readable references) automatically prevent |
| you from manipulating state that is visible to other threads. (Where synchronisation is needed, |
| there are synchronisation |
| primitives like <code>Mutex</code>es or <code>Channel</code>s.)</p> |
| <p>In this example, we will calculate the sum of all digits in a block of numbers. |
| We will do this by parcelling out chunks of the block into different threads. Each thread will sum |
| its tiny block of digits, and subsequently we will sum the intermediate sums produced by each |
| thread.</p> |
| <p>Note that, although we're passing references across thread boundaries, Rust understands that we're |
| only passing read-only references, and that thus no unsafety or data races can occur. Because |
| we're <code>move</code>-ing the data segments into the thread, Rust will also ensure the data is kept alive |
| until the threads exit, so no dangling pointers occur.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::thread; |
| |
| // This is the `main` thread |
| fn main() { |
| |
| // This is our data to process. |
| // We will calculate the sum of all digits via a threaded map-reduce algorithm. |
| // Each whitespace separated chunk will be handled in a different thread. |
| // |
| // TODO: see what happens to the output if you insert spaces! |
| let data = "86967897737416471853297327050364959 |
| 11861322575564723963297542624962850 |
| 70856234701860851907960690014725639 |
| 38397966707106094172783238747669219 |
| 52380795257888236525459303330302837 |
| 58495327135744041048897885734297812 |
| 69920216438980873548808413720956532 |
| 16278424637452589860345374828574668"; |
| |
| // Make a vector to hold the child-threads which we will spawn. |
| let mut children = vec![]; |
| |
| /************************************************************************* |
| * "Map" phase |
| * |
| * Divide our data into segments, and apply initial processing |
| ************************************************************************/ |
| |
| // split our data into segments for individual calculation |
| // each chunk will be a reference (&str) into the actual data |
| let chunked_data = data.split_whitespace(); |
| |
| // Iterate over the data segments. |
| // .enumerate() adds the current loop index to whatever is iterated |
| // the resulting tuple "(index, element)" is then immediately |
| // "destructured" into two variables, "i" and "data_segment" with a |
| // "destructuring assignment" |
| for (i, data_segment) in chunked_data.enumerate() { |
| println!("data segment {} is \"{}\"", i, data_segment); |
| |
| // Process each data segment in a separate thread |
| // |
| // spawn() returns a handle to the new thread, |
| // which we MUST keep to access the returned value |
| // |
| // 'move || -> u32' is syntax for a closure that: |
| // * takes no arguments ('||') |
| // * takes ownership of its captured variables ('move') and |
| // * returns an unsigned 32-bit integer ('-> u32') |
| // |
| // Rust is smart enough to infer the '-> u32' from |
| // the closure itself so we could have left that out. |
| // |
| // TODO: try removing the 'move' and see what happens |
| children.push(thread::spawn(move || -> u32 { |
| // Calculate the intermediate sum of this segment: |
| let result = data_segment |
| // iterate over the characters of our segment.. |
| .chars() |
| // .. convert text-characters to their number value.. |
| .map(|c| c.to_digit(10).expect("should be a digit")) |
| // .. and sum the resulting iterator of numbers |
| .sum(); |
| |
| // println! locks stdout, so no text-interleaving occurs |
| println!("processed segment {}, result={}", i, result); |
| |
| // "return" not needed, because Rust is an "expression language", the |
| // last evaluated expression in each block is automatically its value. |
| result |
| |
| })); |
| } |
| |
| |
| /************************************************************************* |
| * "Reduce" phase |
| * |
| * Collect our intermediate results, and combine them into a final result |
| ************************************************************************/ |
| |
| // combine each thread's intermediate results into a single final sum. |
| // |
| // we use the "turbofish" ::<> to provide sum() with a type hint. |
| // |
| // TODO: try without the turbofish, by instead explicitly |
| // specifying the type of final_result |
| let final_result = children.into_iter().map(|c| c.join().unwrap()).sum::<u32>(); |
| |
| println!("Final sum result: {}", final_result); |
| } |
| |
| |
| </code></pre></pre> |
| <h3 id="assignments"><a class="header" href="#assignments">Assignments</a></h3> |
| <p>It is not wise to let our number of threads depend on user inputted data. |
| What if the user decides to insert a lot of spaces? Do we <em>really</em> want to spawn 2,000 threads? |
| Modify the program so that the data is always chunked into a limited number of chunks, |
| defined by a static constant at the beginning of the program.</p> |
| <h3 id="see-also-69"><a class="header" href="#see-also-69">See also:</a></h3> |
| <ul> |
| <li><a href="std_misc/threads/../threads.html">Threads</a></li> |
| <li><a href="std_misc/threads/../../std/vec.html">vectors</a> and <a href="std_misc/threads/../../trait/iter.html">iterators</a></li> |
| <li><a href="std_misc/threads/../../fn/closures.html">closures</a>, <a href="std_misc/threads/../../scope/move.html">move</a> semantics and <a href="https://doc.rust-lang.org/book/ch13-01-closures.html#closures-can-capture-their-environment"><code>move</code> closures</a></li> |
| <li><a href="https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#destructuring-to-break-apart-values">destructuring</a> assignments</li> |
| <li><a href="https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect">turbofish notation</a> to help type inference</li> |
| <li><a href="std_misc/threads/../../error/option_unwrap.html">unwrap vs. expect</a></li> |
| <li><a href="https://doc.rust-lang.org/book/loops.html#enumerate">enumerate</a></li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="channels"><a class="header" href="#channels">Channels</a></h1> |
| <p>Rust provides asynchronous <code>channels</code> for communication between threads. Channels |
| allow a unidirectional flow of information between two end-points: the |
| <code>Sender</code> and the <code>Receiver</code>.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::sync::mpsc::{Sender, Receiver}; |
| use std::sync::mpsc; |
| use std::thread; |
| |
| static NTHREADS: i32 = 3; |
| |
| fn main() { |
| // Channels have two endpoints: the `Sender<T>` and the `Receiver<T>`, |
| // where `T` is the type of the message to be transferred |
| // (type annotation is superfluous) |
| let (tx, rx): (Sender<i32>, Receiver<i32>) = mpsc::channel(); |
| let mut children = Vec::new(); |
| |
| for id in 0..NTHREADS { |
| // The sender endpoint can be copied |
| let thread_tx = tx.clone(); |
| |
| // Each thread will send its id via the channel |
| let child = thread::spawn(move || { |
| // The thread takes ownership over `thread_tx` |
| // Each thread queues a message in the channel |
| thread_tx.send(id).unwrap(); |
| |
| // Sending is a non-blocking operation, the thread will continue |
| // immediately after sending its message |
| println!("thread {} finished", id); |
| }); |
| |
| children.push(child); |
| } |
| |
| // Here, all the messages are collected |
| let mut ids = Vec::with_capacity(NTHREADS as usize); |
| for _ in 0..NTHREADS { |
| // The `recv` method picks a message from the channel |
| // `recv` will block the current thread if there are no messages available |
| ids.push(rx.recv()); |
| } |
| |
| // Wait for the threads to complete any remaining work |
| for child in children { |
| child.join().expect("oops! the child thread panicked"); |
| } |
| |
| // Show the order in which the messages were sent |
| println!("{:?}", ids); |
| } |
| </code></pre></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="path"><a class="header" href="#path">Path</a></h1> |
| <p>The <code>Path</code> struct represents file paths in the underlying filesystem. There are |
| two flavors of <code>Path</code>: <code>posix::Path</code>, for UNIX-like systems, and |
| <code>windows::Path</code>, for Windows. The prelude exports the appropriate |
| platform-specific <code>Path</code> variant.</p> |
| <p>A <code>Path</code> can be created from an <code>OsStr</code>, and provides several methods to get |
| information from the file/directory the path points to.</p> |
| <p>Note that a <code>Path</code> is <em>not</em> internally represented as an UTF-8 string, but |
| instead is stored as a vector of bytes (<code>Vec<u8></code>). Therefore, converting a |
| <code>Path</code> to a <code>&str</code> is <em>not</em> free and may fail (an <code>Option</code> is returned).</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::path::Path; |
| |
| fn main() { |
| // Create a `Path` from an `&'static str` |
| let path = Path::new("."); |
| |
| // The `display` method returns a `Show`able structure |
| let _display = path.display(); |
| |
| // `join` merges a path with a byte container using the OS specific |
| // separator, and returns the new path |
| let new_path = path.join("a").join("b"); |
| |
| // Convert the path into a string slice |
| match new_path.to_str() { |
| None => panic!("new path is not a valid UTF-8 sequence"), |
| Some(s) => println!("new path is {}", s), |
| } |
| } |
| |
| </code></pre></pre> |
| <p>Be sure to check at other <code>Path</code> methods (<code>posix::Path</code> or <code>windows::Path</code>) and |
| the <code>Metadata</code> struct.</p> |
| <h3 id="see-also-70"><a class="header" href="#see-also-70">See also:</a></h3> |
| <p><a href="https://doc.rust-lang.org/std/ffi/struct.OsStr.html">OsStr</a> and <a href="https://doc.rust-lang.org/std/fs/struct.Metadata.html">Metadata</a>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="file-io"><a class="header" href="#file-io">File I/O</a></h1> |
| <p>The <code>File</code> struct represents a file that has been opened (it wraps a file |
| descriptor), and gives read and/or write access to the underlying file.</p> |
| <p>Since many things can go wrong when doing file I/O, all the <code>File</code> methods |
| return the <code>io::Result<T></code> type, which is an alias for <code>Result<T, io::Error></code>.</p> |
| <p>This makes the failure of all I/O operations <em>explicit</em>. Thanks to this, the |
| programmer can see all the failure paths, and is encouraged to handle them in |
| a proactive manner.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="open"><a class="header" href="#open"><code>open</code></a></h1> |
| <p>The <code>open</code> static method can be used to open a file in read-only mode.</p> |
| <p>A <code>File</code> owns a resource, the file descriptor and takes care of closing the |
| file when it is <code>drop</code>ed.</p> |
| <pre><code class="language-rust editable ignore">use std::fs::File; |
| use std::io::prelude::*; |
| use std::path::Path; |
| |
| fn main() { |
| // Create a path to the desired file |
| let path = Path::new("hello.txt"); |
| let display = path.display(); |
| |
| // Open the path in read-only mode, returns `io::Result<File>` |
| let mut file = match File::open(&path) { |
| Err(why) => panic!("couldn't open {}: {}", display, why), |
| Ok(file) => file, |
| }; |
| |
| // Read the file contents into a string, returns `io::Result<usize>` |
| let mut s = String::new(); |
| match file.read_to_string(&mut s) { |
| Err(why) => panic!("couldn't read {}: {}", display, why), |
| Ok(_) => print!("{} contains:\n{}", display, s), |
| } |
| |
| // `file` goes out of scope, and the "hello.txt" file gets closed |
| } |
| </code></pre> |
| <p>Here's the expected successful output:</p> |
| <pre><code class="language-shell">$ echo "Hello World!" > hello.txt |
| $ rustc open.rs && ./open |
| hello.txt contains: |
| Hello World! |
| </code></pre> |
| <p>(You are encouraged to test the previous example under different failure |
| conditions: <code>hello.txt</code> doesn't exist, or <code>hello.txt</code> is not readable, |
| etc.)</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="create"><a class="header" href="#create"><code>create</code></a></h1> |
| <p>The <code>create</code> static method opens a file in write-only mode. If the file |
| already existed, the old content is destroyed. Otherwise, a new file is |
| created.</p> |
| <pre><code class="language-rust ignore">static LOREM_IPSUM: &str = |
| "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod |
| tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, |
| quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo |
| consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse |
| cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non |
| proident, sunt in culpa qui officia deserunt mollit anim id est laborum. |
| "; |
| |
| use std::fs::File; |
| use std::io::prelude::*; |
| use std::path::Path; |
| |
| fn main() { |
| let path = Path::new("lorem_ipsum.txt"); |
| let display = path.display(); |
| |
| // Open a file in write-only mode, returns `io::Result<File>` |
| let mut file = match File::create(&path) { |
| Err(why) => panic!("couldn't create {}: {}", display, why), |
| Ok(file) => file, |
| }; |
| |
| // Write the `LOREM_IPSUM` string to `file`, returns `io::Result<()>` |
| match file.write_all(LOREM_IPSUM.as_bytes()) { |
| Err(why) => panic!("couldn't write to {}: {}", display, why), |
| Ok(_) => println!("successfully wrote to {}", display), |
| } |
| } |
| </code></pre> |
| <p>Here's the expected successful output:</p> |
| <pre><code class="language-shell">$ rustc create.rs && ./create |
| successfully wrote to lorem_ipsum.txt |
| $ cat lorem_ipsum.txt |
| Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod |
| tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, |
| quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo |
| consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse |
| cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non |
| proident, sunt in culpa qui officia deserunt mollit anim id est laborum. |
| </code></pre> |
| <p>(As in the previous example, you are encouraged to test this example under |
| failure conditions.)</p> |
| <p>There is <a href="https://doc.rust-lang.org/std/fs/struct.OpenOptions.html"><code>OpenOptions</code></a> struct that can be used to configure how a file is opened.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="read_lines"><a class="header" href="#read_lines"><code>read_lines</code></a></h1> |
| <p>The method <code>lines()</code> returns an iterator over the lines |
| of a file.</p> |
| <p><code>File::open</code> expects a generic, <code>AsRef<Path></code>. That's what |
| <code>read_lines()</code> expects as input.</p> |
| <pre><pre class="playground"><code class="language-rust no_run">use std::fs::File; |
| use std::io::{self, BufRead}; |
| use std::path::Path; |
| |
| fn main() { |
| // File hosts must exist in current path before this produces output |
| if let Ok(lines) = read_lines("./hosts") { |
| // Consumes the iterator, returns an (Optional) String |
| for line in lines { |
| if let Ok(ip) = line { |
| println!("{}", ip); |
| } |
| } |
| } |
| } |
| |
| // The output is wrapped in a Result to allow matching on errors |
| // Returns an Iterator to the Reader of the lines of the file. |
| fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>> |
| where P: AsRef<Path>, { |
| let file = File::open(filename)?; |
| Ok(io::BufReader::new(file).lines()) |
| } |
| </code></pre></pre> |
| <p>Running this program simply prints the lines individually.</p> |
| <pre><code class="language-shell">$ echo -e "127.0.0.1\n192.168.0.1\n" > hosts |
| $ rustc read_lines.rs && ./read_lines |
| 127.0.0.1 |
| 192.168.0.1 |
| </code></pre> |
| <p>This process is more efficient than creating a <code>String</code> in memory |
| especially working with larger files.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="child-processes"><a class="header" href="#child-processes">Child processes</a></h1> |
| <p>The <code>process::Output</code> struct represents the output of a finished child process, |
| and the <code>process::Command</code> struct is a process builder.</p> |
| <pre><code class="language-rust editable ignore">use std::process::Command; |
| |
| fn main() { |
| let output = Command::new("rustc") |
| .arg("--version") |
| .output().unwrap_or_else(|e| { |
| panic!("failed to execute process: {}", e) |
| }); |
| |
| if output.status.success() { |
| let s = String::from_utf8_lossy(&output.stdout); |
| |
| print!("rustc succeeded and stdout was:\n{}", s); |
| } else { |
| let s = String::from_utf8_lossy(&output.stderr); |
| |
| print!("rustc failed and stderr was:\n{}", s); |
| } |
| } |
| </code></pre> |
| <p>(You are encouraged to try the previous example with an incorrect flag passed |
| to <code>rustc</code>)</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="pipes"><a class="header" href="#pipes">Pipes</a></h1> |
| <p>The <code>std::Child</code> struct represents a running child process, and exposes the |
| <code>stdin</code>, <code>stdout</code> and <code>stderr</code> handles for interaction with the underlying |
| process via pipes.</p> |
| <pre><code class="language-rust ignore">use std::io::prelude::*; |
| use std::process::{Command, Stdio}; |
| |
| static PANGRAM: &'static str = |
| "the quick brown fox jumped over the lazy dog\n"; |
| |
| fn main() { |
| // Spawn the `wc` command |
| let process = match Command::new("wc") |
| .stdin(Stdio::piped()) |
| .stdout(Stdio::piped()) |
| .spawn() { |
| Err(why) => panic!("couldn't spawn wc: {}", why), |
| Ok(process) => process, |
| }; |
| |
| // Write a string to the `stdin` of `wc`. |
| // |
| // `stdin` has type `Option<ChildStdin>`, but since we know this instance |
| // must have one, we can directly `unwrap` it. |
| match process.stdin.unwrap().write_all(PANGRAM.as_bytes()) { |
| Err(why) => panic!("couldn't write to wc stdin: {}", why), |
| Ok(_) => println!("sent pangram to wc"), |
| } |
| |
| // Because `stdin` does not live after the above calls, it is `drop`ed, |
| // and the pipe is closed. |
| // |
| // This is very important, otherwise `wc` wouldn't start processing the |
| // input we just sent. |
| |
| // The `stdout` field also has type `Option<ChildStdout>` so must be unwrapped. |
| let mut s = String::new(); |
| match process.stdout.unwrap().read_to_string(&mut s) { |
| Err(why) => panic!("couldn't read wc stdout: {}", why), |
| Ok(_) => print!("wc responded with:\n{}", s), |
| } |
| } |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="wait"><a class="header" href="#wait">Wait</a></h1> |
| <p>If you'd like to wait for a <code>process::Child</code> to finish, you must call |
| <code>Child::wait</code>, which will return a <code>process::ExitStatus</code>.</p> |
| <pre><code class="language-rust ignore">use std::process::Command; |
| |
| fn main() { |
| let mut child = Command::new("sleep").arg("5").spawn().unwrap(); |
| let _result = child.wait().unwrap(); |
| |
| println!("reached end of main"); |
| } |
| </code></pre> |
| <pre><code class="language-bash">$ rustc wait.rs && ./wait |
| # `wait` keeps running for 5 seconds until the `sleep 5` command finishes |
| reached end of main |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="filesystem-operations"><a class="header" href="#filesystem-operations">Filesystem Operations</a></h1> |
| <p>The <code>std::fs</code> module contains several functions that deal with the filesystem.</p> |
| <pre><code class="language-rust ignore">use std::fs; |
| use std::fs::{File, OpenOptions}; |
| use std::io; |
| use std::io::prelude::*; |
| use std::os::unix; |
| use std::path::Path; |
| |
| // A simple implementation of `% cat path` |
| fn cat(path: &Path) -> io::Result<String> { |
| let mut f = File::open(path)?; |
| let mut s = String::new(); |
| match f.read_to_string(&mut s) { |
| Ok(_) => Ok(s), |
| Err(e) => Err(e), |
| } |
| } |
| |
| // A simple implementation of `% echo s > path` |
| fn echo(s: &str, path: &Path) -> io::Result<()> { |
| let mut f = File::create(path)?; |
| |
| f.write_all(s.as_bytes()) |
| } |
| |
| // A simple implementation of `% touch path` (ignores existing files) |
| fn touch(path: &Path) -> io::Result<()> { |
| match OpenOptions::new().create(true).write(true).open(path) { |
| Ok(_) => Ok(()), |
| Err(e) => Err(e), |
| } |
| } |
| |
| fn main() { |
| println!("`mkdir a`"); |
| // Create a directory, returns `io::Result<()>` |
| match fs::create_dir("a") { |
| Err(why) => println!("! {:?}", why.kind()), |
| Ok(_) => {}, |
| } |
| |
| println!("`echo hello > a/b.txt`"); |
| // The previous match can be simplified using the `unwrap_or_else` method |
| echo("hello", &Path::new("a/b.txt")).unwrap_or_else(|why| { |
| println!("! {:?}", why.kind()); |
| }); |
| |
| println!("`mkdir -p a/c/d`"); |
| // Recursively create a directory, returns `io::Result<()>` |
| fs::create_dir_all("a/c/d").unwrap_or_else(|why| { |
| println!("! {:?}", why.kind()); |
| }); |
| |
| println!("`touch a/c/e.txt`"); |
| touch(&Path::new("a/c/e.txt")).unwrap_or_else(|why| { |
| println!("! {:?}", why.kind()); |
| }); |
| |
| println!("`ln -s ../b.txt a/c/b.txt`"); |
| // Create a symbolic link, returns `io::Result<()>` |
| if cfg!(target_family = "unix") { |
| unix::fs::symlink("../b.txt", "a/c/b.txt").unwrap_or_else(|why| { |
| println!("! {:?}", why.kind()); |
| }); |
| } |
| |
| println!("`cat a/c/b.txt`"); |
| match cat(&Path::new("a/c/b.txt")) { |
| Err(why) => println!("! {:?}", why.kind()), |
| Ok(s) => println!("> {}", s), |
| } |
| |
| println!("`ls a`"); |
| // Read the contents of a directory, returns `io::Result<Vec<Path>>` |
| match fs::read_dir("a") { |
| Err(why) => println!("! {:?}", why.kind()), |
| Ok(paths) => for path in paths { |
| println!("> {:?}", path.unwrap().path()); |
| }, |
| } |
| |
| println!("`rm a/c/e.txt`"); |
| // Remove a file, returns `io::Result<()>` |
| fs::remove_file("a/c/e.txt").unwrap_or_else(|why| { |
| println!("! {:?}", why.kind()); |
| }); |
| |
| println!("`rmdir a/c/d`"); |
| // Remove an empty directory, returns `io::Result<()>` |
| fs::remove_dir("a/c/d").unwrap_or_else(|why| { |
| println!("! {:?}", why.kind()); |
| }); |
| } |
| |
| </code></pre> |
| <p>Here's the expected successful output:</p> |
| <pre><code class="language-shell">$ rustc fs.rs && ./fs |
| `mkdir a` |
| `echo hello > a/b.txt` |
| `mkdir -p a/c/d` |
| `touch a/c/e.txt` |
| `ln -s ../b.txt a/c/b.txt` |
| `cat a/c/b.txt` |
| > hello |
| `ls a` |
| > "a/b.txt" |
| > "a/c" |
| `rm a/c/e.txt` |
| `rmdir a/c/d` |
| </code></pre> |
| <p>And the final state of the <code>a</code> directory is:</p> |
| <pre><code class="language-shell">$ tree a |
| a |
| |-- b.txt |
| `-- c |
| `-- b.txt -> ../b.txt |
| |
| 1 directory, 2 files |
| </code></pre> |
| <p>An alternative way to define the function <code>cat</code> is with <code>?</code> notation:</p> |
| <pre><code class="language-rust ignore">fn cat(path: &Path) -> io::Result<String> { |
| let mut f = File::open(path)?; |
| let mut s = String::new(); |
| f.read_to_string(&mut s)?; |
| Ok(s) |
| } |
| </code></pre> |
| <h3 id="see-also-71"><a class="header" href="#see-also-71">See also:</a></h3> |
| <p><a href="std_misc/../attribute/cfg.html"><code>cfg!</code></a></p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="program-arguments"><a class="header" href="#program-arguments">Program arguments</a></h1> |
| <h2 id="standard-library"><a class="header" href="#standard-library">Standard Library</a></h2> |
| <p>The command line arguments can be accessed using <code>std::env::args</code>, which |
| returns an iterator that yields a <code>String</code> for each argument:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::env; |
| |
| fn main() { |
| let args: Vec<String> = env::args().collect(); |
| |
| // The first argument is the path that was used to call the program. |
| println!("My path is {}.", args[0]); |
| |
| // The rest of the arguments are the passed command line parameters. |
| // Call the program like this: |
| // $ ./args arg1 arg2 |
| println!("I got {:?} arguments: {:?}.", args.len() - 1, &args[1..]); |
| } |
| </code></pre></pre> |
| <pre><code class="language-shell">$ ./args 1 2 3 |
| My path is ./args. |
| I got 3 arguments: ["1", "2", "3"]. |
| </code></pre> |
| <h2 id="crates-2"><a class="header" href="#crates-2">Crates</a></h2> |
| <p>Alternatively, there are numerous crates that can provide extra functionality |
| when creating command-line applications. The <a href="https://rust-lang-nursery.github.io/rust-cookbook/cli/arguments.html">Rust Cookbook</a> exhibits best |
| practices on how to use one of the more popular command line argument crates, |
| <code>clap</code>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="argument-parsing"><a class="header" href="#argument-parsing">Argument parsing</a></h1> |
| <p>Matching can be used to parse simple arguments:</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::env; |
| |
| fn increase(number: i32) { |
| println!("{}", number + 1); |
| } |
| |
| fn decrease(number: i32) { |
| println!("{}", number - 1); |
| } |
| |
| fn help() { |
| println!("usage: |
| match_args <string> |
| Check whether given string is the answer. |
| match_args {{increase|decrease}} <integer> |
| Increase or decrease given integer by one."); |
| } |
| |
| fn main() { |
| let args: Vec<String> = env::args().collect(); |
| |
| match args.len() { |
| // no arguments passed |
| 1 => { |
| println!("My name is 'match_args'. Try passing some arguments!"); |
| }, |
| // one argument passed |
| 2 => { |
| match args[1].parse() { |
| Ok(42) => println!("This is the answer!"), |
| _ => println!("This is not the answer."), |
| } |
| }, |
| // one command and one argument passed |
| 3 => { |
| let cmd = &args[1]; |
| let num = &args[2]; |
| // parse the number |
| let number: i32 = match num.parse() { |
| Ok(n) => { |
| n |
| }, |
| Err(_) => { |
| eprintln!("error: second argument not an integer"); |
| help(); |
| return; |
| }, |
| }; |
| // parse the command |
| match &cmd[..] { |
| "increase" => increase(number), |
| "decrease" => decrease(number), |
| _ => { |
| eprintln!("error: invalid command"); |
| help(); |
| }, |
| } |
| }, |
| // all the other cases |
| _ => { |
| // show a help message |
| help(); |
| } |
| } |
| } |
| </code></pre></pre> |
| <pre><code class="language-shell">$ ./match_args Rust |
| This is not the answer. |
| $ ./match_args 42 |
| This is the answer! |
| $ ./match_args do something |
| error: second argument not an integer |
| usage: |
| match_args <string> |
| Check whether given string is the answer. |
| match_args {increase|decrease} <integer> |
| Increase or decrease given integer by one. |
| $ ./match_args do 42 |
| error: invalid command |
| usage: |
| match_args <string> |
| Check whether given string is the answer. |
| match_args {increase|decrease} <integer> |
| Increase or decrease given integer by one. |
| $ ./match_args increase 42 |
| 43 |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="foreign-function-interface"><a class="header" href="#foreign-function-interface">Foreign Function Interface</a></h1> |
| <p>Rust provides a Foreign Function Interface (FFI) to C libraries. Foreign |
| functions must be declared inside an <code>extern</code> block annotated with a <code>#[link]</code> |
| attribute containing the name of the foreign library.</p> |
| <pre><code class="language-rust ignore">use std::fmt; |
| |
| // this extern block links to the libm library |
| #[link(name = "m")] |
| extern { |
| // this is a foreign function |
| // that computes the square root of a single precision complex number |
| fn csqrtf(z: Complex) -> Complex; |
| |
| fn ccosf(z: Complex) -> Complex; |
| } |
| |
| // Since calling foreign functions is considered unsafe, |
| // it's common to write safe wrappers around them. |
| fn cos(z: Complex) -> Complex { |
| unsafe { ccosf(z) } |
| } |
| |
| fn main() { |
| // z = -1 + 0i |
| let z = Complex { re: -1., im: 0. }; |
| |
| // calling a foreign function is an unsafe operation |
| let z_sqrt = unsafe { csqrtf(z) }; |
| |
| println!("the square root of {:?} is {:?}", z, z_sqrt); |
| |
| // calling safe API wrapped around unsafe operation |
| println!("cos({:?}) = {:?}", z, cos(z)); |
| } |
| |
| // Minimal implementation of single precision complex numbers |
| #[repr(C)] |
| #[derive(Clone, Copy)] |
| struct Complex { |
| re: f32, |
| im: f32, |
| } |
| |
| impl fmt::Debug for Complex { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| if self.im < 0. { |
| write!(f, "{}-{}i", self.re, -self.im) |
| } else { |
| write!(f, "{}+{}i", self.re, self.im) |
| } |
| } |
| } |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="testing-1"><a class="header" href="#testing-1">Testing</a></h1> |
| <p>Rust is a programming language that cares a lot about correctness and it |
| includes support for writing software tests within the language itself.</p> |
| <p>Testing comes in three styles:</p> |
| <ul> |
| <li><a href="testing/unit_testing.html">Unit</a> testing.</li> |
| <li><a href="testing/doc_testing.html">Doc</a> testing.</li> |
| <li><a href="testing/integration_testing.html">Integration</a> testing.</li> |
| </ul> |
| <p>Also Rust has support for specifying additional dependencies for tests:</p> |
| <ul> |
| <li><a href="testing/dev_dependencies.html">Dev-dependencies</a></li> |
| </ul> |
| <h2 id="see-also-72"><a class="header" href="#see-also-72">See Also</a></h2> |
| <ul> |
| <li><a href="https://doc.rust-lang.org/book/ch11-00-testing.html">The Book</a> chapter on testing</li> |
| <li><a href="https://rust-lang-nursery.github.io/api-guidelines/documentation.html">API Guidelines</a> on doc-testing</li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="unit-testing"><a class="header" href="#unit-testing">Unit testing</a></h1> |
| <p>Tests are Rust functions that verify that the non-test code is functioning in |
| the expected manner. The bodies of test functions typically perform some setup, |
| run the code we want to test, then assert whether the results are what we |
| expect.</p> |
| <p>Most unit tests go into a <code>tests</code> <a href="testing/../mod.html">mod</a> with the <code>#[cfg(test)]</code> <a href="testing/../attribute.html">attribute</a>. |
| Test functions are marked with the <code>#[test]</code> attribute.</p> |
| <p>Tests fail when something in the test function <a href="testing/../std/panic.html">panics</a>. There are some |
| helper <a href="testing/../macros.html">macros</a>:</p> |
| <ul> |
| <li><code>assert!(expression)</code> - panics if expression evaluates to <code>false</code>.</li> |
| <li><code>assert_eq!(left, right)</code> and <code>assert_ne!(left, right)</code> - testing left and |
| right expressions for equality and inequality respectively.</li> |
| </ul> |
| <pre><code class="language-rust ignore">pub fn add(a: i32, b: i32) -> i32 { |
| a + b |
| } |
| |
| // This is a really bad adding function, its purpose is to fail in this |
| // example. |
| #[allow(dead_code)] |
| fn bad_add(a: i32, b: i32) -> i32 { |
| a - b |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| // Note this useful idiom: importing names from outer (for mod tests) scope. |
| use super::*; |
| |
| #[test] |
| fn test_add() { |
| assert_eq!(add(1, 2), 3); |
| } |
| |
| #[test] |
| fn test_bad_add() { |
| // This assert would fire and test will fail. |
| // Please note, that private functions can be tested too! |
| assert_eq!(bad_add(1, 2), 3); |
| } |
| } |
| </code></pre> |
| <p>Tests can be run with <code>cargo test</code>.</p> |
| <pre><code class="language-shell">$ cargo test |
| |
| running 2 tests |
| test tests::test_bad_add ... FAILED |
| test tests::test_add ... ok |
| |
| failures: |
| |
| ---- tests::test_bad_add stdout ---- |
| thread 'tests::test_bad_add' panicked at 'assertion failed: `(left == right)` |
| left: `-1`, |
| right: `3`', src/lib.rs:21:8 |
| note: Run with `RUST_BACKTRACE=1` for a backtrace. |
| |
| |
| failures: |
| tests::test_bad_add |
| |
| test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out |
| </code></pre> |
| <h2 id="tests-and-"><a class="header" href="#tests-and-">Tests and <code>?</code></a></h2> |
| <p>None of the previous unit test examples had a return type. But in Rust 2018, |
| your unit tests can return <code>Result<()></code>, which lets you use <code>?</code> in them! This |
| can make them much more concise.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn sqrt(number: f64) -> Result<f64, String> { |
| if number >= 0.0 { |
| Ok(number.powf(0.5)) |
| } else { |
| Err("negative floats don't have square roots".to_owned()) |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn test_sqrt() -> Result<(), String> { |
| let x = 4.0; |
| assert_eq!(sqrt(x)?.powf(2.0), x); |
| Ok(()) |
| } |
| } |
| </code></pre></pre> |
| <p>See <a href="https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/question-mark-in-main-and-tests.html">"The Edition Guide"</a> for more details.</p> |
| <h2 id="testing-panics"><a class="header" href="#testing-panics">Testing panics</a></h2> |
| <p>To check functions that should panic under certain circumstances, use attribute |
| <code>#[should_panic]</code>. This attribute accepts optional parameter <code>expected = </code> with |
| the text of the panic message. If your function can panic in multiple ways, it helps |
| make sure your test is testing the correct panic.</p> |
| <pre><code class="language-rust ignore">pub fn divide_non_zero_result(a: u32, b: u32) -> u32 { |
| if b == 0 { |
| panic!("Divide-by-zero error"); |
| } else if a < b { |
| panic!("Divide result is zero"); |
| } |
| a / b |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn test_divide() { |
| assert_eq!(divide_non_zero_result(10, 2), 5); |
| } |
| |
| #[test] |
| #[should_panic] |
| fn test_any_panic() { |
| divide_non_zero_result(1, 0); |
| } |
| |
| #[test] |
| #[should_panic(expected = "Divide result is zero")] |
| fn test_specific_panic() { |
| divide_non_zero_result(1, 10); |
| } |
| } |
| </code></pre> |
| <p>Running these tests gives us:</p> |
| <pre><code class="language-shell">$ cargo test |
| |
| running 3 tests |
| test tests::test_any_panic ... ok |
| test tests::test_divide ... ok |
| test tests::test_specific_panic ... ok |
| |
| test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| |
| Doc-tests tmp-test-should-panic |
| |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| </code></pre> |
| <h2 id="running-specific-tests"><a class="header" href="#running-specific-tests">Running specific tests</a></h2> |
| <p>To run specific tests one may specify the test name to <code>cargo test</code> command.</p> |
| <pre><code class="language-shell">$ cargo test test_any_panic |
| running 1 test |
| test tests::test_any_panic ... ok |
| |
| test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out |
| |
| Doc-tests tmp-test-should-panic |
| |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| </code></pre> |
| <p>To run multiple tests one may specify part of a test name that matches all the |
| tests that should be run.</p> |
| <pre><code class="language-shell">$ cargo test panic |
| running 2 tests |
| test tests::test_any_panic ... ok |
| test tests::test_specific_panic ... ok |
| |
| test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out |
| |
| Doc-tests tmp-test-should-panic |
| |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| </code></pre> |
| <h2 id="ignoring-tests"><a class="header" href="#ignoring-tests">Ignoring tests</a></h2> |
| <p>Tests can be marked with the <code>#[ignore]</code> attribute to exclude some tests. Or to run |
| them with command <code>cargo test -- --ignored</code></p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>pub fn add(a: i32, b: i32) -> i32 { |
| a + b |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn test_add() { |
| assert_eq!(add(2, 2), 4); |
| } |
| |
| #[test] |
| fn test_add_hundred() { |
| assert_eq!(add(100, 2), 102); |
| assert_eq!(add(2, 100), 102); |
| } |
| |
| #[test] |
| #[ignore] |
| fn ignored_test() { |
| assert_eq!(add(0, 0), 0); |
| } |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <pre><code class="language-shell">$ cargo test |
| running 3 tests |
| test tests::ignored_test ... ignored |
| test tests::test_add ... ok |
| test tests::test_add_hundred ... ok |
| |
| test result: ok. 2 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out |
| |
| Doc-tests tmp-ignore |
| |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| |
| $ cargo test -- --ignored |
| running 1 test |
| test tests::ignored_test ... ok |
| |
| test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| |
| Doc-tests tmp-ignore |
| |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="documentation-testing"><a class="header" href="#documentation-testing">Documentation testing</a></h1> |
| <p>The primary way of documenting a Rust project is through annotating the source |
| code. Documentation comments are written in <a href="https://daringfireball.net/projects/markdown/">markdown</a> and support code |
| blocks in them. Rust takes care about correctness, so these code blocks are |
| compiled and used as tests.</p> |
| <pre><code class="language-rust ignore">/// First line is a short summary describing function. |
| /// |
| /// The next lines present detailed documentation. Code blocks start with |
| /// triple backquotes and have implicit `fn main()` inside |
| /// and `extern crate <cratename>`. Assume we're testing `doccomments` crate: |
| /// |
| /// ``` |
| /// let result = doccomments::add(2, 3); |
| /// assert_eq!(result, 5); |
| /// ``` |
| pub fn add(a: i32, b: i32) -> i32 { |
| a + b |
| } |
| |
| /// Usually doc comments may include sections "Examples", "Panics" and "Failures". |
| /// |
| /// The next function divides two numbers. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// let result = doccomments::div(10, 2); |
| /// assert_eq!(result, 5); |
| /// ``` |
| /// |
| /// # Panics |
| /// |
| /// The function panics if the second argument is zero. |
| /// |
| /// ```rust,should_panic |
| /// // panics on division by zero |
| /// doccomments::div(10, 0); |
| /// ``` |
| pub fn div(a: i32, b: i32) -> i32 { |
| if b == 0 { |
| panic!("Divide-by-zero error"); |
| } |
| |
| a / b |
| } |
| </code></pre> |
| <p>Tests can be run with <code>cargo test</code>:</p> |
| <pre><code class="language-shell">$ cargo test |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| |
| Doc-tests doccomments |
| |
| running 3 tests |
| test src/lib.rs - add (line 7) ... ok |
| test src/lib.rs - div (line 21) ... ok |
| test src/lib.rs - div (line 31) ... ok |
| |
| test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| </code></pre> |
| <h2 id="motivation-behind-documentation-tests"><a class="header" href="#motivation-behind-documentation-tests">Motivation behind documentation tests</a></h2> |
| <p>The main purpose of documentation tests is to serve as examples that exercise |
| the functionality, which is one of the most important |
| <a href="https://rust-lang-nursery.github.io/api-guidelines/documentation.html#examples-use--not-try-not-unwrap-c-question-mark">guidelines</a>. It allows using examples from docs as |
| complete code snippets. But using <code>?</code> makes compilation fail since <code>main</code> |
| returns <code>unit</code>. The ability to hide some source lines from documentation comes |
| to the rescue: one may write <code>fn try_main() -> Result<(), ErrorType></code>, hide it and |
| <code>unwrap</code> it in hidden <code>main</code>. Sounds complicated? Here's an example:</p> |
| <pre><code class="language-rust ignore">/// Using hidden `try_main` in doc tests. |
| /// |
| /// ``` |
| /// # // hidden lines start with `#` symbol, but they're still compileable! |
| /// # fn try_main() -> Result<(), String> { // line that wraps the body shown in doc |
| /// let res = try::try_div(10, 2)?; |
| /// # Ok(()) // returning from try_main |
| /// # } |
| /// # fn main() { // starting main that'll unwrap() |
| /// # try_main().unwrap(); // calling try_main and unwrapping |
| /// # // so that test will panic in case of error |
| /// # } |
| /// ``` |
| pub fn try_div(a: i32, b: i32) -> Result<i32, String> { |
| if b == 0 { |
| Err(String::from("Divide-by-zero")) |
| } else { |
| Ok(a / b) |
| } |
| } |
| </code></pre> |
| <h2 id="see-also-73"><a class="header" href="#see-also-73">See Also</a></h2> |
| <ul> |
| <li><a href="https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md">RFC505</a> on documentation style</li> |
| <li><a href="https://rust-lang-nursery.github.io/api-guidelines/documentation.html">API Guidelines</a> on documentation guidelines</li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="integration-testing"><a class="header" href="#integration-testing">Integration testing</a></h1> |
| <p><a href="testing/unit_testing.html">Unit tests</a> are testing one module in isolation at a time: they're small |
| and can test private code. Integration tests are external to your crate and use |
| only its public interface in the same way any other code would. Their purpose is |
| to test that many parts of your library work correctly together.</p> |
| <p>Cargo looks for integration tests in <code>tests</code> directory next to <code>src</code>.</p> |
| <p>File <code>src/lib.rs</code>:</p> |
| <pre><code class="language-rust ignore">// Define this in a crate called `adder`. |
| pub fn add(a: i32, b: i32) -> i32 { |
| a + b |
| } |
| </code></pre> |
| <p>File with test: <code>tests/integration_test.rs</code>:</p> |
| <pre><code class="language-rust ignore">#[test] |
| fn test_add() { |
| assert_eq!(adder::add(3, 2), 5); |
| } |
| </code></pre> |
| <p>Running tests with <code>cargo test</code> command:</p> |
| <pre><code class="language-shell">$ cargo test |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| |
| Running target/debug/deps/integration_test-bcd60824f5fbfe19 |
| |
| running 1 test |
| test test_add ... ok |
| |
| test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| |
| Doc-tests adder |
| |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out |
| </code></pre> |
| <p>Each Rust source file in the <code>tests</code> directory is compiled as a separate crate. One |
| way of sharing some code between integration tests is making a module with public |
| functions, importing and using it within tests.</p> |
| <p>File <code>tests/common.rs</code>:</p> |
| <pre><code class="language-rust ignore">pub fn setup() { |
| // some setup code, like creating required files/directories, starting |
| // servers, etc. |
| } |
| </code></pre> |
| <p>File with test: <code>tests/integration_test.rs</code></p> |
| <pre><code class="language-rust ignore">// importing common module. |
| mod common; |
| |
| #[test] |
| fn test_add() { |
| // using common code. |
| common::setup(); |
| assert_eq!(adder::add(3, 2), 5); |
| } |
| </code></pre> |
| <p>Modules with common code follow the ordinary <a href="testing/../mod.html">modules</a> rules, so it's ok to |
| create common module as <code>tests/common/mod.rs</code>.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="development-dependencies"><a class="header" href="#development-dependencies">Development dependencies</a></h1> |
| <p>Sometimes there is a need to have dependencies for tests (or examples, |
| or benchmarks) only. Such dependencies are added to <code>Cargo.toml</code> in the |
| <code>[dev-dependencies]</code> section. These dependencies are not propagated to other |
| packages which depend on this package.</p> |
| <p>One such example is using a crate that extends standard <code>assert!</code> macros.<br /> |
| File <code>Cargo.toml</code>:</p> |
| <pre><code class="language-toml"># standard crate data is left out |
| [dev-dependencies] |
| pretty_assertions = "0.4.0" |
| </code></pre> |
| <p>File <code>src/lib.rs</code>:</p> |
| <pre><code class="language-rust ignore">// externing crate for test-only use |
| #[cfg(test)] |
| #[macro_use] |
| extern crate pretty_assertions; |
| |
| pub fn add(a: i32, b: i32) -> i32 { |
| a + b |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn test_add() { |
| assert_eq!(add(2, 3), 5); |
| } |
| } |
| </code></pre> |
| <h2 id="see-also-74"><a class="header" href="#see-also-74">See Also</a></h2> |
| <p><a href="http://doc.crates.io/specifying-dependencies.html">Cargo</a> docs on specifying dependencies.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="unsafe-operations"><a class="header" href="#unsafe-operations">Unsafe Operations</a></h1> |
| <p>As an introduction to this section, to borrow from <a href="https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html">the official docs</a>, |
| "one should try to minimize the amount of unsafe code in a code base." With that |
| in mind, let's get started! Unsafe annotations in Rust are used to bypass |
| protections put in place by the compiler; specifically, there are four primary |
| things that unsafe is used for:</p> |
| <ul> |
| <li>dereferencing raw pointers</li> |
| <li>calling functions or methods which are <code>unsafe</code> (including calling a function |
| over FFI, see <a href="std_misc/ffi.html">a previous chapter</a> of the book) </li> |
| <li>accessing or modifying static mutable variables</li> |
| <li>implementing unsafe traits</li> |
| </ul> |
| <h3 id="raw-pointers"><a class="header" href="#raw-pointers">Raw Pointers</a></h3> |
| <p>Raw pointers <code>*</code> and references <code>&T</code> function similarly, but references are |
| always safe because they are guaranteed to point to valid data due to the |
| borrow checker. Dereferencing a raw pointer can only be done through an unsafe |
| block.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| let raw_p: *const u32 = &10; |
| |
| unsafe { |
| assert!(*raw_p == 10); |
| } |
| } |
| </code></pre></pre> |
| <h3 id="calling-unsafe-functions"><a class="header" href="#calling-unsafe-functions">Calling Unsafe Functions</a></h3> |
| <p>Some functions can be declared as <code>unsafe</code>, meaning it is the programmer's |
| responsibility to ensure correctness instead of the compiler's. One example |
| of this is <a href="https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html"><code>std::slice::from_raw_parts</code></a> which will create a slice given a |
| pointer to the first element and a length.</p> |
| <pre><pre class="playground"><code class="language-rust editable">use std::slice; |
| |
| fn main() { |
| let some_vector = vec![1, 2, 3, 4]; |
| |
| let pointer = some_vector.as_ptr(); |
| let length = some_vector.len(); |
| |
| unsafe { |
| let my_slice: &[u32] = slice::from_raw_parts(pointer, length); |
| |
| assert_eq!(some_vector.as_slice(), my_slice); |
| } |
| } |
| </code></pre></pre> |
| <p>For <code>slice::from_raw_parts</code>, one of the assumptions which <em>must</em> be upheld is |
| that the pointer passed in points to valid memory and that the memory pointed to |
| is of the correct type. If these invariants aren't upheld then the program's |
| behaviour is undefined and there is no knowing what will happen.</p> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="compatibility"><a class="header" href="#compatibility">Compatibility</a></h1> |
| <p>The Rust language is fastly evolving, and because of this certain compatibility |
| issues can arise, despite efforts to ensure forwards-compatibility wherever |
| possible.</p> |
| <ul> |
| <li><a href="compatibility/raw_identifiers.html">Raw identifiers</a></li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="raw-identifiers"><a class="header" href="#raw-identifiers">Raw identifiers</a></h1> |
| <p>Rust, like many programming languages, has the concept of "keywords". |
| These identifiers mean something to the language, and so you cannot use them in |
| places like variable names, function names, and other places. |
| Raw identifiers let you use keywords where they would not normally be allowed. |
| This is particularly useful when Rust introduces new keywords, and a library |
| using an older edition of Rust has a variable or function with the same name |
| as a keyword introduced in a newer edition.</p> |
| <p>For example, consider a crate <code>foo</code> compiled with the 2015 edition of Rust that |
| exports a function named <code>try</code>. This keyword is reserved for a new feature in |
| the 2018 edition, so without raw identifiers, we would have no way to name the |
| function.</p> |
| <pre><code class="language-rust ignore">extern crate foo; |
| |
| fn main() { |
| foo::try(); |
| } |
| </code></pre> |
| <p>You'll get this error:</p> |
| <pre><code class="language-text">error: expected identifier, found keyword `try` |
| --> src/main.rs:4:4 |
| | |
| 4 | foo::try(); |
| | ^^^ expected identifier, found keyword |
| </code></pre> |
| <p>You can write this with a raw identifier:</p> |
| <pre><code class="language-rust ignore">extern crate foo; |
| |
| fn main() { |
| foo::r#try(); |
| } |
| </code></pre> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="meta"><a class="header" href="#meta">Meta</a></h1> |
| <p>Some topics aren't exactly relevant to how you program but provide you |
| tooling or infrastructure support which just makes things better for |
| everyone. These topics include:</p> |
| <ul> |
| <li><a href="meta/doc.html">Documentation</a>: Generate library documentation for users via the included |
| <code>rustdoc</code>.</li> |
| <li><a href="meta/playpen.html">Playpen</a>: Integrate the Rust Playpen(also known as the Rust Playground) in your documentation.</li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="documentation"><a class="header" href="#documentation">Documentation</a></h1> |
| <p>Use <code>cargo doc</code> to build documentation in <code>target/doc</code>.</p> |
| <p>Use <code>cargo test</code> to run all tests (including documentation tests), and <code>cargo test --doc</code> to only run documentation tests.</p> |
| <p>These commands will appropriately invoke <code>rustdoc</code> (and <code>rustc</code>) as required.</p> |
| <h2 id="doc-comments"><a class="header" href="#doc-comments">Doc comments</a></h2> |
| <p>Doc comments are very useful for big projects that require documentation. When |
| running <code>rustdoc</code>, these are the comments that get compiled into |
| documentation. They are denoted by a <code>///</code>, and support <a href="https://en.wikipedia.org/wiki/Markdown">Markdown</a>.</p> |
| <pre><code class="language-rust editable ignore">#![crate_name = "doc"] |
| |
| /// A human being is represented here |
| pub struct Person { |
| /// A person must have a name, no matter how much Juliet may hate it |
| name: String, |
| } |
| |
| impl Person { |
| /// Returns a person with the name given them |
| /// |
| /// # Arguments |
| /// |
| /// * `name` - A string slice that holds the name of the person |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// // You can have rust code between fences inside the comments |
| /// // If you pass --test to `rustdoc`, it will even test it for you! |
| /// use doc::Person; |
| /// let person = Person::new("name"); |
| /// ``` |
| pub fn new(name: &str) -> Person { |
| Person { |
| name: name.to_string(), |
| } |
| } |
| |
| /// Gives a friendly hello! |
| /// |
| /// Says "Hello, [name]" to the `Person` it is called on. |
| pub fn hello(& self) { |
| println!("Hello, {}!", self.name); |
| } |
| } |
| |
| fn main() { |
| let john = Person::new("John"); |
| |
| john.hello(); |
| } |
| </code></pre> |
| <p>To run the tests, first build the code as a library, then tell <code>rustdoc</code> where |
| to find the library so it can link it into each doctest program:</p> |
| <pre><code class="language-shell">$ rustc doc.rs --crate-type lib |
| $ rustdoc --test --extern doc="libdoc.rlib" doc.rs |
| </code></pre> |
| <h2 id="doc-attributes"><a class="header" href="#doc-attributes">Doc attributes</a></h2> |
| <p>Below are a few examples of the most common <code>#[doc]</code> attributes used with <code>rustdoc</code>.</p> |
| <h3 id="inline"><a class="header" href="#inline"><code>inline</code></a></h3> |
| <p>Used to inline docs, instead of linking out to separate page.</p> |
| <pre><code class="language-rust ignore">#[doc(inline)] |
| pub use bar::Bar; |
| |
| /// bar docs |
| mod bar { |
| /// the docs for Bar |
| pub struct Bar; |
| } |
| </code></pre> |
| <h3 id="no_inline"><a class="header" href="#no_inline"><code>no_inline</code></a></h3> |
| <p>Used to prevent linking out to separate page or anywhere.</p> |
| <pre><code class="language-rust ignore">// Example from libcore/prelude |
| #[doc(no_inline)] |
| pub use crate::mem::drop; |
| </code></pre> |
| <h3 id="hidden"><a class="header" href="#hidden"><code>hidden</code></a></h3> |
| <p>Using this tells <code>rustdoc</code> not to include this in documentation:</p> |
| <pre><code class="language-rust editable ignore">// Example from the futures-rs library |
| #[doc(hidden)] |
| pub use self::async_await::*; |
| </code></pre> |
| <p>For documentation, <code>rustdoc</code> is widely used by the community. It's what is used to generate the <a href="https://doc.rust-lang.org/std/">std library docs</a>.</p> |
| <h3 id="see-also-75"><a class="header" href="#see-also-75">See also:</a></h3> |
| <ul> |
| <li><a href="https://doc.rust-lang.org/book/ch14-02-publishing-to-crates-io.html#making-useful-documentation-comments">The Rust Book: Making Useful Documentation Comments</a></li> |
| <li><a href="https://doc.rust-lang.org/rustdoc/index.html">The rustdoc Book</a></li> |
| <li><a href="https://doc.rust-lang.org/stable/reference/comments.html#doc-comments">The Reference: Doc comments</a></li> |
| <li><a href="https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text">RFC 1574: API Documentation Conventions</a></li> |
| <li><a href="https://rust-lang.github.io/rfcs/1946-intra-rustdoc-links.html">RFC 1946: Relative links to other items from doc comments (intra-rustdoc links)</a></li> |
| <li><a href="https://www.reddit.com/r/rust/comments/ahb50s/is_there_any_documentation_style_guide_for/">Is there any documentation style guide for comments? (reddit)</a></li> |
| </ul> |
| <div style="break-before: page; page-break-before: always;"></div><h1 id="playpen"><a class="header" href="#playpen">Playpen</a></h1> |
| <p>The <a href="https://github.com/rust-lang/rust-playpen">Rust Playpen</a> is a way to experiment with Rust code through a web interface. This project is now commonly referred to as <a href="https://play.rust-lang.org/">Rust Playground</a>.</p> |
| <h2 id="using-it-with-mdbook"><a class="header" href="#using-it-with-mdbook">Using it with <code>mdbook</code></a></h2> |
| <p>In <a href="https://github.com/rust-lang/mdBook"><code>mdbook</code></a>, you can make code examples playable and editable.</p> |
| <pre><pre class="playground"><code class="language-rust editable">fn main() { |
| println!("Hello World!"); |
| } |
| </code></pre></pre> |
| <p>This allows the reader to both run your code sample, but also modify and tweak it. The key here is the adding the word <code>editable</code> to your codefence block separated by a comma.</p> |
| <pre><code class="language-markdown">```rust,editable |
| //...place your code here |
| ``` |
| </code></pre> |
| <p>Additionally, you can add <code>ignore</code> if you want <code>mdbook</code> to skip your code when it builds and tests.</p> |
| <pre><code class="language-markdown">```rust,editable,ignore |
| //...place your code here |
| ``` |
| </code></pre> |
| <h2 id="using-it-with-docs"><a class="header" href="#using-it-with-docs">Using it with docs</a></h2> |
| <p>You may have noticed in some of the <a href="https://doc.rust-lang.org/core/">official Rust docs</a> a button that says "Run", which opens the code sample up in a new tab in Rust Playground. This feature is enabled if you use the #[doc] attribute called <a href="https://doc.rust-lang.org/rustdoc/the-doc-attribute.html#html_playground_url"><code>html_playground_url</code></a>.</p> |
| <h3 id="see-also-76"><a class="header" href="#see-also-76">See also:</a></h3> |
| <ul> |
| <li><a href="https://play.rust-lang.org/">The Rust Playground</a></li> |
| <li><a href="https://github.com/integer32llc/rust-playground/">The next-gen playpen</a></li> |
| <li><a href="https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html">The rustdoc Book</a></li> |
| </ul> |
| |
| </main> |
| |
| <nav class="nav-wrapper" aria-label="Page navigation"> |
| <!-- Mobile navigation buttons --> |
| <div style="clear: both"></div> |
| </nav> |
| </div> |
| </div> |
| |
| <nav class="nav-wide-wrapper" aria-label="Page navigation"> |
| </nav> |
| |
| </div> |
| |
| <script type="text/javascript"> |
| window.playground_copyable = true; |
| </script> |
| <script src="ace.js" type="text/javascript" charset="utf-8"></script> |
| <script src="editor.js" type="text/javascript" charset="utf-8"></script> |
| <script src="mode-rust.js" type="text/javascript" charset="utf-8"></script> |
| <script src="theme-dawn.js" type="text/javascript" charset="utf-8"></script> |
| <script src="theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script> |
| <script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script> |
| <script src="mark.min.js" type="text/javascript" charset="utf-8"></script> |
| <script src="searcher.js" type="text/javascript" charset="utf-8"></script> |
| <script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script> |
| <script src="highlight.js" type="text/javascript" charset="utf-8"></script> |
| <script src="book.js" type="text/javascript" charset="utf-8"></script> |
| |
| <!-- Custom JS scripts --> |
| <script type="text/javascript"> |
| window.addEventListener('load', function() { |
| window.setTimeout(window.print, 100); |
| }); |
| </script> |
| </body> |
| </html> |