Sophie

Sophie

distrib > Mageia > 6 > x86_64 > media > core-updates > by-pkgid > 878cdd00a13d17a73c6619a777ef5d74 > files > 277

rust-doc-1.19.0-1.mga6.x86_64.rpm

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Improving our I/O Project - The Rust Programming Language</title>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <base href="">

        <link rel="stylesheet" href="book.css">
        <link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>

        <link rel="shortcut icon" href="favicon.png">

        <!-- Font Awesome -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

        <link rel="stylesheet" href="highlight.css">
        <link rel="stylesheet" href="tomorrow-night.css">
        <style>
            .page-wrapper.has-warning > .nav-chapters {
              /* add height for warning content & margin */
              top: 120px;
            }

            p.warning {
                background-color: rgb(242, 222, 222);
                border-bottom-color: rgb(238, 211, 215);
                border-bottom-left-radius: 4px;
                border-bottom-right-radius: 4px;
                border-bottom-style: solid;
                border-bottom-width: 0.666667px;
                border-image-outset: 0 0 0 0;
                border-image-repeat: stretch stretch;
                border-image-slice: 100% 100% 100% 100%;
                border-image-source: none;
                border-image-width: 1 1 1 1;
                border-left-color: rgb(238, 211, 215);
                border-left-style: solid;
                border-left-width: 0.666667px;
                border-right-color: rgb(238, 211, 215);
                border-right-style: solid;
                border-right-width: 0.666667px;
                border-top-color: rgb(238, 211, 215);
                border-top-left-radius: 4px;
                border-top-right-radius: 4px;
                border-top-style: solid;
                border-top-width: 0.666667px;
                color: rgb(185, 74, 72);
                margin-bottom: 0px;
                margin-left: 0px;
                margin-right: 0px;
                margin-top: 30px;
                padding-bottom: 8px;
                padding-left: 14px;
                padding-right: 35px;
                padding-top: 8px;
            }
            p.warning strong {
                color: rgb(185, 74, 72)
            }
            p.warning a {
                color: rgb(0, 136, 204)
            }
        </style>

        <!-- MathJax -->
        <script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>

        <!-- Fetch JQuery from CDN but have a local fallback -->
        <script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
        <script>
            if (typeof jQuery == 'undefined') {
                document.write(unescape("%3Cscript src='jquery.js'%3E%3C/script%3E"));
            }
        </script>
    </head>
    <body class="light">
        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme = localStorage.getItem('theme');
            if (theme == null) { theme = 'light'; }
            $('body').removeClass().addClass(theme);
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var sidebar = localStorage.getItem('sidebar');
            if (sidebar === "hidden") { $("html").addClass("sidebar-hidden") }
            else if (sidebar === "visible") { $("html").addClass("sidebar-visible") }
        </script>

        <div id="sidebar" class="sidebar">
            <ul class="chapter"><li><a href="ch01-00-introduction.html"><strong>1.</strong> Introduction</a></li><li><ul class="section"><li><a href="ch01-01-installation.html"><strong>1.1.</strong> Installation</a></li><li><a href="ch01-02-hello-world.html"><strong>1.2.</strong> Hello, World!</a></li></ul></li><li><a href="ch02-00-guessing-game-tutorial.html"><strong>2.</strong> Guessing Game Tutorial</a></li><li><a href="ch03-00-common-programming-concepts.html"><strong>3.</strong> Common Programming Concepts</a></li><li><ul class="section"><li><a href="ch03-01-variables-and-mutability.html"><strong>3.1.</strong> Variables and Mutability</a></li><li><a href="ch03-02-data-types.html"><strong>3.2.</strong> Data Types</a></li><li><a href="ch03-03-how-functions-work.html"><strong>3.3.</strong> How Functions Work</a></li><li><a href="ch03-04-comments.html"><strong>3.4.</strong> Comments</a></li><li><a href="ch03-05-control-flow.html"><strong>3.5.</strong> Control Flow</a></li></ul></li><li><a href="ch04-00-understanding-ownership.html"><strong>4.</strong> Understanding Ownership</a></li><li><ul class="section"><li><a href="ch04-01-what-is-ownership.html"><strong>4.1.</strong> What is Ownership?</a></li><li><a href="ch04-02-references-and-borrowing.html"><strong>4.2.</strong> References &amp; Borrowing</a></li><li><a href="ch04-03-slices.html"><strong>4.3.</strong> Slices</a></li></ul></li><li><a href="ch05-00-structs.html"><strong>5.</strong> Using Structs to Structure Related Data</a></li><li><ul class="section"><li><a href="ch05-01-defining-structs.html"><strong>5.1.</strong> Defining and Instantiating Structs</a></li><li><a href="ch05-02-example-structs.html"><strong>5.2.</strong> An Example Program Using Structs</a></li><li><a href="ch05-03-method-syntax.html"><strong>5.3.</strong> Method Syntax</a></li></ul></li><li><a href="ch06-00-enums.html"><strong>6.</strong> Enums and Pattern Matching</a></li><li><ul class="section"><li><a href="ch06-01-defining-an-enum.html"><strong>6.1.</strong> Defining an Enum</a></li><li><a href="ch06-02-match.html"><strong>6.2.</strong> The <code>match</code> Control Flow Operator</a></li><li><a href="ch06-03-if-let.html"><strong>6.3.</strong> Concise Control Flow with <code>if let</code></a></li></ul></li><li><a href="ch07-00-modules.html"><strong>7.</strong> Modules</a></li><li><ul class="section"><li><a href="ch07-01-mod-and-the-filesystem.html"><strong>7.1.</strong> <code>mod</code> and the Filesystem</a></li><li><a href="ch07-02-controlling-visibility-with-pub.html"><strong>7.2.</strong> Controlling Visibility with <code>pub</code></a></li><li><a href="ch07-03-importing-names-with-use.html"><strong>7.3.</strong> Importing Names with <code>use</code></a></li></ul></li><li><a href="ch08-00-common-collections.html"><strong>8.</strong> Common Collections</a></li><li><ul class="section"><li><a href="ch08-01-vectors.html"><strong>8.1.</strong> Vectors</a></li><li><a href="ch08-02-strings.html"><strong>8.2.</strong> Strings</a></li><li><a href="ch08-03-hash-maps.html"><strong>8.3.</strong> Hash Maps</a></li></ul></li><li><a href="ch09-00-error-handling.html"><strong>9.</strong> Error Handling</a></li><li><ul class="section"><li><a href="ch09-01-unrecoverable-errors-with-panic.html"><strong>9.1.</strong> Unrecoverable Errors with <code>panic!</code></a></li><li><a href="ch09-02-recoverable-errors-with-result.html"><strong>9.2.</strong> Recoverable Errors with <code>Result</code></a></li><li><a href="ch09-03-to-panic-or-not-to-panic.html"><strong>9.3.</strong> To <code>panic!</code> or Not To <code>panic!</code></a></li></ul></li><li><a href="ch10-00-generics.html"><strong>10.</strong> Generic Types, Traits, and Lifetimes</a></li><li><ul class="section"><li><a href="ch10-01-syntax.html"><strong>10.1.</strong> Generic Data Types</a></li><li><a href="ch10-02-traits.html"><strong>10.2.</strong> Traits: Defining Shared Behavior</a></li><li><a href="ch10-03-lifetime-syntax.html"><strong>10.3.</strong> Validating References with Lifetimes</a></li></ul></li><li><a href="ch11-00-testing.html"><strong>11.</strong> Testing</a></li><li><ul class="section"><li><a href="ch11-01-writing-tests.html"><strong>11.1.</strong> Writing tests</a></li><li><a href="ch11-02-running-tests.html"><strong>11.2.</strong> Running tests</a></li><li><a href="ch11-03-test-organization.html"><strong>11.3.</strong> Test Organization</a></li></ul></li><li><a href="ch12-00-an-io-project.html"><strong>12.</strong> An I/O Project</a></li><li><ul class="section"><li><a href="ch12-01-accepting-command-line-arguments.html"><strong>12.1.</strong> Accepting Command Line Arguments</a></li><li><a href="ch12-02-reading-a-file.html"><strong>12.2.</strong> Reading a File</a></li><li><a href="ch12-03-improving-error-handling-and-modularity.html"><strong>12.3.</strong> Improving Error Handling and Modularity</a></li><li><a href="ch12-04-testing-the-librarys-functionality.html"><strong>12.4.</strong> Testing the Library's Functionality</a></li><li><a href="ch12-05-working-with-environment-variables.html"><strong>12.5.</strong> Working with Environment Variables</a></li><li><a href="ch12-06-writing-to-stderr-instead-of-stdout.html"><strong>12.6.</strong> Writing to <code>stderr</code> instead of <code>stdout</code></a></li></ul></li><li><a href="ch13-00-functional-features.html"><strong>13.</strong> Functional Language Features in Rust</a></li><li><ul class="section"><li><a href="ch13-01-closures.html"><strong>13.1.</strong> Closures</a></li><li><a href="ch13-02-iterators.html"><strong>13.2.</strong> Iterators</a></li><li><a href="ch13-03-improving-our-io-project.html" class="active"><strong>13.3.</strong> Improving our I/O Project</a></li><li><a href="ch13-04-performance.html"><strong>13.4.</strong> Performance</a></li></ul></li><li><a href="ch14-00-more-about-cargo.html"><strong>14.</strong> More about Cargo and Crates.io</a></li><li><ul class="section"><li><a href="ch14-01-release-profiles.html"><strong>14.1.</strong> Release Profiles</a></li><li><a href="ch14-02-publishing-to-crates-io.html"><strong>14.2.</strong> Publishing a Crate to Crates.io</a></li><li><a href="ch14-03-cargo-workspaces.html"><strong>14.3.</strong> Cargo Workspaces</a></li><li><a href="ch14-04-installing-binaries.html"><strong>14.4.</strong> Installing Binaries from Crates.io with <code>cargo install</code></a></li><li><a href="ch14-05-extending-cargo.html"><strong>14.5.</strong> Extending Cargo with Custom Commands</a></li></ul></li><li><a href="ch15-00-smart-pointers.html"><strong>15.</strong> Smart Pointers</a></li><li><ul class="section"><li><a href="ch15-01-box.html"><strong>15.1.</strong> <code>Box&lt;T&gt;</code> Points to Data on the Heap and Has a Known Size</a></li><li><a href="ch15-02-deref.html"><strong>15.2.</strong> The <code>Deref</code> Trait Allows Access to the Data Through a Reference</a></li><li><a href="ch15-03-drop.html"><strong>15.3.</strong> The <code>Drop</code> Trait Runs Code on Cleanup</a></li><li><a href="ch15-04-rc.html"><strong>15.4.</strong> <code>Rc&lt;T&gt;</code>, the Reference Counted Smart Pointer</a></li><li><a href="ch15-05-interior-mutability.html"><strong>15.5.</strong> <code>RefCell&lt;T&gt;</code> and the Interior Mutability Pattern</a></li><li><a href="ch15-06-reference-cycles.html"><strong>15.6.</strong> Creating Reference Cycles and Leaking Memory is Safe</a></li></ul></li><li><a href="ch16-00-concurrency.html"><strong>16.</strong> Fearless Concurrency</a></li><li><ul class="section"><li><a href="ch16-01-threads.html"><strong>16.1.</strong> Threads</a></li><li><a href="ch16-02-message-passing.html"><strong>16.2.</strong> Message Passing</a></li><li><a href="ch16-03-shared-state.html"><strong>16.3.</strong> Shared State</a></li><li><a href="ch16-04-extensible-concurrency-sync-and-send.html"><strong>16.4.</strong> Extensible Concurrency: <code>Sync</code> and <code>Send</code></a></li></ul></li><li><a href="ch17-00-oop.html"><strong>17.</strong> Is Rust an Object-Oriented Programming Language?</a></li><li><ul class="section"><li><a href="ch17-01-what-is-oo.html"><strong>17.1.</strong> What Does Object-Oriented Mean?</a></li><li><a href="ch17-02-trait-objects.html"><strong>17.2.</strong> Trait Objects for Using Values of Different Types</a></li><li><a href="ch17-03-oo-design-patterns.html"><strong>17.3.</strong> Object-Oriented Design Pattern Implementations</a></li></ul></li><li><a href="ch18-00-patterns.html"><strong>18.</strong> Patterns Match the Structure of Values</a></li><li><ul class="section"><li><a href="ch18-01-all-the-places-for-patterns.html"><strong>18.1.</strong> All the Places Patterns May be Used</a></li><li><a href="ch18-02-refutability.html"><strong>18.2.</strong> Refutability: Whether a Pattern Might Fail to Match</a></li><li><a href="ch18-03-pattern-syntax.html"><strong>18.3.</strong> All the Pattern Syntax</a></li></ul></li><li><a href="ch19-00-advanced-features.html"><strong>19.</strong> Advanced Features</a></li><li><ul class="section"><li><a href="ch19-01-unsafe-rust.html"><strong>19.1.</strong> Unsafe Rust</a></li><li><a href="ch19-02-advanced-lifetimes.html"><strong>19.2.</strong> Advanced Lifetimes</a></li><li><a href="ch19-03-advanced-traits.html"><strong>19.3.</strong> Advanced Traits</a></li><li><a href="ch19-04-advanced-types.html"><strong>19.4.</strong> Advanced Types</a></li><li><a href="ch19-05-advanced-functions-and-closures.html"><strong>19.5.</strong> Advanced Functions &amp; Closures</a></li></ul></li><li><a href="ch20-00-final-project-a-web-server.html"><strong>20.</strong> Final Project: Building a Multithreaded Web Server</a></li><li><ul class="section"><li><a href="ch20-01-single-threaded.html"><strong>20.1.</strong> A Single Threaded Web Server</a></li><li><a href="ch20-02-slow-requests.html"><strong>20.2.</strong> How Slow Requests Affect Throughput</a></li><li><a href="ch20-03-designing-the-interface.html"><strong>20.3.</strong> Designing the Thread Pool Interface</a></li><li><a href="ch20-04-storing-threads.html"><strong>20.4.</strong> Creating the Thread Pool and Storing Threads</a></li><li><a href="ch20-05-sending-requests-via-channels.html"><strong>20.5.</strong> Sending Requests to Threads Via Channels</a></li><li><a href="ch20-06-graceful-shutdown-and-cleanup.html"><strong>20.6.</strong> Graceful Shutdown and Cleanup</a></li></ul></li><li><a href="appendix-00.html"><strong>21.</strong> Appendix</a></li><li><ul class="section"><li><a href="appendix-01-keywords.html"><strong>21.1.</strong> A - Keywords</a></li><li><a href="appendix-02-operators.html"><strong>21.2.</strong> B - Operators</a></li><li><strong>21.3.</strong> C - Derivable Traits</li><li><strong>21.4.</strong> D - Nightly Rust</li><li><strong>21.5.</strong> E - Macros</li><li><strong>21.6.</strong> F - Translations</li><li><a href="appendix-07-newest-features.html"><strong>21.7.</strong> G - Newest Features</a></li></ul></li></ul>
        </div>

        <div id="page-wrapper" class="page-wrapper has-warning">

            <div class="page">
                <header><p class="warning">You are reading a <strong>draft</strong> of the next edition of TRPL. For more, go <a href="../index.html">here</a>.</p></header>
                <div id="menu-bar" class="menu-bar">
                    <div class="left-buttons">
                        <i id="sidebar-toggle" class="fa fa-bars"></i>
                        <i id="theme-toggle" class="fa fa-paint-brush"></i>
                    </div>

                    <h1 class="menu-title">The Rust Programming Language</h1>

                    <div class="right-buttons">
                        <i id="print-button" class="fa fa-print" title="Print this book"></i>
                    </div>
                </div>


                <div id="content" class="content">
                    <a class="header" href="ch13-03-improving-our-io-project.html#improving-our-io-project" id="improving-our-io-project"><h2>Improving our I/O Project</h2></a>
<p>We can improve our implementation of the I/O project in Chapter 12 by using
iterators to make places in the code clearer and more concise. Let's take a
look at how iterators can improve our implementation of both the <code>Config::new</code>
function and the <code>search</code> function.</p>
<a class="header" href="ch13-03-improving-our-io-project.html#removing-a-clone-using-an-iterator" id="removing-a-clone-using-an-iterator"><h3>Removing a <code>clone</code> Using an Iterator</h3></a>
<p>In Listing 12-13, we had code that took a slice of <code>String</code> values and created
an instance of the <code>Config</code> struct by checking for the right number of
arguments, indexing into the slice, and cloning the values so that the <code>Config</code>
struct could own those values. We've reproduced the code here in Listing 13-23:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust ignore">impl Config {
    fn new(args: &amp;[String]) -&gt; Result&lt;Config, &amp;'static str&gt; {
        if args.len() &lt; 3 {
            return Err(&quot;not enough arguments&quot;);
        }

        let query = args[1].clone();
        let filename = args[2].clone();

        Ok(Config {
            query, filename
        })
    }
}
</code></pre>
<p><span class="caption">Listing 13-23: Reproduction of the <code>Config::new</code> function
from Listing 12-13</span></p>
<!--Is this why we didn't want to use clone calls, they were inefficient, or
was it that stacking clone calls can become confusing/is bad practice? -->
<!-- Yep, it's for performance reasons /Carol -->
<p>At the time, we said not to worry about the inefficient <code>clone</code> calls here
because we would remove them in the future. Well, that time is now!</p>
<p>The reason we needed <code>clone</code> here in the first place is that we have a slice
with <code>String</code> elements in the parameter <code>args</code>, but the <code>new</code> function does not
own <code>args</code>. In order to be able to return ownership of a <code>Config</code> instance, we
need to clone the values that we put in the <code>query</code> and <code>filename</code> fields of
<code>Config</code>, so that the <code>Config</code> instance can own its values.</p>
<p>With our new knowledge about iterators, we can change the <code>new</code> function to
take ownership of an iterator as its argument instead of borrowing a slice.
We'll use the iterator functionality instead of the code we had that checks the
length of the slice and indexes into specific locations. This will clear up
what the <code>Config::new</code> function is doing since the iterator will take care of
accessing the values.</p>
<!-- use the iterator functionality to what? How will iterating allow us to do
the same thing, can you briefly lay that out? -->
<!-- It's mostly for clarity and using a good abstraction, I've tried fixing
/Carol -->
<p>Once <code>Config::new</code> taking ownership of the iterator and not using indexing
operations that borrow, we can move the <code>String</code> values from the iterator into
<code>Config</code> rather than calling <code>clone</code> and making a new allocation.</p>
<!-- below: which file are we in, can you specify here? -->
<!-- done /Carol -->
<a class="header" href="ch13-03-improving-our-io-project.html#using-the-iterator-returned-by-envargs-directly" id="using-the-iterator-returned-by-envargs-directly"><h4>Using the Iterator Returned by <code>env::args</code> Directly</h4></a>
<p>In your I/O project's <em>src/main.rs</em>, let's change the start of the <code>main</code>
function from this code that we had in Listing 12-23:</p>
<pre><code class="language-rust ignore">fn main() {
    let args: Vec&lt;String&gt; = env::args().collect();
    let mut stderr = std::io::stderr();

    let config = Config::new(&amp;args).unwrap_or_else(|err| {
        writeln!(
            &amp;mut stderr,
            &quot;Problem parsing arguments: {}&quot;,
            err
        ).expect(&quot;Could not write to stderr&quot;);
        process::exit(1);
    });
    // ...snip...
}
</code></pre>
<p>To the code in Listing 13-24:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust ignore">fn main() {
    let mut stderr = std::io::stderr();

    let config = Config::new(env::args()).unwrap_or_else(|err| {
        writeln!(
            &amp;mut stderr,
            &quot;Problem parsing arguments: {}&quot;,
            err
        ).expect(&quot;Could not write to stderr&quot;);
        process::exit(1);
    });
    // ...snip...
}
</code></pre>
<p><span class="caption">Listing 13-24: Passing the return value of <code>env::args</code> to
<code>Config::new</code></span></p>
<!-- I think, if we're going to be building this up bit by bit, it might be
worth adding listing numbers and file names to each, can you add those? Don't
worry about being accurate with the numbers, we can update them more easily
later -->
<!-- That's nice of you to offer, but since we're maintaining an online version
that we're keeping in sync with each round of edits, we need to keep the
listing numbers making sense as well. We'll just take care of them. /Carol -->
<p>The <code>env::args</code> function returns an iterator! Rather than collecting the
iterator values into a vector and then passing a slice to <code>Config::new</code>, now
we're passing ownership of the iterator returned from <code>env::args</code> to
<code>Config::new</code> directly.</p>
<p>Next, we need to update the definition of <code>Config::new</code>. In your I/O project's
<em>src/lib.rs</em>, let's change the signature of <code>Config::new</code> to look like Listing
13-25:</p>
<!-- can you give the filename here too? -->
<!-- done /Carol -->
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust ignore">impl Config {
    fn new(args: std::env::Args) -&gt; Result&lt;Config, &amp;'static str&gt; {
        // ...snip...
</code></pre>
<p><span class="caption">Listing 13-25: Updating the signature of <code>Config::new</code> to
expect an iterator</span></p>
<p>The standard library documentation for the <code>env::args</code> function shows that the
type of the iterator it returns is <code>std::env::Args</code>. We've updated the
signature of the <code>Config::new</code> function so that the parameter <code>args</code> has the
type <code>std::env::Args</code> instead of <code>&amp;[String]</code>.</p>
<a class="header" href="ch13-03-improving-our-io-project.html#using-iterator-trait-methods-instead-of-indexing" id="using-iterator-trait-methods-instead-of-indexing"><h4>Using <code>Iterator</code> Trait Methods Instead of Indexing</h4></a>
<p>Next, we'll fix the body of <code>Config::new</code>. The standard library documentation
also mentions that <code>std::env::Args</code> implements the <code>Iterator</code> trait, so we know
we can call the <code>next</code> method on it! Listing 13-26 has the new code:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><pre class="playpen"><code class="language-rust"># #![allow(unused_variables)]
#fn main() {
# struct Config {
#     query: String,
#     filename: String,
# }
#
impl Config {
    fn new(mut args: std::env::Args) -&gt; Result&lt;Config, &amp;'static str&gt; {
        args.next();

        let query = match args.next() {
            Some(arg) =&gt; arg,
            None =&gt; return Err(&quot;Didn't get a query string&quot;),
        };

        let filename = match args.next() {
            Some(arg) =&gt; arg,
            None =&gt; return Err(&quot;Didn't get a file name&quot;),
        };

        Ok(Config {
            query, filename
        })
    }
}

#}</code></pre></pre>
<p><span class="caption">Listing 13-26: Changing the body of <code>Config::new</code> to use
iterator methods</span></p>
<!-- is this the *full* new lib.rs code? Worth noting for ghosting purposes -->
<!-- No, this is just the `Config::new` function, which I thought would be
clear by saying "Next, we'll fix the body of `Config::new`.", can you elaborate
on why that's not clear enough? I would expect programmers to be able to
understand where a function starts and ends. /Carol -->
<p>Remember that the first value in the return value of <code>env::args</code> is the name of
the program. We want to ignore that and get to the next value, so first we call
<code>next</code> and do nothing with the return value. Second, we call <code>next</code> on the
value we want to put in the <code>query</code> field of <code>Config</code>. If <code>next</code> returns a
<code>Some</code>, we use a <code>match</code> to extract the value. If it returns <code>None</code>, it means
not enough arguments were given and we return early with an <code>Err</code> value. We do
the same thing for the <code>filename</code> value.</p>
<!-- Hm, if ? would not work anyway, I'm not clear on why we mention, why it's
a shame we cant use it on Option? -->
<!-- We've taken this out, it's something that a portion of the readers might
be wondering and something that Rust might let you do someday, but yeah, it's
probably just distracting to most people /Carol -->
<a class="header" href="ch13-03-improving-our-io-project.html#making-code-clearer-with-iterator-adaptors" id="making-code-clearer-with-iterator-adaptors"><h3>Making Code Clearer with Iterator Adaptors</h3></a>
<p>The other place in our I/O project we could take advantage of iterators is in
the <code>search</code> function, as implemented in Listing 12-19 and reproduced here in
Listing 13-27:</p>
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust ignore">fn search&lt;'a&gt;(query: &amp;str, contents: &amp;'a str) -&gt; Vec&lt;&amp;'a str&gt; {
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.contains(query) {
            results.push(line);
        }
    }

    results
}
</code></pre>
<p><span class="caption">Listing 13-27: The implementation of the <code>search</code>
function from Listing 12-19</span></p>
<p>We can write this code in a much shorter way by using iterator adaptor methods
instead. This also lets us avoid having a mutable intermediate <code>results</code>
vector. The functional programming style prefers to minimize the amount of
mutable state to make code clearer. Removing the mutable state might make it
easier for us to make a future enhancement to make searching happen in
parallel, since we wouldn't have to manage concurrent access to the <code>results</code>
vector. Listing 13-28 shows this change:</p>
<!-- Remind us why we want to avoid the mutable results vector? -->
<!-- done /Carol -->
<p><span class="filename">Filename: src/lib.rs</span></p>
<pre><code class="language-rust ignore">fn search&lt;'a&gt;(query: &amp;str, contents: &amp;'a str) -&gt; Vec&lt;&amp;'a str&gt; {
    contents.lines()
        .filter(|line| line.contains(query))
        .collect()
}
</code></pre>
<p><span class="caption">Listing 13-28: Using iterator adaptor methods in the
implementation of the <code>search</code> function</span></p>
<p>Recall that the purpose of the <code>search</code> function is to return all lines in
<code>contents</code> that contain the <code>query</code>. Similarly to the <code>filter</code> example in
Listing 13-18, we can use the <code>filter</code> adaptor to keep only the lines that
<code>line.contains(query)</code> returns true for. We then collect the matching lines up
into another vector with <code>collect</code>. Much simpler!</p>
<!-- what is that, here, only lines that contain a matching string? A bit more
context would help out, we probably can't rely on readers remembering all the
details I'm afraid -->
<!-- done /Carol -->
<p>The next logical question is which style you should choose in your own code:
the original implementation in Listing 13-27, or the version using iterators in
Listing 13-28. Most Rust programmers prefer to use the iterator style. It's a
bit tougher to get the hang of at first, but once you get a feel for the
various iterator adaptors and what they do, iterators can be easier to
understand. Instead of fiddling with the various bits of looping and building
new vectors, the code focuses on the high-level objective of the loop. This
abstracts away some of the commonplace code so that it's easier to see the
concepts that are unique to this code, like the filtering condition each
element in the iterator must pass.</p>
<p>But are the two implementations truly equivalent? The intuitive assumption
might be that the more low-level loop will be faster. Let's talk about
performance.</p>

                </div>

                <!-- Mobile navigation buttons -->
                
                    <a href="ch13-02-iterators.html" class="mobile-nav-chapters previous">
                        <i class="fa fa-angle-left"></i>
                    </a>
                

                
                    <a href="ch13-04-performance.html" class="mobile-nav-chapters next">
                        <i class="fa fa-angle-right"></i>
                    </a>
                

            </div>

            
                <a href="ch13-02-iterators.html" class="nav-chapters previous" title="You can navigate through the chapters using the arrow keys">
                    <i class="fa fa-angle-left"></i>
                </a>
            

            
                <a href="ch13-04-performance.html" class="nav-chapters next" title="You can navigate through the chapters using the arrow keys">
                    <i class="fa fa-angle-right"></i>
                </a>
            

        </div>


        <!-- Local fallback for Font Awesome -->
        <script>
            if ($(".fa").css("font-family") !== "FontAwesome") {
                $('<link rel="stylesheet" type="text/css" href="_FontAwesome/css/font-awesome.css">').prependTo('head');
            }
        </script>

        <!-- Livereload script (if served using the cli tool) -->
        

        <script src="highlight.js"></script>
        <script src="book.js"></script>
    </body>
</html>