mirror of
https://github.com/rust-unofficial/patterns
synced 2024-11-02 21:40:26 +00:00
279 lines
17 KiB
HTML
279 lines
17 KiB
HTML
|
<!DOCTYPE HTML>
|
||
|
<html lang="en" class="sidebar-visible no-js rust">
|
||
|
<head>
|
||
|
<!-- Book generated using mdBook -->
|
||
|
<meta charset="UTF-8">
|
||
|
<title>Functional Programming - Rust Design Patterns</title>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<!-- Custom HTML head -->
|
||
|
|
||
|
|
||
|
|
||
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||
|
<meta name="description" content="A catalogue of Rust design patterns, anti-patterns and idioms">
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
|
<meta name="theme-color" content="#ffffff" />
|
||
|
|
||
|
|
||
|
<link rel="icon" href="../favicon.svg">
|
||
|
|
||
|
|
||
|
<link rel="shortcut icon" href="../favicon.png">
|
||
|
|
||
|
<link rel="stylesheet" href="../css/variables.css">
|
||
|
<link rel="stylesheet" href="../css/general.css">
|
||
|
<link rel="stylesheet" href="../css/chrome.css">
|
||
|
|
||
|
<link rel="stylesheet" href="../css/print.css" media="print">
|
||
|
|
||
|
|
||
|
<!-- Fonts -->
|
||
|
<link rel="stylesheet" href="../FontAwesome/css/font-awesome.css">
|
||
|
|
||
|
<link rel="stylesheet" href="../fonts/fonts.css">
|
||
|
|
||
|
|
||
|
<!-- Highlight.js Stylesheets -->
|
||
|
<link rel="stylesheet" href="../highlight.css">
|
||
|
<link rel="stylesheet" href="../tomorrow-night.css">
|
||
|
<link rel="stylesheet" href="../ayu-highlight.css">
|
||
|
|
||
|
<!-- Custom theme stylesheets -->
|
||
|
|
||
|
|
||
|
|
||
|
</head>
|
||
|
<body>
|
||
|
<!-- Provide site root to javascript -->
|
||
|
<script type="text/javascript">
|
||
|
var path_to_root = "../";
|
||
|
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "rust";
|
||
|
</script>
|
||
|
|
||
|
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||
|
<script type="text/javascript">
|
||
|
try {
|
||
|
var theme = localStorage.getItem('mdbook-theme');
|
||
|
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||
|
|
||
|
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||
|
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||
|
}
|
||
|
|
||
|
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||
|
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||
|
}
|
||
|
} catch (e) { }
|
||
|
</script>
|
||
|
|
||
|
<!-- Set the theme before any content is loaded, prevents flash -->
|
||
|
<script type="text/javascript">
|
||
|
var theme;
|
||
|
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||
|
if (theme === null || theme === undefined) { theme = default_theme; }
|
||
|
var html = document.querySelector('html');
|
||
|
html.classList.remove('no-js')
|
||
|
html.classList.remove('rust')
|
||
|
html.classList.add(theme);
|
||
|
html.classList.add('js');
|
||
|
</script>
|
||
|
|
||
|
<!-- Hide / unhide sidebar before it is displayed -->
|
||
|
<script type="text/javascript">
|
||
|
var html = document.querySelector('html');
|
||
|
var sidebar = 'hidden';
|
||
|
if (document.body.clientWidth >= 1080) {
|
||
|
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||
|
sidebar = sidebar || 'visible';
|
||
|
}
|
||
|
html.classList.remove('sidebar-visible');
|
||
|
html.classList.add("sidebar-" + sidebar);
|
||
|
</script>
|
||
|
|
||
|
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||
|
<div class="sidebar-scrollbox">
|
||
|
<ol class="chapter"><li class="chapter-item expanded "><a href="../intro.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li class="chapter-item expanded "><a href="../idioms/index.html"><strong aria-hidden="true">2.</strong> Idioms</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../idioms/concat-format.html"><strong aria-hidden="true">2.1.</strong> Concatenating Strings with format!</a></li><li class="chapter-item expanded "><a href="../idioms/ctor.html"><strong aria-hidden="true">2.2.</strong> Constructor</a></li><li class="chapter-item expanded "><a href="../idioms/default.html"><strong aria-hidden="true">2.3.</strong> The Default Trait</a></li><li class="chapter-item expanded "><a href="../idioms/deref.html"><strong aria-hidden="true">2.4.</strong> Collections Are Smart Pointers</a></li><li class="chapter-item expanded "><a href="../idioms/dtor-finally.html"><strong aria-hidden="true">2.5.</strong> Finalisation in Destructors</a></li><li class="chapter-item expanded "><a href="../idioms/mem-replace.html"><strong aria-hidden="true">2.6.</strong> mem::replace(_)</a></li><li class="chapter-item expanded "><a href="../idioms/on-stack-dyn-dispatch.html"><strong aria-hidden="true">2.7.</strong> On-Stack Dynamic Dispatch</a></li><li class="chapter-item expanded "><a href="../idioms/option-iter.html"><strong aria-hidden="true">2.8.</strong> Iterating over an Option</a></li><li class="chapter-item expanded "><a href="../idioms/pass-var-to-closure.html"><strong aria-hidden="true">2.9.</strong> Pass Variables to Closure</a></li><li class="chapter-item expanded "><a href="../idioms/priv-extend.html"><strong aria-hidden="true">2.10.</strong> Privacy For Extensibility</a></li><li class="chapter-item expanded "><a href="../idioms/rustdoc-init.html"><strong aria-hidden="true">2.11.</strong> Easy doc initialization</a></li><li class="chapter-item expanded "><a href="../idioms/temporary-mutability.html"><strong aria-hidden="true">2.12.</strong> Temporary mutability</a></li></ol></li><li class="chapter-item expanded "><a href="../patterns/index.html"><strong aria-hidden="true">3.</strong> Design Patterns</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../patterns/builder.html"><strong aria-hidden="true">3.1.</strong> Builder</a></li><li class="chapter-item expanded "><a href="../patterns/compose-structs.html"><strong aria-hidden="true">3.2.</strong> Compose Structs</a></li><li class="chapter-item expanded "><a href="../patterns/entry.html"><strong aria-hidden="true">3.3.</strong> Entry API</a></li><li class="chapter-item expanded "><a href="../patterns/fold.html"><strong aria-hidden="true">3.4.</strong> Fold</a></li><li class="chapter-item expanded "><a href="../patterns/late-bounds.html"><strong aria-hidden="true">3.5.</strong> Late Bound Bounds</a></li><li class="chapter-item expanded "><a href="../patterns/newtype.html"><strong aria-hidden="true">3.6.</strong> Newtype</a></li><li class="chapter-item expanded "><a href="../patterns/RAII.html"><strong aria-hidden="true">3.7.</strong> RAII Guards</a></li><li class="chapter-item expanded "><a href="../patterns/small-crates.html"><strong aria-hidden="true">3.8.</strong> Prefer Small Crates</a></li><li class="chapter-item expanded "><a href="../patterns/unsafe-mods.html"><strong aria-hidden="true">3.9.</strong> Contain unsafety in small modules</a></li><li class="chapter-item expanded "><a href="../patterns/visitor.html"><strong aria-hidden="true">3.10.</strong> Visitor</a></li></ol></li><li class="chapter-item expanded "><a href="../anti_patterns/index.html"><strong aria-hidden="true">4.</strong> Anti-patterns</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="../anti_patterns/deny-warnings.html"><strong aria-hidden="true">4.1.</strong> #[deny(warnings)]</a></li><li class="chapter-item expanded "><a href="../anti_patterns/deref.html"><strong aria-hidden="true">4.2.</strong> Deref Polymorphism</a></li></ol></li><li class="chapter-item expanded "><a href="../functional/index.
|
||
|
</div>
|
||
|
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||
|
</nav>
|
||
|
|
||
|
<div id="page-wrapper" class="page-wrapper">
|
||
|
|
||
|
<div class="page">
|
||
|
|
||
|
<div id="menu-bar-hover-placeholder"></div>
|
||
|
<div id="menu-bar" class="menu-bar sticky bordered">
|
||
|
<div class="left-buttons">
|
||
|
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||
|
<i class="fa fa-bars"></i>
|
||
|
</button>
|
||
|
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||
|
<i class="fa fa-paint-brush"></i>
|
||
|
</button>
|
||
|
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||
|
<li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
|
||
|
<li role="none"><button role="menuitem" class="theme" id="rust">Rust (default)</button></li>
|
||
|
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
|
||
|
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
|
||
|
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
|
||
|
</ul>
|
||
|
|
||
|
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||
|
<i class="fa fa-search"></i>
|
||
|
</button>
|
||
|
|
||
|
</div>
|
||
|
|
||
|
<h1 class="menu-title">Rust Design Patterns</h1>
|
||
|
|
||
|
<div class="right-buttons">
|
||
|
|
||
|
<a href="../print.html" title="Print this book" aria-label="Print this book">
|
||
|
<i id="print-button" class="fa fa-print"></i>
|
||
|
</a>
|
||
|
|
||
|
|
||
|
<a href="https://github.com/rust-unofficial/patterns" title="Git repository" aria-label="Git repository">
|
||
|
<i id="git-repository-button" class="fa fa-github"></i>
|
||
|
</a>
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<div id="search-wrapper" class="hidden">
|
||
|
<form id="searchbar-outer" class="searchbar-outer">
|
||
|
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||
|
</form>
|
||
|
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||
|
<div id="searchresults-header" class="searchresults-header"></div>
|
||
|
<ul id="searchresults">
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||
|
<script type="text/javascript">
|
||
|
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||
|
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||
|
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||
|
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||
|
});
|
||
|
</script>
|
||
|
|
||
|
<div id="content" class="content">
|
||
|
<main>
|
||
|
<h1><a class="header" href="#functional-usage-of-rust" id="functional-usage-of-rust">Functional Usage of Rust</a></h1>
|
||
|
<p>Rust is an imperative language, but it follows many functional programming paradigms. One of the biggest hurdles to understanding functional programs when coming from an imperative background is the shift in thinking. Imperative programs describe <strong>how</strong> to do something, whereas declarative programs describe <strong>what</strong> to do. Let's sum the numbers from 1 to 10 to show this.</p>
|
||
|
<h2><a class="header" href="#imperative" id="imperative">Imperative</a></h2>
|
||
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
||
|
<span class="boring">#![allow(unused)]
|
||
|
</span><span class="boring">fn main() {
|
||
|
</span>let mut sum = 0;
|
||
|
for i in 1..11 {
|
||
|
sum += i;
|
||
|
}
|
||
|
println!("{}", sum);
|
||
|
<span class="boring">}
|
||
|
</span></code></pre></pre>
|
||
|
<p>With imperative programs, we have to play compiler to see what is happening. Here, we start with a <code>sum</code> of <code>0</code>. Next, we iterate through the range from 1 to 10. Each time through the loop, we add the corresponding value in the range. Then we print it out.</p>
|
||
|
<table><thead><tr><th><code>i</code></th><th><code>sum</code></th></tr></thead><tbody>
|
||
|
<tr><td>1</td><td>1</td></tr>
|
||
|
<tr><td>2</td><td>3</td></tr>
|
||
|
<tr><td>3</td><td>6</td></tr>
|
||
|
<tr><td>4</td><td>10</td></tr>
|
||
|
<tr><td>5</td><td>15</td></tr>
|
||
|
<tr><td>6</td><td>21</td></tr>
|
||
|
<tr><td>7</td><td>28</td></tr>
|
||
|
<tr><td>8</td><td>36</td></tr>
|
||
|
<tr><td>9</td><td>45</td></tr>
|
||
|
<tr><td>10</td><td>55</td></tr>
|
||
|
</tbody></table>
|
||
|
<p>This is how most of us start out programming. We learn that a program is a set of steps.</p>
|
||
|
<h2><a class="header" href="#declarative" id="declarative">Declarative</a></h2>
|
||
|
<pre><pre class="playground"><code class="language-rust edition2018">
|
||
|
<span class="boring">#![allow(unused)]
|
||
|
</span><span class="boring">fn main() {
|
||
|
</span>println!("{}", (1..11).fold(0, |a, b| a + b));
|
||
|
<span class="boring">}
|
||
|
</span></code></pre></pre>
|
||
|
<p>Whoa! This is really different! What's going on here? Remember that with declarative programs we are describing <strong>what</strong> to do, rather than <strong>how</strong> to do it. <code>fold</code> is a function that <a href="https://en.wikipedia.org/wiki/Function_composition">composes</a> functions. The name is a convention from Haskell.</p>
|
||
|
<p>Here, we are composing functions of addition (this closure: <code>|a, b| a + b)</code>) with a range from 1 to 10. The <code>0</code> is the starting point, so <code>a</code> is <code>0</code> at first. <code>b</code> is the first element of the range, <code>1</code>. <code>0 + 1 = 1</code> is the result. So now we <code>fold</code> again, with <code>a = 1</code>, <code>b = 2</code> and so <code>1 + 2 = 3</code> is the next result. This process continues until we get to the last element in the range, <code>10</code>.</p>
|
||
|
<table><thead><tr><th><code>a</code></th><th><code>b</code></th><th>result</th></tr></thead><tbody>
|
||
|
<tr><td>0</td><td>1</td><td>1</td></tr>
|
||
|
<tr><td>1</td><td>2</td><td>3</td></tr>
|
||
|
<tr><td>3</td><td>3</td><td>6</td></tr>
|
||
|
<tr><td>6</td><td>4</td><td>10</td></tr>
|
||
|
<tr><td>10</td><td>5</td><td>15</td></tr>
|
||
|
<tr><td>15</td><td>6</td><td>21</td></tr>
|
||
|
<tr><td>21</td><td>7</td><td>28</td></tr>
|
||
|
<tr><td>28</td><td>8</td><td>36</td></tr>
|
||
|
<tr><td>36</td><td>9</td><td>45</td></tr>
|
||
|
<tr><td>45</td><td>10</td><td>55</td></tr>
|
||
|
</tbody></table>
|
||
|
|
||
|
</main>
|
||
|
|
||
|
<nav class="nav-wrapper" aria-label="Page navigation">
|
||
|
<!-- Mobile navigation buttons -->
|
||
|
|
||
|
<a rel="prev" href="../anti_patterns/deref.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
|
<i class="fa fa-angle-left"></i>
|
||
|
</a>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<div style="clear: both"></div>
|
||
|
</nav>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||
|
|
||
|
<a rel="prev" href="../anti_patterns/deref.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||
|
<i class="fa fa-angle-left"></i>
|
||
|
</a>
|
||
|
|
||
|
|
||
|
|
||
|
</nav>
|
||
|
|
||
|
</div>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<script type="text/javascript">
|
||
|
window.playground_copyable = true;
|
||
|
</script>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<script src="../elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
||
|
<script src="../mark.min.js" type="text/javascript" charset="utf-8"></script>
|
||
|
<script src="../searcher.js" type="text/javascript" charset="utf-8"></script>
|
||
|
|
||
|
|
||
|
<script src="../clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
||
|
<script src="../highlight.js" type="text/javascript" charset="utf-8"></script>
|
||
|
<script src="../book.js" type="text/javascript" charset="utf-8"></script>
|
||
|
|
||
|
<!-- Custom JS scripts -->
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
</body>
|
||
|
</html>
|