feat: added cleanscript
This commit is contained in:
12
ch19/ch19-00-advanced-features.html
Normal file
12
ch19/ch19-00-advanced-features.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Redirecting...</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to... <a href="../ch20/ch20-00-advanced-features.html">ch20-00-advanced-features.html</a>.</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
35
ch19/ch19-00-patterns.html
Normal file
35
ch19/ch19-00-patterns.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Patterns and Matching</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="patterns-and-matching"><a class="header" href="#patterns-and-matching">Patterns and Matching</a></h1>
|
||||
<p>Patterns are a special syntax in Rust for matching against the structure of
|
||||
types, both complex and simple. Using patterns in conjunction with <code>match</code>
|
||||
expressions and other constructs gives you more control over a program’s
|
||||
control flow. A pattern consists of some combination of the following:</p>
|
||||
<ul>
|
||||
<li>Literals</li>
|
||||
<li>Destructured arrays, enums, structs, or tuples</li>
|
||||
<li>Variables</li>
|
||||
<li>Wildcards</li>
|
||||
<li>Placeholders</li>
|
||||
</ul>
|
||||
<p>Some example patterns include <code>x</code>, <code>(a, 3)</code>, and <code>Some(Color::Red)</code>. In the
|
||||
contexts in which patterns are valid, these components describe the shape of
|
||||
data. Our program then matches values against the patterns to determine whether
|
||||
it has the correct shape of data to continue running a particular piece of code.</p>
|
||||
<p>To use a pattern, we compare it to some value. If the pattern matches the
|
||||
value, we use the value parts in our code. Recall the <code>match</code> expressions in
|
||||
Chapter 6 that used patterns, such as the coin-sorting machine example. If the
|
||||
value fits the shape of the pattern, we can use the named pieces. If it
|
||||
doesn’t, the code associated with the pattern won’t run.</p>
|
||||
<p>This chapter is a reference on all things related to patterns. We’ll cover the
|
||||
valid places to use patterns, the difference between refutable and irrefutable
|
||||
patterns, and the different kinds of pattern syntax that you might see. By the
|
||||
end of the chapter, you’ll know how to use patterns to express many concepts in
|
||||
a clear way.</p>
|
||||
</body>
|
||||
</html>
|
||||
261
ch19/ch19-01-all-the-places-for-patterns.html
Normal file
261
ch19/ch19-01-all-the-places-for-patterns.html
Normal file
@@ -0,0 +1,261 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>All the Places Patterns Can Be Used</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2 id="all-the-places-patterns-can-be-used"><a class="header" href="#all-the-places-patterns-can-be-used">All the Places Patterns Can Be Used</a></h2>
|
||||
<p>Patterns pop up in a number of places in Rust, and you’ve been using them a lot
|
||||
without realizing it! This section discusses all the places where patterns are
|
||||
valid.</p>
|
||||
<h3 id="match-arms"><a class="header" href="#match-arms"><code>match</code> Arms</a></h3>
|
||||
<p>As discussed in Chapter 6, we use patterns in the arms of <code>match</code> expressions.
|
||||
Formally, <code>match</code> expressions are defined as the keyword <code>match</code>, a value to
|
||||
match on, and one or more match arms that consist of a pattern and an
|
||||
expression to run if the value matches that arm’s pattern, like this:</p>
|
||||
<!--
|
||||
Manually formatted rather than using Markdown intentionally: Markdown does not
|
||||
support italicizing code in the body of a block like this!
|
||||
-->
|
||||
<pre><code>match <em>VALUE</em> {
|
||||
<em>PATTERN</em> => <em>EXPRESSION</em>,
|
||||
<em>PATTERN</em> => <em>EXPRESSION</em>,
|
||||
<em>PATTERN</em> => <em>EXPRESSION</em>,
|
||||
}</code></pre>
|
||||
|
||||
<p>For example, here’s the <code>match</code> expression from Listing 6-5 that matches on an
|
||||
<code>Option<i32></code> value in the variable <code>x</code>:</p>
|
||||
<pre><code class="language-rust ignore">match x {
|
||||
None => None,
|
||||
Some(i) => Some(i + 1),
|
||||
}</code></pre>
|
||||
<p>The patterns in this <code>match</code> expression are the <code>None</code> and <code>Some(i)</code> to the
|
||||
left of each arrow.</p>
|
||||
<p>One requirement for <code>match</code> expressions is that they need to be exhaustive in
|
||||
the sense that all possibilities for the value in the <code>match</code> expression must
|
||||
be accounted for. One way to ensure that you’ve covered every possibility is to
|
||||
have a catch-all pattern for the last arm: For example, a variable name
|
||||
matching any value can never fail and thus covers every remaining case.</p>
|
||||
<p>The particular pattern <code>_</code> will match anything, but it never binds to a
|
||||
variable, so it’s often used in the last match arm. The <code>_</code> pattern can be
|
||||
useful when you want to ignore any value not specified, for example. We’ll
|
||||
cover the <code>_</code> pattern in more detail in <a href="ch19-03-pattern-syntax.html#ignoring-values-in-a-pattern">“Ignoring Values in a
|
||||
Pattern”</a><!-- ignore --> later in this chapter.</p>
|
||||
<h3 id="let-statements"><a class="header" href="#let-statements"><code>let</code> Statements</a></h3>
|
||||
<p>Prior to this chapter, we had only explicitly discussed using patterns with
|
||||
<code>match</code> and <code>if let</code>, but in fact, we’ve used patterns in other places as well,
|
||||
including in <code>let</code> statements. For example, consider this straightforward
|
||||
variable assignment with <code>let</code>:</p>
|
||||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">#![allow(unused)]
|
||||
</span><span class="boring">fn main() {
|
||||
</span>let x = 5;
|
||||
<span class="boring">}</span></code></pre>
|
||||
<p>Every time you’ve used a <code>let</code> statement like this you’ve been using patterns,
|
||||
although you might not have realized it! More formally, a <code>let</code> statement looks
|
||||
like this:</p>
|
||||
<!--
|
||||
Manually formatted rather than using Markdown intentionally: Markdown does not
|
||||
support italicizing code in the body of a block like this!
|
||||
-->
|
||||
<pre>
|
||||
<code>let <em>PATTERN</em> = <em>EXPRESSION</em>;</code>
|
||||
</pre>
|
||||
|
||||
<p>In statements like <code>let x = 5;</code> with a variable name in the PATTERN slot, the
|
||||
variable name is just a particularly simple form of a pattern. Rust compares
|
||||
the expression against the pattern and assigns any names it finds. So, in the
|
||||
<code>let x = 5;</code> example, <code>x</code> is a pattern that means “bind what matches here to
|
||||
the variable <code>x</code>.” Because the name <code>x</code> is the whole pattern, this pattern
|
||||
effectively means “bind everything to the variable <code>x</code>, whatever the value is.”</p>
|
||||
<p>To see the pattern-matching aspect of <code>let</code> more clearly, consider Listing
|
||||
19-1, which uses a pattern with <code>let</code> to destructure a tuple.</p>
|
||||
<figure class="listing" id="listing-19-1">
|
||||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||||
</span> let (x, y, z) = (1, 2, 3);
|
||||
<span class="boring">}</span></code></pre>
|
||||
<figcaption><a href="#listing-19-1">Listing 19-1</a>: Using a pattern to destructure a tuple and create three variables at once</figcaption>
|
||||
</figure>
|
||||
<p>Here, we match a tuple against a pattern. Rust compares the value <code>(1, 2, 3)</code>
|
||||
to the pattern <code>(x, y, z)</code> and sees that the value matches the pattern—that is,
|
||||
it sees that the number of elements is the same in both—so Rust binds <code>1</code> to
|
||||
<code>x</code>, <code>2</code> to <code>y</code>, and <code>3</code> to <code>z</code>. You can think of this tuple pattern as nesting
|
||||
three individual variable patterns inside it.</p>
|
||||
<p>If the number of elements in the pattern doesn’t match the number of elements
|
||||
in the tuple, the overall type won’t match and we’ll get a compiler error. For
|
||||
example, Listing 19-2 shows an attempt to destructure a tuple with three
|
||||
elements into two variables, which won’t work.</p>
|
||||
<figure class="listing" id="listing-19-2">
|
||||
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
|
||||
</span> let (x, y) = (1, 2, 3);
|
||||
<span class="boring">}</span></code></pre>
|
||||
<figcaption><a href="#listing-19-2">Listing 19-2</a>: Incorrectly constructing a pattern whose variables don’t match the number of elements in the tuple</figcaption>
|
||||
</figure>
|
||||
<p>Attempting to compile this code results in this type error:</p>
|
||||
<pre><code class="language-console">$ cargo run
|
||||
Compiling patterns v0.1.0 (file:///projects/patterns)
|
||||
error[E0308]: mismatched types
|
||||
--> src/main.rs:2:9
|
||||
|
|
||||
2 | let (x, y) = (1, 2, 3);
|
||||
| ^^^^^^ --------- this expression has type `({integer}, {integer}, {integer})`
|
||||
| |
|
||||
| expected a tuple with 3 elements, found one with 2 elements
|
||||
|
|
||||
= note: expected tuple `({integer}, {integer}, {integer})`
|
||||
found tuple `(_, _)`
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
error: could not compile `patterns` (bin "patterns") due to 1 previous error
|
||||
</code></pre>
|
||||
<p>To fix the error, we could ignore one or more of the values in the tuple using
|
||||
<code>_</code> or <code>..</code>, as you’ll see in the <a href="ch19-03-pattern-syntax.html#ignoring-values-in-a-pattern">“Ignoring Values in a
|
||||
Pattern”</a><!-- ignore --> section. If the problem
|
||||
is that we have too many variables in the pattern, the solution is to make the
|
||||
types match by removing variables so that the number of variables equals the
|
||||
number of elements in the tuple.</p>
|
||||
<h3 id="conditional-if-let-expressions"><a class="header" href="#conditional-if-let-expressions">Conditional <code>if let</code> Expressions</a></h3>
|
||||
<p>In Chapter 6, we discussed how to use <code>if let</code> expressions mainly as a shorter
|
||||
way to write the equivalent of a <code>match</code> that only matches one case.
|
||||
Optionally, <code>if let</code> can have a corresponding <code>else</code> containing code to run if
|
||||
the pattern in the <code>if let</code> doesn’t match.</p>
|
||||
<p>Listing 19-3 shows that it’s also possible to mix and match <code>if let</code>, <code>else if</code>, and <code>else if let</code> expressions. Doing so gives us more flexibility than a
|
||||
<code>match</code> expression in which we can express only one value to compare with the
|
||||
patterns. Also, Rust doesn’t require that the conditions in a series of <code>if let</code>, <code>else if</code>, and <code>else if let</code> arms relate to each other.</p>
|
||||
<p>The code in Listing 19-3 determines what color to make your background based on
|
||||
a series of checks for several conditions. For this example, we’ve created
|
||||
variables with hardcoded values that a real program might receive from user
|
||||
input.</p>
|
||||
<figure class="listing" id="listing-19-3">
|
||||
<span class="file-name">Filename: src/main.rs</span>
|
||||
<pre class="playground"><code class="language-rust edition2024">fn main() {
|
||||
let favorite_color: Option<&str> = None;
|
||||
let is_tuesday = false;
|
||||
let age: Result<u8, _> = "34".parse();
|
||||
|
||||
if let Some(color) = favorite_color {
|
||||
println!("Using your favorite color, {color}, as the background");
|
||||
} else if is_tuesday {
|
||||
println!("Tuesday is green day!");
|
||||
} else if let Ok(age) = age {
|
||||
if age > 30 {
|
||||
println!("Using purple as the background color");
|
||||
} else {
|
||||
println!("Using orange as the background color");
|
||||
}
|
||||
} else {
|
||||
println!("Using blue as the background color");
|
||||
}
|
||||
}</code></pre>
|
||||
<figcaption><a href="#listing-19-3">Listing 19-3</a>: Mixing <code>if let</code>, <code>else if</code>, <code>else if let</code>, and <code>else</code></figcaption>
|
||||
</figure>
|
||||
<p>If the user specifies a favorite color, that color is used as the background.
|
||||
If no favorite color is specified and today is Tuesday, the background color is
|
||||
green. Otherwise, if the user specifies their age as a string and we can parse
|
||||
it as a number successfully, the color is either purple or orange depending on
|
||||
the value of the number. If none of these conditions apply, the background
|
||||
color is blue.</p>
|
||||
<p>This conditional structure lets us support complex requirements. With the
|
||||
hardcoded values we have here, this example will print <code>Using purple as the background color</code>.</p>
|
||||
<p>You can see that <code>if let</code> can also introduce new variables that shadow existing
|
||||
variables in the same way that <code>match</code> arms can: The line <code>if let Ok(age) = age</code>
|
||||
introduces a new <code>age</code> variable that contains the value inside the <code>Ok</code> variant,
|
||||
shadowing the existing <code>age</code> variable. This means we need to place the <code>if age > 30</code> condition within that block: We can’t combine these two conditions into <code>if let Ok(age) = age && age > 30</code>. The new <code>age</code> we want to compare to 30 isn’t
|
||||
valid until the new scope starts with the curly bracket.</p>
|
||||
<p>The downside of using <code>if let</code> expressions is that the compiler doesn’t check
|
||||
for exhaustiveness, whereas with <code>match</code> expressions it does. If we omitted the
|
||||
last <code>else</code> block and therefore missed handling some cases, the compiler would
|
||||
not alert us to the possible logic bug.</p>
|
||||
<h3 id="while-let-conditional-loops"><a class="header" href="#while-let-conditional-loops"><code>while let</code> Conditional Loops</a></h3>
|
||||
<p>Similar in construction to <code>if let</code>, the <code>while let</code> conditional loop allows a
|
||||
<code>while</code> loop to run for as long as a pattern continues to match. In Listing
|
||||
19-4, we show a <code>while let</code> loop that waits on messages sent between threads,
|
||||
but in this case checking a <code>Result</code> instead of an <code>Option</code>.</p>
|
||||
<figure class="listing" id="listing-19-4">
|
||||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||||
</span> let (tx, rx) = std::sync::mpsc::channel();
|
||||
std::thread::spawn(move || {
|
||||
for val in [1, 2, 3] {
|
||||
tx.send(val).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
while let Ok(value) = rx.recv() {
|
||||
println!("{value}");
|
||||
}
|
||||
<span class="boring">}</span></code></pre>
|
||||
<figcaption><a href="#listing-19-4">Listing 19-4</a>: Using a <code>while let</code> loop to print values for as long as <code>rx.recv()</code> returns <code>Ok</code></figcaption>
|
||||
</figure>
|
||||
<p>This example prints <code>1</code>, <code>2</code>, and then <code>3</code>. The <code>recv</code> method takes the first
|
||||
message out of the receiver side of the channel and returns an <code>Ok(value)</code>. When
|
||||
we first saw <code>recv</code> back in Chapter 16, we unwrapped the error directly, or
|
||||
we interacted with it as an iterator using a <code>for</code> loop. As Listing 19-4 shows,
|
||||
though, we can also use <code>while let</code>, because the <code>recv</code> method returns an <code>Ok</code>
|
||||
each time a message arrives, as long as the sender exists, and then produces an
|
||||
<code>Err</code> once the sender side disconnects.</p>
|
||||
<h3 id="for-loops"><a class="header" href="#for-loops"><code>for</code> Loops</a></h3>
|
||||
<p>In a <code>for</code> loop, the value that directly follows the keyword <code>for</code> is a
|
||||
pattern. For example, in <code>for x in y</code>, the <code>x</code> is the pattern. Listing 19-5
|
||||
demonstrates how to use a pattern in a <code>for</code> loop to destructure, or break
|
||||
apart, a tuple as part of the <code>for</code> loop.</p>
|
||||
<figure class="listing" id="listing-19-5">
|
||||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||||
</span> let v = vec!['a', 'b', 'c'];
|
||||
|
||||
for (index, value) in v.iter().enumerate() {
|
||||
println!("{value} is at index {index}");
|
||||
}
|
||||
<span class="boring">}</span></code></pre>
|
||||
<figcaption><a href="#listing-19-5">Listing 19-5</a>: Using a pattern in a <code>for</code> loop to destructure a tuple</figcaption>
|
||||
</figure>
|
||||
<p>The code in Listing 19-5 will print the following:</p>
|
||||
<pre><code class="language-console">$ cargo run
|
||||
Compiling patterns v0.1.0 (file:///projects/patterns)
|
||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.52s
|
||||
Running `target/debug/patterns`
|
||||
a is at index 0
|
||||
b is at index 1
|
||||
c is at index 2
|
||||
</code></pre>
|
||||
<p>We adapt an iterator using the <code>enumerate</code> method so that it produces a value
|
||||
and the index for that value, placed into a tuple. The first value produced is
|
||||
the tuple <code>(0, 'a')</code>. When this value is matched to the pattern <code>(index, value)</code>, index will be <code>0</code> and value will be <code>'a'</code>, printing the first line of
|
||||
the output.</p>
|
||||
<h3 id="function-parameters"><a class="header" href="#function-parameters">Function Parameters</a></h3>
|
||||
<p>Function parameters can also be patterns. The code in Listing 19-6, which
|
||||
declares a function named <code>foo</code> that takes one parameter named <code>x</code> of type
|
||||
<code>i32</code>, should by now look familiar.</p>
|
||||
<figure class="listing" id="listing-19-6">
|
||||
<pre class="playground"><code class="language-rust edition2024">fn foo(x: i32) {
|
||||
// code goes here
|
||||
}
|
||||
<span class="boring">
|
||||
</span><span class="boring">fn main() {}</span></code></pre>
|
||||
<figcaption><a href="#listing-19-6">Listing 19-6</a>: A function signature using patterns in the parameters</figcaption>
|
||||
</figure>
|
||||
<p>The <code>x</code> part is a pattern! As we did with <code>let</code>, we could match a tuple in a
|
||||
function’s arguments to the pattern. Listing 19-7 splits the values in a tuple
|
||||
as we pass it to a function.</p>
|
||||
<figure class="listing" id="listing-19-7">
|
||||
<span class="file-name">Filename: src/main.rs</span>
|
||||
<pre class="playground"><code class="language-rust edition2024">fn print_coordinates(&(x, y): &(i32, i32)) {
|
||||
println!("Current location: ({x}, {y})");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let point = (3, 5);
|
||||
print_coordinates(&point);
|
||||
}</code></pre>
|
||||
<figcaption><a href="#listing-19-7">Listing 19-7</a>: A function with parameters that destructure a tuple</figcaption>
|
||||
</figure>
|
||||
<p>This code prints <code>Current location: (3, 5)</code>. The values <code>&(3, 5)</code> match the
|
||||
pattern <code>&(x, y)</code>, so <code>x</code> is the value <code>3</code> and <code>y</code> is the value <code>5</code>.</p>
|
||||
<p>We can also use patterns in closure parameter lists in the same way as in
|
||||
function parameter lists because closures are similar to functions, as
|
||||
discussed in Chapter 13.</p>
|
||||
<p>At this point, you’ve seen several ways to use patterns, but patterns don’t
|
||||
work the same in every place we can use them. In some places, the patterns must
|
||||
be irrefutable; in other circumstances, they can be refutable. We’ll discuss
|
||||
these two concepts next.</p>
|
||||
</body>
|
||||
</html>
|
||||
12
ch19/ch19-01-unsafe-rust.html
Normal file
12
ch19/ch19-01-unsafe-rust.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Redirecting...</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to... <a href="../ch20/ch20-01-unsafe-rust.html">ch20-01-unsafe-rust.html</a>.</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
117
ch19/ch19-02-refutability.html
Normal file
117
ch19/ch19-02-refutability.html
Normal file
@@ -0,0 +1,117 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Refutability: Whether a Pattern Might Fail to Match</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2 id="refutability-whether-a-pattern-might-fail-to-match"><a class="header" href="#refutability-whether-a-pattern-might-fail-to-match">Refutability: Whether a Pattern Might Fail to Match</a></h2>
|
||||
<p>Patterns come in two forms: refutable and irrefutable. Patterns that will match
|
||||
for any possible value passed are <em>irrefutable</em>. An example would be <code>x</code> in the
|
||||
statement <code>let x = 5;</code> because <code>x</code> matches anything and therefore cannot fail
|
||||
to match. Patterns that can fail to match for some possible value are
|
||||
<em>refutable</em>. An example would be <code>Some(x)</code> in the expression <code>if let Some(x) = a_value</code> because if the value in the <code>a_value</code> variable is <code>None</code> rather than
|
||||
<code>Some</code>, the <code>Some(x)</code> pattern will not match.</p>
|
||||
<p>Function parameters, <code>let</code> statements, and <code>for</code> loops can only accept
|
||||
irrefutable patterns because the program cannot do anything meaningful when
|
||||
values don’t match. The <code>if let</code> and <code>while let</code> expressions and the
|
||||
<code>let...else</code> statement accept refutable and irrefutable patterns, but the
|
||||
compiler warns against irrefutable patterns because, by definition, they’re
|
||||
intended to handle possible failure: The functionality of a conditional is in
|
||||
its ability to perform differently depending on success or failure.</p>
|
||||
<p>In general, you shouldn’t have to worry about the distinction between refutable
|
||||
and irrefutable patterns; however, you do need to be familiar with the concept
|
||||
of refutability so that you can respond when you see it in an error message. In
|
||||
those cases, you’ll need to change either the pattern or the construct you’re
|
||||
using the pattern with, depending on the intended behavior of the code.</p>
|
||||
<p>Let’s look at an example of what happens when we try to use a refutable pattern
|
||||
where Rust requires an irrefutable pattern and vice versa. Listing 19-8 shows a
|
||||
<code>let</code> statement, but for the pattern, we’ve specified <code>Some(x)</code>, a refutable
|
||||
pattern. As you might expect, this code will not compile.</p>
|
||||
<figure class="listing" id="listing-19-8">
|
||||
<pre><code class="language-rust ignore does_not_compile"><span class="boring">fn main() {
|
||||
</span><span class="boring"> let some_option_value: Option<i32> = None;
|
||||
</span> let Some(x) = some_option_value;
|
||||
<span class="boring">}</span></code></pre>
|
||||
<figcaption><a href="#listing-19-8">Listing 19-8</a>: Attempting to use a refutable pattern with <code>let</code></figcaption>
|
||||
</figure>
|
||||
<p>If <code>some_option_value</code> were a <code>None</code> value, it would fail to match the pattern
|
||||
<code>Some(x)</code>, meaning the pattern is refutable. However, the <code>let</code> statement can
|
||||
only accept an irrefutable pattern because there is nothing valid the code can
|
||||
do with a <code>None</code> value. At compile time, Rust will complain that we’ve tried to
|
||||
use a refutable pattern where an irrefutable pattern is required:</p>
|
||||
<pre><code class="language-console">$ cargo run
|
||||
Compiling patterns v0.1.0 (file:///projects/patterns)
|
||||
error[E0005]: refutable pattern in local binding
|
||||
--> src/main.rs:3:9
|
||||
|
|
||||
3 | let Some(x) = some_option_value;
|
||||
| ^^^^^^^ pattern `None` not covered
|
||||
|
|
||||
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html
|
||||
= note: the matched value is of type `Option<i32>`
|
||||
help: you might want to use `let else` to handle the variant that isn't matched
|
||||
|
|
||||
3 | let Some(x) = some_option_value else { todo!() };
|
||||
| ++++++++++++++++
|
||||
|
||||
For more information about this error, try `rustc --explain E0005`.
|
||||
error: could not compile `patterns` (bin "patterns") due to 1 previous error
|
||||
</code></pre>
|
||||
<p>Because we didn’t cover (and couldn’t cover!) every valid value with the
|
||||
pattern <code>Some(x)</code>, Rust rightfully produces a compiler error.</p>
|
||||
<p>If we have a refutable pattern where an irrefutable pattern is needed, we can
|
||||
fix it by changing the code that uses the pattern: Instead of using <code>let</code>, we
|
||||
can use <code>let...else</code>. Then, if the pattern doesn’t match, the code in the curly
|
||||
brackets will handle the value. Listing 19-9 shows how to fix the code in
|
||||
Listing 19-8.</p>
|
||||
<figure class="listing" id="listing-19-9">
|
||||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||||
</span><span class="boring"> let some_option_value: Option<i32> = None;
|
||||
</span> let Some(x) = some_option_value else {
|
||||
return;
|
||||
};
|
||||
<span class="boring">}</span></code></pre>
|
||||
<figcaption><a href="#listing-19-9">Listing 19-9</a>: Using <code>let...else</code> and a block with refutable patterns instead of <code>let</code></figcaption>
|
||||
</figure>
|
||||
<p>We’ve given the code an out! This code is perfectly valid, although it means we
|
||||
cannot use an irrefutable pattern without receiving a warning. If we give
|
||||
<code>let...else</code> a pattern that will always match, such as <code>x</code>, as shown in Listing
|
||||
19-10, the compiler will give a warning.</p>
|
||||
<figure class="listing" id="listing-19-10">
|
||||
<pre class="playground"><code class="language-rust edition2024"><span class="boring">fn main() {
|
||||
</span> let x = 5 else {
|
||||
return;
|
||||
};
|
||||
<span class="boring">}</span></code></pre>
|
||||
<figcaption><a href="#listing-19-10">Listing 19-10</a>: Attempting to use an irrefutable pattern with <code>let...else</code></figcaption>
|
||||
</figure>
|
||||
<p>Rust complains that it doesn’t make sense to use <code>let...else</code> with an
|
||||
irrefutable pattern:</p>
|
||||
<pre><code class="language-console">$ cargo run
|
||||
Compiling patterns v0.1.0 (file:///projects/patterns)
|
||||
warning: irrefutable `let...else` pattern
|
||||
--> src/main.rs:2:5
|
||||
|
|
||||
2 | let x = 5 else {
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: this pattern will always match, so the `else` clause is useless
|
||||
= help: consider removing the `else` clause
|
||||
= note: `#[warn(irrefutable_let_patterns)]` on by default
|
||||
|
||||
warning: `patterns` (bin "patterns") generated 1 warning
|
||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.39s
|
||||
Running `target/debug/patterns`
|
||||
</code></pre>
|
||||
<p>For this reason, match arms must use refutable patterns, except for the last
|
||||
arm, which should match any remaining values with an irrefutable pattern. Rust
|
||||
allows us to use an irrefutable pattern in a <code>match</code> with only one arm, but
|
||||
this syntax isn’t particularly useful and could be replaced with a simpler
|
||||
<code>let</code> statement.</p>
|
||||
<p>Now that you know where to use patterns and the difference between refutable
|
||||
and irrefutable patterns, let’s cover all the syntax we can use to create
|
||||
patterns.</p>
|
||||
</body>
|
||||
</html>
|
||||
12
ch19/ch19-03-advanced-traits.html
Normal file
12
ch19/ch19-03-advanced-traits.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Redirecting...</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to... <a href="../ch20/ch20-02-advanced-traits.html">ch20-02-advanced-traits.html</a>.</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
707
ch19/ch19-03-pattern-syntax.html
Normal file
707
ch19/ch19-03-pattern-syntax.html
Normal file
@@ -0,0 +1,707 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Pattern Syntax</title>
|
||||
</head>
|
||||
<body>
|
||||
<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>
|
||||
</body>
|
||||
</html>
|
||||
12
ch19/ch19-04-advanced-types.html
Normal file
12
ch19/ch19-04-advanced-types.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Redirecting...</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to... <a href="../ch20/ch20-03-advanced-types.html">ch20-03-advanced-types.html</a>.</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
12
ch19/ch19-05-advanced-functions-and-closures.html
Normal file
12
ch19/ch19-05-advanced-functions-and-closures.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Redirecting...</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to... <a href="../ch20/ch20-04-advanced-functions-and-closures.html">ch20-04-advanced-functions-and-closures.html</a>.</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
12
ch19/ch19-06-macros.html
Normal file
12
ch19/ch19-06-macros.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Redirecting...</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Redirecting to... <a href="../ch20/ch20-05-macros.html">ch20-05-macros.html</a>.</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user