Files
docs-rust/build/ch06-02-match.html
2026-06-22 21:17:36 +05:30

605 lines
42 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE HTML>
<html lang="en" class="light sidebar-visible" dir="ltr">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>The match Control Flow Construct - The Rust Programming Language</title>
<!-- Custom HTML head -->
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="favicon-de23e50b.svg">
<link rel="shortcut icon" href="favicon-8114d1fc.png">
<link rel="stylesheet" href="css/variables-8adf115d.css">
<link rel="stylesheet" href="css/general-0392ca55.css">
<link rel="stylesheet" href="css/chrome-fc474251.css">
<link rel="stylesheet" href="css/print-9e4910d8.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="fonts/fonts-9644e21d.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" id="mdbook-highlight-css" href="highlight-493f70e1.css">
<link rel="stylesheet" id="mdbook-tomorrow-night-css" href="tomorrow-night-4c0ae647.css">
<link rel="stylesheet" id="mdbook-ayu-highlight-css" href="ayu-highlight-3fdfc3ac.css">
<!-- Custom theme stylesheets -->
<link rel="stylesheet" href="ferris-d33b75bf.css">
<link rel="stylesheet" href="theme/2018-edition-4e126c62.css">
<link rel="stylesheet" href="theme/semantic-notes-9b5766c0.css">
<link rel="stylesheet" href="theme/listing-cab26221.css">
<!-- Provide site root and default themes to javascript -->
<script>
const path_to_root = "";
const default_light_theme = "light";
const default_dark_theme = "navy";
window.path_to_searchindex_js = "searchindex-6a1da8cc.js";
</script>
<!-- Start loading toc.js asap -->
<script src="toc-0e4ce700.js"></script>
</head>
<body>
<div id="mdbook-help-container">
<div id="mdbook-help-popup">
<h2 class="mdbook-help-title">Keyboard shortcuts</h2>
<div>
<p>Press <kbd></kbd> or <kbd></kbd> to navigate between chapters</p>
<p>Press <kbd>S</kbd> or <kbd>/</kbd> to search in the book</p>
<p>Press <kbd>?</kbd> to show this help</p>
<p>Press <kbd>Esc</kbd> to hide this help</p>
</div>
</div>
</div>
<div id="mdbook-body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script>
try {
let theme = localStorage.getItem('mdbook-theme');
let 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>
const default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? default_dark_theme : default_light_theme;
let theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
const html = document.documentElement;
html.classList.remove('light')
html.classList.add(theme);
html.classList.add("js");
</script>
<input type="checkbox" id="mdbook-sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed -->
<script>
let sidebar = null;
const sidebar_toggle = document.getElementById("mdbook-sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
sidebar_toggle.checked = false;
}
if (sidebar === 'visible') {
sidebar_toggle.checked = true;
} else {
html.classList.remove('sidebar-visible');
}
</script>
<nav id="mdbook-sidebar" class="sidebar" aria-label="Table of contents">
<!-- populated by js -->
<mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="toc.html"></iframe>
</noscript>
<div id="mdbook-sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div>
</nav>
<div id="mdbook-page-wrapper" class="page-wrapper">
<div class="page">
<div id="mdbook-menu-bar-hover-placeholder"></div>
<div id="mdbook-menu-bar" class="menu-bar sticky">
<div class="left-buttons">
<label id="mdbook-sidebar-toggle" class="icon-button" for="mdbook-sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="mdbook-sidebar">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg></span>
</label>
<button id="mdbook-theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="mdbook-theme-list">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M371.3 367.1c27.3-3.9 51.9-19.4 67.2-42.9L600.2 74.1c12.6-19.5 9.4-45.3-7.6-61.2S549.7-4.4 531.1 9.6L294.4 187.2c-24 18-38.2 46.1-38.4 76.1L371.3 367.1zm-19.6 25.4l-116-104.4C175.9 290.3 128 339.6 128 400c0 3.9 .2 7.8 .6 11.6c1.8 17.5-10.2 36.4-27.8 36.4H96c-17.7 0-32 14.3-32 32s14.3 32 32 32H240c61.9 0 112-50.1 112-112c0-2.5-.1-5-.2-7.5z"/></svg></span>
</button>
<ul id="mdbook-theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-default_theme">Auto</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="mdbook-theme-ayu">Ayu</button></li>
</ul>
<button id="mdbook-search-toggle" class="icon-button" type="button" title="Search (`/`)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="/ s" aria-controls="mdbook-searchbar">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352c79.5 0 144-64.5 144-144s-64.5-144-144-144S64 128.5 64 208s64.5 144 144 144z"/></svg></span>
</button>
</div>
<h1 class="menu-title">The Rust Programming Language</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<span class=fa-svg id="print-button"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M128 0C92.7 0 64 28.7 64 64v96h64V64H354.7L384 93.3V160h64V93.3c0-17-6.7-33.3-18.7-45.3L400 18.7C388 6.7 371.7 0 354.7 0H128zM384 352v32 64H128V384 368 352H384zm64 32h32c17.7 0 32-14.3 32-32V256c0-35.3-28.7-64-64-64H64c-35.3 0-64 28.7-64 64v96c0 17.7 14.3 32 32 32H64v64c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V384zm-16-88c-13.3 0-24-10.7-24-24s10.7-24 24-24s24 10.7 24 24s-10.7 24-24 24z"/></svg></span>
</a>
<a href="https://github.com/rust-lang/book" title="Git repository" aria-label="Git repository">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg></span>
</a>
</div>
</div>
<div id="mdbook-search-wrapper" class="hidden">
<form id="mdbook-searchbar-outer" class="searchbar-outer">
<div class="search-wrapper">
<input type="search" id="mdbook-searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="mdbook-searchresults-outer" aria-describedby="searchresults-header">
<div class="spinner-wrapper">
<span class=fa-svg id="fa-spin"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M304 48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zm0 416c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM48 304c26.5 0 48-21.5 48-48s-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48zm464-48c0-26.5-21.5-48-48-48s-48 21.5-48 48s21.5 48 48 48s48-21.5 48-48zM142.9 437c18.7-18.7 18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zm0-294.2c18.7-18.7 18.7-49.1 0-67.9S93.7 56.2 75 75s-18.7 49.1 0 67.9s49.1 18.7 67.9 0zM369.1 437c18.7 18.7 49.1 18.7 67.9 0s18.7-49.1 0-67.9s-49.1-18.7-67.9 0s-18.7 49.1 0 67.9z"/></svg></span>
</div>
</div>
</form>
<div id="mdbook-searchresults-outer" class="searchresults-outer hidden">
<div id="mdbook-searchresults-header" class="searchresults-header"></div>
<ul id="mdbook-searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script>
document.getElementById('mdbook-sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('mdbook-sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#mdbook-sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="mdbook-content" class="content">
<main>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="the-match-control-flow-operator"></a></p>
<h2 id="the-match-control-flow-construct"><a class="header" href="#the-match-control-flow-construct">The <code>match</code> Control Flow Construct</a></h2>
<p>Rust has an extremely powerful control flow construct called <code>match</code> that
allows you to compare a value against a series of patterns and then execute
code based on which pattern matches. Patterns can be made up of literal values,
variable names, wildcards, and many other things; <a href="ch19-00-patterns.html">Chapter
19</a><!-- ignore --> covers all the different kinds of patterns
and what they do. The power of <code>match</code> comes from the expressiveness of the
patterns and the fact that the compiler confirms that all possible cases are
handled.</p>
<p>Think of a <code>match</code> expression as being like a coin-sorting machine: Coins slide
down a track with variously sized holes along it, and each coin falls through
the first hole it encounters that it fits into. In the same way, values go
through each pattern in a <code>match</code>, and at the first pattern the value “fits,”
the value falls into the associated code block to be used during execution.</p>
<p>Speaking of coins, lets use them as an example using <code>match</code>! We can write a
function that takes an unknown US coin and, in a similar way as the counting
machine, determines which coin it is and returns its value in cents, as shown
in Listing 6-3.</p>
<figure class="listing" id="listing-6-3">
<pre class="playground"><code class="language-rust edition2024">enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -&gt; u8 {
match coin {
Coin::Penny =&gt; 1,
Coin::Nickel =&gt; 5,
Coin::Dime =&gt; 10,
Coin::Quarter =&gt; 25,
}
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre>
<figcaption><a href="#listing-6-3">Listing 6-3</a>: An enum and a <code>match</code> expression that has the variants of the enum as its patterns</figcaption>
</figure>
<p>Lets break down the <code>match</code> in the <code>value_in_cents</code> function. First, we list
the <code>match</code> keyword followed by an expression, which in this case is the value
<code>coin</code>. This seems very similar to a conditional expression used with <code>if</code>, but
theres a big difference: With <code>if</code>, the condition needs to evaluate to a
Boolean value, but here it can be any type. The type of <code>coin</code> in this example
is the <code>Coin</code> enum that we defined on the first line.</p>
<p>Next are the <code>match</code> arms. An arm has two parts: a pattern and some code. The
first arm here has a pattern that is the value <code>Coin::Penny</code> and then the <code>=&gt;</code>
operator that separates the pattern and the code to run. The code in this case
is just the value <code>1</code>. Each arm is separated from the next with a comma.</p>
<p>When the <code>match</code> expression executes, it compares the resultant value against
the pattern of each arm, in order. If a pattern matches the value, the code
associated with that pattern is executed. If that pattern doesnt match the
value, execution continues to the next arm, much as in a coin-sorting machine.
We can have as many arms as we need: In Listing 6-3, our <code>match</code> has four arms.</p>
<p>The code associated with each arm is an expression, and the resultant value of
the expression in the matching arm is the value that gets returned for the
entire <code>match</code> expression.</p>
<p>We dont typically use curly brackets if the match arm code is short, as it is
in Listing 6-3 where each arm just returns a value. If you want to run multiple
lines of code in a match arm, you must use curly brackets, and the comma
following the arm is then optional. For example, the following code prints
“Lucky penny!” every time the method is called with a <code>Coin::Penny</code>, but it
still returns the last value of the block, <code>1</code>:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">enum Coin {
</span><span class="boring"> Penny,
</span><span class="boring"> Nickel,
</span><span class="boring"> Dime,
</span><span class="boring"> Quarter,
</span><span class="boring">}
</span><span class="boring">
</span>fn value_in_cents(coin: Coin) -&gt; u8 {
match coin {
Coin::Penny =&gt; {
println!("Lucky penny!");
1
}
Coin::Nickel =&gt; 5,
Coin::Dime =&gt; 10,
Coin::Quarter =&gt; 25,
}
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre>
<h3 id="patterns-that-bind-to-values"><a class="header" href="#patterns-that-bind-to-values">Patterns That Bind to Values</a></h3>
<p>Another useful feature of match arms is that they can bind to the parts of the
values that match the pattern. This is how we can extract values out of enum
variants.</p>
<p>As an example, lets change one of our enum variants to hold data inside it.
From 1999 through 2008, the United States minted quarters with different
designs for each of the 50 states on one side. No other coins got state
designs, so only quarters have this extra value. We can add this information to
our <code>enum</code> by changing the <code>Quarter</code> variant to include a <code>UsState</code> value
stored inside it, which weve done in Listing 6-4.</p>
<figure class="listing" id="listing-6-4">
<pre class="playground"><code class="language-rust edition2024">#[derive(Debug)] // so we can inspect the state in a minute
enum UsState {
Alabama,
Alaska,
// --snip--
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
<span class="boring">
</span><span class="boring">fn main() {}</span></code></pre>
<figcaption><a href="#listing-6-4">Listing 6-4</a>: A <code>Coin</code> enum in which the <code>Quarter</code> variant also holds a <code>UsState</code> value</figcaption>
</figure>
<p>Lets imagine that a friend is trying to collect all 50 state quarters. While
we sort our loose change by coin type, well also call out the name of the
state associated with each quarter so that if its one our friend doesnt have,
they can add it to their collection.</p>
<p>In the match expression for this code, we add a variable called <code>state</code> to the
pattern that matches values of the variant <code>Coin::Quarter</code>. When a
<code>Coin::Quarter</code> matches, the <code>state</code> variable will bind to the value of that
quarters state. Then, we can use <code>state</code> in the code for that arm, like so:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">#[derive(Debug)]
</span><span class="boring">enum UsState {
</span><span class="boring"> Alabama,
</span><span class="boring"> Alaska,
</span><span class="boring"> // --snip--
</span><span class="boring">}
</span><span class="boring">
</span><span class="boring">enum Coin {
</span><span class="boring"> Penny,
</span><span class="boring"> Nickel,
</span><span class="boring"> Dime,
</span><span class="boring"> Quarter(UsState),
</span><span class="boring">}
</span><span class="boring">
</span>fn value_in_cents(coin: Coin) -&gt; u8 {
match coin {
Coin::Penny =&gt; 1,
Coin::Nickel =&gt; 5,
Coin::Dime =&gt; 10,
Coin::Quarter(state) =&gt; {
println!("State quarter from {state:?}!");
25
}
}
}
<span class="boring">
</span><span class="boring">fn main() {
</span><span class="boring"> value_in_cents(Coin::Quarter(UsState::Alaska));
</span><span class="boring">}</span></code></pre>
<p>If we were to call <code>value_in_cents(Coin::Quarter(UsState::Alaska))</code>, <code>coin</code>
would be <code>Coin::Quarter(UsState::Alaska)</code>. When we compare that value with each
of the match arms, none of them match until we reach <code>Coin::Quarter(state)</code>. At
that point, the binding for <code>state</code> will be the value <code>UsState::Alaska</code>. We can
then use that binding in the <code>println!</code> expression, thus getting the inner
state value out of the <code>Coin</code> enum variant for <code>Quarter</code>.</p>
<!-- Old headings. Do not remove or links may break. -->
<p><a id="matching-with-optiont"></a></p>
<h3 id="the-optiont-match-pattern"><a class="header" href="#the-optiont-match-pattern">The <code>Option&lt;T&gt;</code> <code>match</code> Pattern</a></h3>
<p>In the previous section, we wanted to get the inner <code>T</code> value out of the <code>Some</code>
case when using <code>Option&lt;T&gt;</code>; we can also handle <code>Option&lt;T&gt;</code> using <code>match</code>, as
we did with the <code>Coin</code> enum! Instead of comparing coins, well compare the
variants of <code>Option&lt;T&gt;</code>, but the way the <code>match</code> expression works remains the
same.</p>
<p>Lets say we want to write a function that takes an <code>Option&lt;i32&gt;</code> and, if
theres a value inside, adds 1 to that value. If there isnt a value inside,
the function should return the <code>None</code> value and not attempt to perform any
operations.</p>
<p>This function is very easy to write, thanks to <code>match</code>, and will look like
Listing 6-5.</p>
<figure class="listing" id="listing-6-5">
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> fn plus_one(x: Option&lt;i32&gt;) -&gt; Option&lt;i32&gt; {
match x {
None =&gt; None,
Some(i) =&gt; Some(i + 1),
}
}
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
<span class="boring">}</span></code></pre>
<figcaption><a href="#listing-6-5">Listing 6-5</a>: A function that uses a <code>match</code> expression on an <code>Option&lt;i32&gt;</code></figcaption>
</figure>
<p>Lets examine the first execution of <code>plus_one</code> in more detail. When we call
<code>plus_one(five)</code>, the variable <code>x</code> in the body of <code>plus_one</code> will have the
value <code>Some(5)</code>. We then compare that against each match arm:</p>
<pre><code class="language-rust ignore"><span class="boring">fn main() {
</span><span class="boring"> fn plus_one(x: Option&lt;i32&gt;) -&gt; Option&lt;i32&gt; {
</span><span class="boring"> match x {
</span> None =&gt; None,
<span class="boring"> Some(i) =&gt; Some(i + 1),
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> let five = Some(5);
</span><span class="boring"> let six = plus_one(five);
</span><span class="boring"> let none = plus_one(None);
</span><span class="boring">}</span></code></pre>
<p>The <code>Some(5)</code> value doesnt match the pattern <code>None</code>, so we continue to the
next arm:</p>
<pre><code class="language-rust ignore"><span class="boring">fn main() {
</span><span class="boring"> fn plus_one(x: Option&lt;i32&gt;) -&gt; Option&lt;i32&gt; {
</span><span class="boring"> match x {
</span><span class="boring"> None =&gt; None,
</span> Some(i) =&gt; Some(i + 1),
<span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> let five = Some(5);
</span><span class="boring"> let six = plus_one(five);
</span><span class="boring"> let none = plus_one(None);
</span><span class="boring">}</span></code></pre>
<p>Does <code>Some(5)</code> match <code>Some(i)</code>? It does! We have the same variant. The <code>i</code>
binds to the value contained in <code>Some</code>, so <code>i</code> takes the value <code>5</code>. The code in
the match arm is then executed, so we add 1 to the value of <code>i</code> and create a
new <code>Some</code> value with our total <code>6</code> inside.</p>
<p>Now lets consider the second call of <code>plus_one</code> in Listing 6-5, where <code>x</code> is
<code>None</code>. We enter the <code>match</code> and compare to the first arm:</p>
<pre><code class="language-rust ignore"><span class="boring">fn main() {
</span><span class="boring"> fn plus_one(x: Option&lt;i32&gt;) -&gt; Option&lt;i32&gt; {
</span><span class="boring"> match x {
</span> None =&gt; None,
<span class="boring"> Some(i) =&gt; Some(i + 1),
</span><span class="boring"> }
</span><span class="boring"> }
</span><span class="boring">
</span><span class="boring"> let five = Some(5);
</span><span class="boring"> let six = plus_one(five);
</span><span class="boring"> let none = plus_one(None);
</span><span class="boring">}</span></code></pre>
<p>It matches! Theres no value to add to, so the program stops and returns the
<code>None</code> value on the right side of <code>=&gt;</code>. Because the first arm matched, no other
arms are compared.</p>
<p>Combining <code>match</code> and enums is useful in many situations. Youll see this
pattern a lot in Rust code: <code>match</code> against an enum, bind a variable to the
data inside, and then execute code based on it. Its a bit tricky at first, but
once you get used to it, youll wish you had it in all languages. Its
consistently a user favorite.</p>
<h3 id="matches-are-exhaustive"><a class="header" href="#matches-are-exhaustive">Matches Are Exhaustive</a></h3>
<p>Theres one other aspect of <code>match</code> we need to discuss: The arms patterns must
cover all possibilities. Consider this version of our <code>plus_one</code> function,
which has a bug and wont compile:</p>
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
</span> fn plus_one(x: Option&lt;i32&gt;) -&gt; Option&lt;i32&gt; {
match x {
Some(i) =&gt; Some(i + 1),
}
}
<span class="boring">
</span><span class="boring"> let five = Some(5);
</span><span class="boring"> let six = plus_one(five);
</span><span class="boring"> let none = plus_one(None);
</span><span class="boring">}</span></code></pre>
<p>We didnt handle the <code>None</code> case, so this code will cause a bug. Luckily, its
a bug Rust knows how to catch. If we try to compile this code, well get this
error:</p>
<pre><code class="language-console">$ cargo run
Compiling enums v0.1.0 (file:///projects/enums)
error[E0004]: non-exhaustive patterns: `None` not covered
--&gt; src/main.rs:3:15
|
3 | match x {
| ^ pattern `None` not covered
|
note: `Option&lt;i32&gt;` defined here
--&gt; /rustc/1159e78c4747b02ef996e55082b704c09b970588/library/core/src/option.rs:593:1
::: /rustc/1159e78c4747b02ef996e55082b704c09b970588/library/core/src/option.rs:597:5
|
= note: not covered
= note: the matched value is of type `Option&lt;i32&gt;`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
4 ~ Some(i) =&gt; Some(i + 1),
5 ~ None =&gt; todo!(),
|
For more information about this error, try `rustc --explain E0004`.
error: could not compile `enums` (bin "enums") due to 1 previous error
</code></pre>
<p>Rust knows that we didnt cover every possible case and even knows which
pattern we forgot! Matches in Rust are <em>exhaustive</em>: We must exhaust every last
possibility in order for the code to be valid. Especially in the case of
<code>Option&lt;T&gt;</code>, when Rust prevents us from forgetting to explicitly handle the
<code>None</code> case, it protects us from assuming that we have a value when we might
have null, thus making the billion-dollar mistake discussed earlier impossible.</p>
<h3 id="catch-all-patterns-and-the-_-placeholder"><a class="header" href="#catch-all-patterns-and-the-_-placeholder">Catch-All Patterns and the <code>_</code> Placeholder</a></h3>
<p>Using enums, we can also take special actions for a few particular values, but
for all other values take one default action. Imagine were implementing a game
where, if you roll a 3 on a dice roll, your player doesnt move but instead
gets a fancy new hat. If you roll a 7, your player loses a fancy hat. For all
other values, your player moves that number of spaces on the game board. Heres
a <code>match</code> that implements that logic, with the result of the dice roll
hardcoded rather than a random value, and all other logic represented by
functions without bodies because actually implementing them is out of scope for
this example:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let dice_roll = 9;
match dice_roll {
3 =&gt; add_fancy_hat(),
7 =&gt; remove_fancy_hat(),
other =&gt; move_player(other),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn move_player(num_spaces: u8) {}
<span class="boring">}</span></code></pre>
<p>For the first two arms, the patterns are the literal values <code>3</code> and <code>7</code>. For
the last arm that covers every other possible value, the pattern is the
variable weve chosen to name <code>other</code>. The code that runs for the <code>other</code> arm
uses the variable by passing it to the <code>move_player</code> function.</p>
<p>This code compiles, even though we havent listed all the possible values a
<code>u8</code> can have, because the last pattern will match all values not specifically
listed. This catch-all pattern meets the requirement that <code>match</code> must be
exhaustive. Note that we have to put the catch-all arm last because the
patterns are evaluated in order. If we had put the catch-all arm earlier, the
other arms would never run, so Rust will warn us if we add arms after a
catch-all!</p>
<p>Rust also has a pattern we can use when we want a catch-all but dont want to
<em>use</em> the value in the catch-all pattern: <code>_</code> is a special pattern that matches
any value and does not bind to that value. This tells Rust we arent going to
use the value, so Rust wont warn us about an unused variable.</p>
<p>Lets change the rules of the game: Now, if you roll anything other than a 3 or
a 7, you must roll again. We no longer need to use the catch-all value, so we
can change our code to use <code>_</code> instead of the variable named <code>other</code>:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let dice_roll = 9;
match dice_roll {
3 =&gt; add_fancy_hat(),
7 =&gt; remove_fancy_hat(),
_ =&gt; reroll(),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn reroll() {}
<span class="boring">}</span></code></pre>
<p>This example also meets the exhaustiveness requirement because were explicitly
ignoring all other values in the last arm; we havent forgotten anything.</p>
<p>Finally, well change the rules of the game one more time so that nothing else
happens on your turn if you roll anything other than a 3 or a 7. We can express
that by using the unit value (the empty tuple type we mentioned in <a href="ch03-02-data-types.html#the-tuple-type">“The Tuple
Type”</a><!-- ignore --> section) as the code that goes with the <code>_</code> arm:</p>
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
</span> let dice_roll = 9;
match dice_roll {
3 =&gt; add_fancy_hat(),
7 =&gt; remove_fancy_hat(),
_ =&gt; (),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}
<span class="boring">}</span></code></pre>
<p>Here, were telling Rust explicitly that we arent going to use any other value
that doesnt match a pattern in an earlier arm, and we dont want to run any
code in this case.</p>
<p>Theres more about patterns and matching that well cover in <a href="ch19-00-patterns.html">Chapter
19</a><!-- ignore -->. For now, were going to move on to the
<code>if let</code> syntax, which can be useful in situations where the <code>match</code> expression
is a bit wordy.</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="ch06-01-defining-an-enum.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span>
</a>
<a rel="next prefetch" href="ch06-03-if-let.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="ch06-01-defining-an-enum.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M41.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.3 256 246.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg></span>
</a>
<a rel="next prefetch" href="ch06-03-if-let.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M278.6 233.4c12.5 12.5 12.5 32.8 0 45.3l-160 160c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3L210.7 256 73.4 118.6c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0l160 160z"/></svg></span>
</a>
</nav>
</div>
<template id=fa-eye><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM432 256c0 79.5-64.5 144-144 144s-144-64.5-144-144s64.5-144 144-144s144 64.5 144 144zM288 192c0 35.3-28.7 64-64 64c-11.5 0-22.3-3-31.6-8.4c-.2 2.8-.4 5.5-.4 8.4c0 53 43 96 96 96s96-43 96-96s-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6z"/></svg></span></template>
<template id=fa-eye-slash><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L525.6 386.7c39.6-40.6 66.4-86.1 79.9-118.4c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C465.5 68.8 400.8 32 320 32c-68.2 0-125 26.3-169.3 60.8L38.8 5.1zM223.1 149.5C248.6 126.2 282.7 112 320 112c79.5 0 144 64.5 144 144c0 24.9-6.3 48.3-17.4 68.7L408 294.5c5.2-11.8 8-24.8 8-38.5c0-53-43-96-96-96c-2.8 0-5.6 .1-8.4 .4c5.3 9.3 8.4 20.1 8.4 31.6c0 10.2-2.4 19.8-6.6 28.3l-90.3-70.8zm223.1 298L373 389.9c-16.4 6.5-34.3 10.1-53 10.1c-79.5 0-144-64.5-144-144c0-6.9 .5-13.6 1.4-20.2L83.1 161.5C60.3 191.2 44 220.8 34.5 243.7c-3.3 7.9-3.3 16.7 0 24.6c14.9 35.7 46.2 87.7 93 131.1C174.5 443.2 239.2 480 320 480c47.8 0 89.9-12.9 126.2-32.5z"/></svg></span></template>
<template id=fa-copy><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M502.6 70.63l-61.25-61.25C435.4 3.371 427.2 0 418.7 0H255.1c-35.35 0-64 28.66-64 64l.0195 256C192 355.4 220.7 384 256 384h192c35.2 0 64-28.8 64-64V93.25C512 84.77 508.6 76.63 502.6 70.63zM464 320c0 8.836-7.164 16-16 16H255.1c-8.838 0-16-7.164-16-16L239.1 64.13c0-8.836 7.164-16 16-16h128L384 96c0 17.67 14.33 32 32 32h47.1V320zM272 448c0 8.836-7.164 16-16 16H63.1c-8.838 0-16-7.164-16-16L47.98 192.1c0-8.836 7.164-16 16-16H160V128H63.99c-35.35 0-64 28.65-64 64l.0098 256C.002 483.3 28.66 512 64 512h192c35.2 0 64-28.8 64-64v-32h-47.1L272 448z"/></svg></span></template>
<template id=fa-play><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M73 39c-14.8-9.1-33.4-9.4-48.5-.9S0 62.6 0 80V432c0 17.4 9.4 33.4 24.5 41.9s33.7 8.1 48.5-.9L361 297c14.3-8.7 23-24.2 23-41s-8.7-32.2-23-41L73 39z"/></svg></span></template>
<template id=fa-clock-rotate-left><span class=fa-svg><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc. --><path d="M75 75L41 41C25.9 25.9 0 36.6 0 57.9V168c0 13.3 10.7 24 24 24H134.1c21.4 0 32.1-25.9 17-41l-30.8-30.8C155 85.5 203 64 256 64c106 0 192 86 192 192s-86 192-192 192c-40.8 0-78.6-12.7-109.7-34.4c-14.5-10.1-34.4-6.6-44.6 7.9s-6.6 34.4 7.9 44.6C151.2 495 201.7 512 256 512c141.4 0 256-114.6 256-256S397.4 0 256 0C185.3 0 121.3 28.7 75 75zm181 53c-13.3 0-24 10.7-24 24V256c0 6.4 2.5 12.5 7 17l72 72c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-65-65V152c0-13.3-10.7-24-24-24z"/></svg></span></template>
<script>
window.playground_copyable = true;
</script>
<script src="elasticlunr-ef4e11c1.min.js"></script>
<script src="mark-09e88c2c.min.js"></script>
<script src="searcher-09f2665d.js"></script>
<script src="clipboard-1626706a.min.js"></script>
<script src="highlight-abc7f01d.js"></script>
<script src="book-c22b7243.js"></script>
<!-- Custom JS scripts -->
<script src="ferris-2317480c.js"></script>
</div>
</body>
</html>