941 lines
62 KiB
HTML
941 lines
62 KiB
HTML
<!DOCTYPE HTML>
|
||
<html lang="en" class="light sidebar-visible" dir="ltr">
|
||
<head>
|
||
<!-- Book generated using mdBook -->
|
||
<meta charset="UTF-8">
|
||
<title>Pattern Syntax - 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>
|
||
<h2 id="pattern-syntax"><a class="header" href="#pattern-syntax">Pattern Syntax</a></h2>
|
||
<p>In this section, we gather all the syntax that is valid in patterns and discuss
|
||
why and when you might want to use each one.</p>
|
||
<h3 id="matching-literals"><a class="header" href="#matching-literals">Matching Literals</a></h3>
|
||
<p>As you saw in Chapter 6, you can match patterns against literals directly. The
|
||
following code gives some examples:</p>
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let x = 1;
|
||
|
||
match x {
|
||
1 => println!("one"),
|
||
2 => println!("two"),
|
||
3 => println!("three"),
|
||
_ => println!("anything"),
|
||
}
|
||
<span class="boring">}</span></code></pre>
|
||
<p>This code prints <code>one</code> because the value in <code>x</code> is <code>1</code>. This syntax is useful
|
||
when you want your code to take an action if it gets a particular concrete
|
||
value.</p>
|
||
<h3 id="matching-named-variables"><a class="header" href="#matching-named-variables">Matching Named Variables</a></h3>
|
||
<p>Named variables are irrefutable patterns that match any value, and we’ve used
|
||
them many times in this book. However, there is a complication when you use
|
||
named variables in <code>match</code>, <code>if let</code>, or <code>while let</code> expressions. Because each
|
||
of these kinds of expressions starts a new scope, variables declared as part of
|
||
a pattern inside these expressions will shadow those with the same name outside
|
||
the constructs, as is the case with all variables. In Listing 19-11, we declare
|
||
a variable named <code>x</code> with the value <code>Some(5)</code> and a variable <code>y</code> with the value
|
||
<code>10</code>. We then create a <code>match</code> expression on the value <code>x</code>. Look at the
|
||
patterns in the match arms and <code>println!</code> at the end, and try to figure out
|
||
what the code will print before running this code or reading further.</p>
|
||
<figure class="listing" id="listing-19-11">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let x = Some(5);
|
||
let y = 10;
|
||
|
||
match x {
|
||
Some(50) => println!("Got 50"),
|
||
Some(y) => println!("Matched, y = {y}"),
|
||
_ => println!("Default case, x = {x:?}"),
|
||
}
|
||
|
||
println!("at the end: x = {x:?}, y = {y}");
|
||
<span class="boring">}</span></code></pre>
|
||
<figcaption><a href="#listing-19-11">Listing 19-11</a>: A <code>match</code> expression with an arm that introduces a new variable which shadows an existing variable <code>y</code></figcaption>
|
||
</figure>
|
||
<p>Let’s walk through what happens when the <code>match</code> expression runs. The pattern
|
||
in the first match arm doesn’t match the defined value of <code>x</code>, so the code
|
||
continues.</p>
|
||
<p>The pattern in the second match arm introduces a new variable named <code>y</code> that
|
||
will match any value inside a <code>Some</code> value. Because we’re in a new scope inside
|
||
the <code>match</code> expression, this is a new <code>y</code> variable, not the <code>y</code> we declared at
|
||
the beginning with the value <code>10</code>. This new <code>y</code> binding will match any value
|
||
inside a <code>Some</code>, which is what we have in <code>x</code>. Therefore, this new <code>y</code> binds to
|
||
the inner value of the <code>Some</code> in <code>x</code>. That value is <code>5</code>, so the expression for
|
||
that arm executes and prints <code>Matched, y = 5</code>.</p>
|
||
<p>If <code>x</code> had been a <code>None</code> value instead of <code>Some(5)</code>, the patterns in the first
|
||
two arms wouldn’t have matched, so the value would have matched to the
|
||
underscore. We didn’t introduce the <code>x</code> variable in the pattern of the
|
||
underscore arm, so the <code>x</code> in the expression is still the outer <code>x</code> that hasn’t
|
||
been shadowed. In this hypothetical case, the <code>match</code> would print <code>Default case, x = None</code>.</p>
|
||
<p>When the <code>match</code> expression is done, its scope ends, and so does the scope of
|
||
the inner <code>y</code>. The last <code>println!</code> produces <code>at the end: x = Some(5), y = 10</code>.</p>
|
||
<p>To create a <code>match</code> expression that compares the values of the outer <code>x</code> and
|
||
<code>y</code>, rather than introducing a new variable that shadows the existing <code>y</code>
|
||
variable, we would need to use a match guard conditional instead. We’ll talk
|
||
about match guards later in the <a href="#adding-conditionals-with-match-guards">“Adding Conditionals with Match
|
||
Guards”</a><!-- ignore --> section.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="multiple-patterns"></a></p>
|
||
<h3 id="matching-multiple-patterns"><a class="header" href="#matching-multiple-patterns">Matching Multiple Patterns</a></h3>
|
||
<p>In <code>match</code> expressions, you can match multiple patterns using the <code>|</code> syntax,
|
||
which is the pattern <em>or</em> operator. For example, in the following code, we match
|
||
the value of <code>x</code> against the match arms, the first of which has an <em>or</em> option,
|
||
meaning if the value of <code>x</code> matches either of the values in that arm, that
|
||
arm’s code will run:</p>
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let x = 1;
|
||
|
||
match x {
|
||
1 | 2 => println!("one or two"),
|
||
3 => println!("three"),
|
||
_ => println!("anything"),
|
||
}
|
||
<span class="boring">}</span></code></pre>
|
||
<p>This code prints <code>one or two</code>.</p>
|
||
<h3 id="matching-ranges-of-values-with-"><a class="header" href="#matching-ranges-of-values-with-">Matching Ranges of Values with <code>..=</code></a></h3>
|
||
<p>The <code>..=</code> syntax allows us to match to an inclusive range of values. In the
|
||
following code, when a pattern matches any of the values within the given
|
||
range, that arm will execute:</p>
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let x = 5;
|
||
|
||
match x {
|
||
1..=5 => println!("one through five"),
|
||
_ => println!("something else"),
|
||
}
|
||
<span class="boring">}</span></code></pre>
|
||
<p>If <code>x</code> is <code>1</code>, <code>2</code>, <code>3</code>, <code>4</code>, or <code>5</code>, the first arm will match. This syntax is
|
||
more convenient for multiple match values than using the <code>|</code> operator to
|
||
express the same idea; if we were to use <code>|</code>, we would have to specify <code>1 | 2 | 3 | 4 | 5</code>. Specifying a range is much shorter, especially if we want to match,
|
||
say, any number between 1 and 1,000!</p>
|
||
<p>The compiler checks that the range isn’t empty at compile time, and because the
|
||
only types for which Rust can tell if a range is empty or not are <code>char</code> and
|
||
numeric values, ranges are only allowed with numeric or <code>char</code> values.</p>
|
||
<p>Here is an example using ranges of <code>char</code> values:</p>
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let x = 'c';
|
||
|
||
match x {
|
||
'a'..='j' => println!("early ASCII letter"),
|
||
'k'..='z' => println!("late ASCII letter"),
|
||
_ => println!("something else"),
|
||
}
|
||
<span class="boring">}</span></code></pre>
|
||
<p>Rust can tell that <code>'c'</code> is within the first pattern’s range and prints <code>early ASCII letter</code>.</p>
|
||
<h3 id="destructuring-to-break-apart-values"><a class="header" href="#destructuring-to-break-apart-values">Destructuring to Break Apart Values</a></h3>
|
||
<p>We can also use patterns to destructure structs, enums, and tuples to use
|
||
different parts of these values. Let’s walk through each value.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="destructuring-structs"></a></p>
|
||
<h4 id="structs"><a class="header" href="#structs">Structs</a></h4>
|
||
<p>Listing 19-12 shows a <code>Point</code> struct with two fields, <code>x</code> and <code>y</code>, that we can
|
||
break apart using a pattern with a <code>let</code> statement.</p>
|
||
<figure class="listing" id="listing-19-12">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre class="playground"><code class="language-rust edition2024">struct Point {
|
||
x: i32,
|
||
y: i32,
|
||
}
|
||
|
||
fn main() {
|
||
let p = Point { x: 0, y: 7 };
|
||
|
||
let Point { x: a, y: b } = p;
|
||
assert_eq!(0, a);
|
||
assert_eq!(7, b);
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-12">Listing 19-12</a>: Destructuring a struct’s fields into separate variables</figcaption>
|
||
</figure>
|
||
<p>This code creates the variables <code>a</code> and <code>b</code> that match the values of the <code>x</code>
|
||
and <code>y</code> fields of the <code>p</code> struct. This example shows that the names of the
|
||
variables in the pattern don’t have to match the field names of the struct.
|
||
However, it’s common to match the variable names to the field names to make it
|
||
easier to remember which variables came from which fields. Because of this
|
||
common usage, and because writing <code>let Point { x: x, y: y } = p;</code> contains a
|
||
lot of duplication, Rust has a shorthand for patterns that match struct fields:
|
||
You only need to list the name of the struct field, and the variables created
|
||
from the pattern will have the same names. Listing 19-13 behaves in the same
|
||
way as the code in Listing 19-12, but the variables created in the <code>let</code>
|
||
pattern are <code>x</code> and <code>y</code> instead of <code>a</code> and <code>b</code>.</p>
|
||
<figure class="listing" id="listing-19-13">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre class="playground"><code class="language-rust edition2024">struct Point {
|
||
x: i32,
|
||
y: i32,
|
||
}
|
||
|
||
fn main() {
|
||
let p = Point { x: 0, y: 7 };
|
||
|
||
let Point { x, y } = p;
|
||
assert_eq!(0, x);
|
||
assert_eq!(7, y);
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-13">Listing 19-13</a>: Destructuring struct fields using struct field shorthand</figcaption>
|
||
</figure>
|
||
<p>This code creates the variables <code>x</code> and <code>y</code> that match the <code>x</code> and <code>y</code> fields
|
||
of the <code>p</code> variable. The outcome is that the variables <code>x</code> and <code>y</code> contain the
|
||
values from the <code>p</code> struct.</p>
|
||
<p>We can also destructure with literal values as part of the struct pattern
|
||
rather than creating variables for all the fields. Doing so allows us to test
|
||
some of the fields for particular values while creating variables to
|
||
destructure the other fields.</p>
|
||
<p>In Listing 19-14, we have a <code>match</code> expression that separates <code>Point</code> values
|
||
into three cases: points that lie directly on the <code>x</code> axis (which is true when
|
||
<code>y = 0</code>), on the <code>y</code> axis (<code>x = 0</code>), or on neither axis.</p>
|
||
<figure class="listing" id="listing-19-14">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">struct Point {
|
||
</span><span class="boring"> x: i32,
|
||
</span><span class="boring"> y: i32,
|
||
</span><span class="boring">}
|
||
</span><span class="boring">
|
||
</span>fn main() {
|
||
let p = Point { x: 0, y: 7 };
|
||
|
||
match p {
|
||
Point { x, y: 0 } => println!("On the x axis at {x}"),
|
||
Point { x: 0, y } => println!("On the y axis at {y}"),
|
||
Point { x, y } => {
|
||
println!("On neither axis: ({x}, {y})");
|
||
}
|
||
}
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-14">Listing 19-14</a>: Destructuring and matching literal values in one pattern</figcaption>
|
||
</figure>
|
||
<p>The first arm will match any point that lies on the <code>x</code> axis by specifying that
|
||
the <code>y</code> field matches if its value matches the literal <code>0</code>. The pattern still
|
||
creates an <code>x</code> variable that we can use in the code for this arm.</p>
|
||
<p>Similarly, the second arm matches any point on the <code>y</code> axis by specifying that
|
||
the <code>x</code> field matches if its value is <code>0</code> and creates a variable <code>y</code> for the
|
||
value of the <code>y</code> field. The third arm doesn’t specify any literals, so it
|
||
matches any other <code>Point</code> and creates variables for both the <code>x</code> and <code>y</code> fields.</p>
|
||
<p>In this example, the value <code>p</code> matches the second arm by virtue of <code>x</code>
|
||
containing a <code>0</code>, so this code will print <code>On the y axis at 7</code>.</p>
|
||
<p>Remember that a <code>match</code> expression stops checking arms once it has found the
|
||
first matching pattern, so even though <code>Point { x: 0, y: 0 }</code> is on the <code>x</code> axis
|
||
and the <code>y</code> axis, this code would only print <code>On the x axis at 0</code>.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="destructuring-enums"></a></p>
|
||
<h4 id="enums"><a class="header" href="#enums">Enums</a></h4>
|
||
<p>We’ve destructured enums in this book (for example, Listing 6-5 in Chapter 6),
|
||
but we haven’t yet explicitly discussed that the pattern to destructure an enum
|
||
corresponds to the way the data stored within the enum is defined. As an
|
||
example, in Listing 19-15, we use the <code>Message</code> enum from Listing 6-2 and write
|
||
a <code>match</code> with patterns that will destructure each inner value.</p>
|
||
<figure class="listing" id="listing-19-15">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre class="playground"><code class="language-rust edition2024">enum Message {
|
||
Quit,
|
||
Move { x: i32, y: i32 },
|
||
Write(String),
|
||
ChangeColor(i32, i32, i32),
|
||
}
|
||
|
||
fn main() {
|
||
let msg = Message::ChangeColor(0, 160, 255);
|
||
|
||
match msg {
|
||
Message::Quit => {
|
||
println!("The Quit variant has no data to destructure.");
|
||
}
|
||
Message::Move { x, y } => {
|
||
println!("Move in the x direction {x} and in the y direction {y}");
|
||
}
|
||
Message::Write(text) => {
|
||
println!("Text message: {text}");
|
||
}
|
||
Message::ChangeColor(r, g, b) => {
|
||
println!("Change color to red {r}, green {g}, and blue {b}");
|
||
}
|
||
}
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-15">Listing 19-15</a>: Destructuring enum variants that hold different kinds of values</figcaption>
|
||
</figure>
|
||
<p>This code will print <code>Change color to red 0, green 160, and blue 255</code>. Try
|
||
changing the value of <code>msg</code> to see the code from the other arms run.</p>
|
||
<p>For enum variants without any data, like <code>Message::Quit</code>, we can’t destructure
|
||
the value any further. We can only match on the literal <code>Message::Quit</code> value,
|
||
and no variables are in that pattern.</p>
|
||
<p>For struct-like enum variants, such as <code>Message::Move</code>, we can use a pattern
|
||
similar to the pattern we specify to match structs. After the variant name, we
|
||
place curly brackets and then list the fields with variables so that we break
|
||
apart the pieces to use in the code for this arm. Here we use the shorthand
|
||
form as we did in Listing 19-13.</p>
|
||
<p>For tuple-like enum variants, like <code>Message::Write</code> that holds a tuple with one
|
||
element and <code>Message::ChangeColor</code> that holds a tuple with three elements, the
|
||
pattern is similar to the pattern we specify to match tuples. The number of
|
||
variables in the pattern must match the number of elements in the variant we’re
|
||
matching.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="destructuring-nested-structs-and-enums"></a></p>
|
||
<h4 id="nested-structs-and-enums"><a class="header" href="#nested-structs-and-enums">Nested Structs and Enums</a></h4>
|
||
<p>So far, our examples have all been matching structs or enums one level deep,
|
||
but matching can work on nested items too! For example, we can refactor the
|
||
code in Listing 19-15 to support RGB and HSV colors in the <code>ChangeColor</code>
|
||
message, as shown in Listing 19-16.</p>
|
||
<figure class="listing" id="listing-19-16">
|
||
<pre class="playground"><code class="language-rust edition2024">enum Color {
|
||
Rgb(i32, i32, i32),
|
||
Hsv(i32, i32, i32),
|
||
}
|
||
|
||
enum Message {
|
||
Quit,
|
||
Move { x: i32, y: i32 },
|
||
Write(String),
|
||
ChangeColor(Color),
|
||
}
|
||
|
||
fn main() {
|
||
let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
|
||
|
||
match msg {
|
||
Message::ChangeColor(Color::Rgb(r, g, b)) => {
|
||
println!("Change color to red {r}, green {g}, and blue {b}");
|
||
}
|
||
Message::ChangeColor(Color::Hsv(h, s, v)) => {
|
||
println!("Change color to hue {h}, saturation {s}, value {v}");
|
||
}
|
||
_ => (),
|
||
}
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-16">Listing 19-16</a>: Matching on nested enums</figcaption>
|
||
</figure>
|
||
<p>The pattern of the first arm in the <code>match</code> expression matches a
|
||
<code>Message::ChangeColor</code> enum variant that contains a <code>Color::Rgb</code> variant; then,
|
||
the pattern binds to the three inner <code>i32</code> values. The pattern of the second
|
||
arm also matches a <code>Message::ChangeColor</code> enum variant, but the inner enum
|
||
matches <code>Color::Hsv</code> instead. We can specify these complex conditions in one
|
||
<code>match</code> expression, even though two enums are involved.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="destructuring-structs-and-tuples"></a></p>
|
||
<h4 id="structs-and-tuples"><a class="header" href="#structs-and-tuples">Structs and Tuples</a></h4>
|
||
<p>We can mix, match, and nest destructuring patterns in even more complex ways.
|
||
The following example shows a complicated destructure where we nest structs and
|
||
tuples inside a tuple and destructure all the primitive values out:</p>
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span><span class="boring"> struct Point {
|
||
</span><span class="boring"> x: i32,
|
||
</span><span class="boring"> y: i32,
|
||
</span><span class="boring"> }
|
||
</span><span class="boring">
|
||
</span> let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 });
|
||
<span class="boring">}</span></code></pre>
|
||
<p>This code lets us break complex types into their component parts so that we can
|
||
use the values we’re interested in separately.</p>
|
||
<p>Destructuring with patterns is a convenient way to use pieces of values, such
|
||
as the value from each field in a struct, separately from each other.</p>
|
||
<h3 id="ignoring-values-in-a-pattern"><a class="header" href="#ignoring-values-in-a-pattern">Ignoring Values in a Pattern</a></h3>
|
||
<p>You’ve seen that it’s sometimes useful to ignore values in a pattern, such as
|
||
in the last arm of a <code>match</code>, to get a catch-all that doesn’t actually do
|
||
anything but does account for all remaining possible values. There are a few
|
||
ways to ignore entire values or parts of values in a pattern: using the <code>_</code>
|
||
pattern (which you’ve seen), using the <code>_</code> pattern within another pattern,
|
||
using a name that starts with an underscore, or using <code>..</code> to ignore remaining
|
||
parts of a value. Let’s explore how and why to use each of these patterns.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="ignoring-an-entire-value-with-_"></a></p>
|
||
<h4 id="an-entire-value-with-_"><a class="header" href="#an-entire-value-with-_">An Entire Value with <code>_</code></a></h4>
|
||
<p>We’ve used the underscore as a wildcard pattern that will match any value but
|
||
not bind to the value. This is especially useful as the last arm in a <code>match</code>
|
||
expression, but we can also use it in any pattern, including function
|
||
parameters, as shown in Listing 19-17.</p>
|
||
<figure class="listing" id="listing-19-17">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre class="playground"><code class="language-rust edition2024">fn foo(_: i32, y: i32) {
|
||
println!("This code only uses the y parameter: {y}");
|
||
}
|
||
|
||
fn main() {
|
||
foo(3, 4);
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-17">Listing 19-17</a>: Using <code>_</code> in a function signature</figcaption>
|
||
</figure>
|
||
<p>This code will completely ignore the value <code>3</code> passed as the first argument,
|
||
and will print <code>This code only uses the y parameter: 4</code>.</p>
|
||
<p>In most cases when you no longer need a particular function parameter, you
|
||
would change the signature so that it doesn’t include the unused parameter.
|
||
Ignoring a function parameter can be especially useful in cases when, for
|
||
example, you’re implementing a trait when you need a certain type signature but
|
||
the function body in your implementation doesn’t need one of the parameters.
|
||
You then avoid getting a compiler warning about unused function parameters, as
|
||
you would if you used a name instead.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="ignoring-parts-of-a-value-with-a-nested-_"></a></p>
|
||
<h4 id="parts-of-a-value-with-a-nested-_"><a class="header" href="#parts-of-a-value-with-a-nested-_">Parts of a Value with a Nested <code>_</code></a></h4>
|
||
<p>We can also use <code>_</code> inside another pattern to ignore just part of a value, for
|
||
example, when we want to test for only part of a value but have no use for the
|
||
other parts in the corresponding code we want to run. Listing 19-18 shows code
|
||
responsible for managing a setting’s value. The business requirements are that
|
||
the user should not be allowed to overwrite an existing customization of a
|
||
setting but can unset the setting and give it a value if it is currently unset.</p>
|
||
<figure class="listing" id="listing-19-18">
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let mut setting_value = Some(5);
|
||
let new_setting_value = Some(10);
|
||
|
||
match (setting_value, new_setting_value) {
|
||
(Some(_), Some(_)) => {
|
||
println!("Can't overwrite an existing customized value");
|
||
}
|
||
_ => {
|
||
setting_value = new_setting_value;
|
||
}
|
||
}
|
||
|
||
println!("setting is {setting_value:?}");
|
||
<span class="boring">}</span></code></pre>
|
||
<figcaption><a href="#listing-19-18">Listing 19-18</a>: Using an underscore within patterns that match <code>Some</code> variants when we don’t need to use the value inside the <code>Some</code></figcaption>
|
||
</figure>
|
||
<p>This code will print <code>Can't overwrite an existing customized value</code> and then
|
||
<code>setting is Some(5)</code>. In the first match arm, we don’t need to match on or use
|
||
the values inside either <code>Some</code> variant, but we do need to test for the case
|
||
when <code>setting_value</code> and <code>new_setting_value</code> are the <code>Some</code> variant. In that
|
||
case, we print the reason for not changing <code>setting_value</code>, and it doesn’t get
|
||
changed.</p>
|
||
<p>In all other cases (if either <code>setting_value</code> or <code>new_setting_value</code> is <code>None</code>)
|
||
expressed by the <code>_</code> pattern in the second arm, we want to allow
|
||
<code>new_setting_value</code> to become <code>setting_value</code>.</p>
|
||
<p>We can also use underscores in multiple places within one pattern to ignore
|
||
particular values. Listing 19-19 shows an example of ignoring the second and
|
||
fourth values in a tuple of five items.</p>
|
||
<figure class="listing" id="listing-19-19">
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let numbers = (2, 4, 8, 16, 32);
|
||
|
||
match numbers {
|
||
(first, _, third, _, fifth) => {
|
||
println!("Some numbers: {first}, {third}, {fifth}");
|
||
}
|
||
}
|
||
<span class="boring">}</span></code></pre>
|
||
<figcaption><a href="#listing-19-19">Listing 19-19</a>: Ignoring multiple parts of a tuple</figcaption>
|
||
</figure>
|
||
<p>This code will print <code>Some numbers: 2, 8, 32</code>, and the values <code>4</code> and <code>16</code> will
|
||
be ignored.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="ignoring-an-unused-variable-by-starting-its-name-with-_"></a></p>
|
||
<h4 id="an-unused-variable-by-starting-its-name-with-_"><a class="header" href="#an-unused-variable-by-starting-its-name-with-_">An Unused Variable by Starting Its Name with <code>_</code></a></h4>
|
||
<p>If you create a variable but don’t use it anywhere, Rust will usually issue a
|
||
warning because an unused variable could be a bug. However, sometimes it’s
|
||
useful to be able to create a variable you won’t use yet, such as when you’re
|
||
prototyping or just starting a project. In this situation, you can tell Rust
|
||
not to warn you about the unused variable by starting the name of the variable
|
||
with an underscore. In Listing 19-20, we create two unused variables, but when
|
||
we compile this code, we should only get a warning about one of them.</p>
|
||
<figure class="listing" id="listing-19-20">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre class="playground"><code class="language-rust edition2024">fn main() {
|
||
let _x = 5;
|
||
let y = 10;
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-20">Listing 19-20</a>: Starting a variable name with an underscore to avoid getting unused variable warnings</figcaption>
|
||
</figure>
|
||
<p>Here, we get a warning about not using the variable <code>y</code>, but we don’t get a
|
||
warning about not using <code>_x</code>.</p>
|
||
<p>Note that there is a subtle difference between using only <code>_</code> and using a name
|
||
that starts with an underscore. The syntax <code>_x</code> still binds the value to the
|
||
variable, whereas <code>_</code> doesn’t bind at all. To show a case where this
|
||
distinction matters, Listing 19-21 will provide us with an error.</p>
|
||
<figure class="listing" id="listing-19-21">
|
||
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
|
||
</span> let s = Some(String::from("Hello!"));
|
||
|
||
if let Some(_s) = s {
|
||
println!("found a string");
|
||
}
|
||
|
||
println!("{s:?}");
|
||
<span class="boring">}</span></code></pre>
|
||
<figcaption><a href="#listing-19-21">Listing 19-21</a>: An unused variable starting with an underscore still binds the value, which might take ownership of the value.</figcaption>
|
||
</figure>
|
||
<p>We’ll receive an error because the <code>s</code> value will still be moved into <code>_s</code>,
|
||
which prevents us from using <code>s</code> again. However, using the underscore by itself
|
||
doesn’t ever bind to the value. Listing 19-22 will compile without any errors
|
||
because <code>s</code> doesn’t get moved into <code>_</code>.</p>
|
||
<figure class="listing" id="listing-19-22">
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let s = Some(String::from("Hello!"));
|
||
|
||
if let Some(_) = s {
|
||
println!("found a string");
|
||
}
|
||
|
||
println!("{s:?}");
|
||
<span class="boring">}</span></code></pre>
|
||
<figcaption><a href="#listing-19-22">Listing 19-22</a>: Using an underscore does not bind the value.</figcaption>
|
||
</figure>
|
||
<p>This code works just fine because we never bind <code>s</code> to anything; it isn’t moved.</p>
|
||
<p><a id="ignoring-remaining-parts-of-a-value-with-"></a></p>
|
||
<h4 id="remaining-parts-of-a-value-with-"><a class="header" href="#remaining-parts-of-a-value-with-">Remaining Parts of a Value with <code>..</code></a></h4>
|
||
<p>With values that have many parts, we can use the <code>..</code> syntax to use specific
|
||
parts and ignore the rest, avoiding the need to list underscores for each
|
||
ignored value. The <code>..</code> pattern ignores any parts of a value that we haven’t
|
||
explicitly matched in the rest of the pattern. In Listing 19-23, we have a
|
||
<code>Point</code> struct that holds a coordinate in three-dimensional space. In the
|
||
<code>match</code> expression, we want to operate only on the <code>x</code> coordinate and ignore
|
||
the values in the <code>y</code> and <code>z</code> fields.</p>
|
||
<figure class="listing" id="listing-19-23">
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> struct Point {
|
||
x: i32,
|
||
y: i32,
|
||
z: i32,
|
||
}
|
||
|
||
let origin = Point { x: 0, y: 0, z: 0 };
|
||
|
||
match origin {
|
||
Point { x, .. } => println!("x is {x}"),
|
||
}
|
||
<span class="boring">}</span></code></pre>
|
||
<figcaption><a href="#listing-19-23">Listing 19-23</a>: Ignoring all fields of a <code>Point</code> except for <code>x</code> by using <code>..</code></figcaption>
|
||
</figure>
|
||
<p>We list the <code>x</code> value and then just include the <code>..</code> pattern. This is quicker
|
||
than having to list <code>y: _</code> and <code>z: _</code>, particularly when we’re working with
|
||
structs that have lots of fields in situations where only one or two fields are
|
||
relevant.</p>
|
||
<p>The syntax <code>..</code> will expand to as many values as it needs to be. Listing 19-24
|
||
shows how to use <code>..</code> with a tuple.</p>
|
||
<figure class="listing" id="listing-19-24">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre class="playground"><code class="language-rust edition2024">fn main() {
|
||
let numbers = (2, 4, 8, 16, 32);
|
||
|
||
match numbers {
|
||
(first, .., last) => {
|
||
println!("Some numbers: {first}, {last}");
|
||
}
|
||
}
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-24">Listing 19-24</a>: Matching only the first and last values in a tuple and ignoring all other values</figcaption>
|
||
</figure>
|
||
<p>In this code, the first and last values are matched with <code>first</code> and <code>last</code>.
|
||
The <code>..</code> will match and ignore everything in the middle.</p>
|
||
<p>However, using <code>..</code> must be unambiguous. If it is unclear which values are
|
||
intended for matching and which should be ignored, Rust will give us an error.
|
||
Listing 19-25 shows an example of using <code>..</code> ambiguously, so it will not
|
||
compile.</p>
|
||
<figure class="listing" id="listing-19-25">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre><code class="language-rust ignore does_not_compile">fn main() {
|
||
let numbers = (2, 4, 8, 16, 32);
|
||
|
||
match numbers {
|
||
(.., second, ..) => {
|
||
println!("Some numbers: {second}")
|
||
},
|
||
}
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-25">Listing 19-25</a>: An attempt to use <code>..</code> in an ambiguous way</figcaption>
|
||
</figure>
|
||
<p>When we compile this example, we get this error:</p>
|
||
<pre><code class="language-console">$ cargo run
|
||
Compiling patterns v0.1.0 (file:///projects/patterns)
|
||
error: `..` can only be used once per tuple pattern
|
||
--> src/main.rs:5:22
|
||
|
|
||
5 | (.., second, ..) => {
|
||
| -- ^^ can only be used once per tuple pattern
|
||
| |
|
||
| previously used here
|
||
|
||
error: could not compile `patterns` (bin "patterns") due to 1 previous error
|
||
</code></pre>
|
||
<p>It’s impossible for Rust to determine how many values in the tuple to ignore
|
||
before matching a value with <code>second</code> and then how many further values to
|
||
ignore thereafter. This code could mean that we want to ignore <code>2</code>, bind
|
||
<code>second</code> to <code>4</code>, and then ignore <code>8</code>, <code>16</code>, and <code>32</code>; or that we want to ignore
|
||
<code>2</code> and <code>4</code>, bind <code>second</code> to <code>8</code>, and then ignore <code>16</code> and <code>32</code>; and so forth.
|
||
The variable name <code>second</code> doesn’t mean anything special to Rust, so we get a
|
||
compiler error because using <code>..</code> in two places like this is ambiguous.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="extra-conditionals-with-match-guards"></a></p>
|
||
<h3 id="adding-conditionals-with-match-guards"><a class="header" href="#adding-conditionals-with-match-guards">Adding Conditionals with Match Guards</a></h3>
|
||
<p>A <em>match guard</em> is an additional <code>if</code> condition, specified after the pattern in
|
||
a <code>match</code> arm, that must also match for that arm to be chosen. Match guards are
|
||
useful for expressing more complex ideas than a pattern alone allows. Note,
|
||
however, that they are only available in <code>match</code> expressions, not <code>if let</code> or
|
||
<code>while let</code> expressions.</p>
|
||
<p>The condition can use variables created in the pattern. Listing 19-26 shows a
|
||
<code>match</code> where the first arm has the pattern <code>Some(x)</code> and also has a match
|
||
guard of <code>if x % 2 == 0</code> (which will be <code>true</code> if the number is even).</p>
|
||
<figure class="listing" id="listing-19-26">
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let num = Some(4);
|
||
|
||
match num {
|
||
Some(x) if x % 2 == 0 => println!("The number {x} is even"),
|
||
Some(x) => println!("The number {x} is odd"),
|
||
None => (),
|
||
}
|
||
<span class="boring">}</span></code></pre>
|
||
<figcaption><a href="#listing-19-26">Listing 19-26</a>: Adding a match guard to a pattern</figcaption>
|
||
</figure>
|
||
<p>This example will print <code>The number 4 is even</code>. When <code>num</code> is compared to the
|
||
pattern in the first arm, it matches because <code>Some(4)</code> matches <code>Some(x)</code>. Then,
|
||
the match guard checks whether the remainder of dividing <code>x</code> by 2 is equal to
|
||
0, and because it is, the first arm is selected.</p>
|
||
<p>If <code>num</code> had been <code>Some(5)</code> instead, the match guard in the first arm would
|
||
have been <code>false</code> because the remainder of 5 divided by 2 is 1, which is not
|
||
equal to 0. Rust would then go to the second arm, which would match because the
|
||
second arm doesn’t have a match guard and therefore matches any <code>Some</code> variant.</p>
|
||
<p>There is no way to express the <code>if x % 2 == 0</code> condition within a pattern, so
|
||
the match guard gives us the ability to express this logic. The downside of
|
||
this additional expressiveness is that the compiler doesn’t try to check for
|
||
exhaustiveness when match guard expressions are involved.</p>
|
||
<p>When discussing Listing 19-11, we mentioned that we could use match guards to
|
||
solve our pattern-shadowing problem. Recall that we created a new variable
|
||
inside the pattern in the <code>match</code> expression instead of using the variable
|
||
outside the <code>match</code>. That new variable meant we couldn’t test against the value
|
||
of the outer variable. Listing 19-27 shows how we can use a match guard to fix
|
||
this problem.</p>
|
||
<figure class="listing" id="listing-19-27">
|
||
<span class="file-name">Filename: src/main.rs</span>
|
||
<pre class="playground"><code class="language-rust edition2024">fn main() {
|
||
let x = Some(5);
|
||
let y = 10;
|
||
|
||
match x {
|
||
Some(50) => println!("Got 50"),
|
||
Some(n) if n == y => println!("Matched, n = {n}"),
|
||
_ => println!("Default case, x = {x:?}"),
|
||
}
|
||
|
||
println!("at the end: x = {x:?}, y = {y}");
|
||
}</code></pre>
|
||
<figcaption><a href="#listing-19-27">Listing 19-27</a>: Using a match guard to test for equality with an outer variable</figcaption>
|
||
</figure>
|
||
<p>This code will now print <code>Default case, x = Some(5)</code>. The pattern in the second
|
||
match arm doesn’t introduce a new variable <code>y</code> that would shadow the outer <code>y</code>,
|
||
meaning we can use the outer <code>y</code> in the match guard. Instead of specifying the
|
||
pattern as <code>Some(y)</code>, which would have shadowed the outer <code>y</code>, we specify
|
||
<code>Some(n)</code>. This creates a new variable <code>n</code> that doesn’t shadow anything because
|
||
there is no <code>n</code> variable outside the <code>match</code>.</p>
|
||
<p>The match guard <code>if n == y</code> is not a pattern and therefore doesn’t introduce new
|
||
variables. This <code>y</code> <em>is</em> the outer <code>y</code> rather than a new <code>y</code> shadowing it, and
|
||
we can look for a value that has the same value as the outer <code>y</code> by comparing
|
||
<code>n</code> to <code>y</code>.</p>
|
||
<p>You can also use the <em>or</em> operator <code>|</code> in a match guard to specify multiple
|
||
patterns; the match guard condition will apply to all the patterns. Listing
|
||
19-28 shows the precedence when combining a pattern that uses <code>|</code> with a match
|
||
guard. The important part of this example is that the <code>if y</code> match guard
|
||
applies to <code>4</code>, <code>5</code>, <em>and</em> <code>6</code>, even though it might look like <code>if y</code> only
|
||
applies to <code>6</code>.</p>
|
||
<figure class="listing" id="listing-19-28">
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> let x = 4;
|
||
let y = false;
|
||
|
||
match x {
|
||
4 | 5 | 6 if y => println!("yes"),
|
||
_ => println!("no"),
|
||
}
|
||
<span class="boring">}</span></code></pre>
|
||
<figcaption><a href="#listing-19-28">Listing 19-28</a>: Combining multiple patterns with a match guard</figcaption>
|
||
</figure>
|
||
<p>The match condition states that the arm only matches if the value of <code>x</code> is
|
||
equal to <code>4</code>, <code>5</code>, or <code>6</code> <em>and</em> if <code>y</code> is <code>true</code>. When this code runs, the
|
||
pattern of the first arm matches because <code>x</code> is <code>4</code>, but the match guard <code>if y</code>
|
||
is <code>false</code>, so the first arm is not chosen. The code moves on to the second
|
||
arm, which does match, and this program prints <code>no</code>. The reason is that the
|
||
<code>if</code> condition applies to the whole pattern <code>4 | 5 | 6</code>, not just to the last
|
||
value <code>6</code>. In other words, the precedence of a match guard in relation to a
|
||
pattern behaves like this:</p>
|
||
<pre><code class="language-text">(4 | 5 | 6) if y => ...
|
||
</code></pre>
|
||
<p>rather than this:</p>
|
||
<pre><code class="language-text">4 | 5 | (6 if y) => ...
|
||
</code></pre>
|
||
<p>After running the code, the precedence behavior is evident: If the match guard
|
||
were applied only to the final value in the list of values specified using the
|
||
<code>|</code> operator, the arm would have matched, and the program would have printed
|
||
<code>yes</code>.</p>
|
||
<!-- Old headings. Do not remove or links may break. -->
|
||
<p><a id="-bindings"></a></p>
|
||
<h3 id="using--bindings"><a class="header" href="#using--bindings">Using <code>@</code> Bindings</a></h3>
|
||
<p>The <em>at</em> operator <code>@</code> lets us create a variable that holds a value at the same
|
||
time we’re testing that value for a pattern match. In Listing 19-29, we want to
|
||
test that a <code>Message::Hello</code> <code>id</code> field is within the range <code>3..=7</code>. We also
|
||
want to bind the value to the variable <code>id</code> so that we can use it in the code
|
||
associated with the arm.</p>
|
||
<figure class="listing" id="listing-19-29">
|
||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||
</span> enum Message {
|
||
Hello { id: i32 },
|
||
}
|
||
|
||
let msg = Message::Hello { id: 5 };
|
||
|
||
match msg {
|
||
Message::Hello { id: id @ 3..=7 } => {
|
||
println!("Found an id in range: {id}")
|
||
}
|
||
Message::Hello { id: 10..=12 } => {
|
||
println!("Found an id in another range")
|
||
}
|
||
Message::Hello { id } => println!("Found some other id: {id}"),
|
||
}
|
||
<span class="boring">}</span></code></pre>
|
||
<figcaption><a href="#listing-19-29">Listing 19-29</a>: Using <code>@</code> to bind to a value in a pattern while also testing it</figcaption>
|
||
</figure>
|
||
<p>This example will print <code>Found an id in range: 5</code>. By specifying <code>id @</code> before
|
||
the range <code>3..=7</code>, we’re capturing whatever value matched the range in a
|
||
variable named <code>id</code> while also testing that the value matched the range pattern.</p>
|
||
<p>In the second arm, where we only have a range specified in the pattern, the code
|
||
associated with the arm doesn’t have a variable that contains the actual value
|
||
of the <code>id</code> field. The <code>id</code> field’s value could have been 10, 11, or 12, but
|
||
the code that goes with that pattern doesn’t know which it is. The pattern code
|
||
isn’t able to use the value from the <code>id</code> field because we haven’t saved the
|
||
<code>id</code> value in a variable.</p>
|
||
<p>In the last arm, where we’ve specified a variable without a range, we do have
|
||
the value available to use in the arm’s code in a variable named <code>id</code>. The
|
||
reason is that we’ve used the struct field shorthand syntax. But we haven’t
|
||
applied any test to the value in the <code>id</code> field in this arm, as we did with the
|
||
first two arms: Any value would match this pattern.</p>
|
||
<p>Using <code>@</code> lets us test a value and save it in a variable within one pattern.</p>
|
||
<h2 id="summary"><a class="header" href="#summary">Summary</a></h2>
|
||
<p>Rust’s patterns are very useful in distinguishing between different kinds of
|
||
data. When used in <code>match</code> expressions, Rust ensures that your patterns cover
|
||
every possible value, or your program won’t compile. Patterns in <code>let</code>
|
||
statements and function parameters make those constructs more useful, enabling
|
||
the destructuring of values into smaller parts and assigning those parts to
|
||
variables. We can create simple or complex patterns to suit our needs.</p>
|
||
<p>Next, for the penultimate chapter of the book, we’ll look at some advanced
|
||
aspects of a variety of Rust’s features.</p>
|
||
|
||
</main>
|
||
|
||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||
<!-- Mobile navigation buttons -->
|
||
<a rel="prev" href="ch19-02-refutability.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="ch20-00-advanced-features.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="ch19-02-refutability.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="ch20-00-advanced-features.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>
|