easy_rust/Chapter_7.html

338 lines
26 KiB
HTML
Raw Normal View History

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title> Types - Easy Rust</title>
<!-- Custom HTML head -->
<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">
<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" : "light";
</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('light')
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="Chapter_0.html"><strong aria-hidden="true">1.</strong> Update</a></li><li class="chapter-item expanded "><a href="Chapter_1.html"><strong aria-hidden="true">2.</strong> Introduction</a></li><li class="chapter-item expanded "><a href="Chapter_2.html"><strong aria-hidden="true">3.</strong> Who am I?</a></li><li class="chapter-item expanded "><a href="Chapter_3.html"><strong aria-hidden="true">4.</strong> Writing Rust in Easy English</a></li><li class="chapter-item expanded "><a href="Chapter_4.html"><strong aria-hidden="true">5.</strong> Rust Playground</a></li><li class="chapter-item expanded "><a href="Chapter_5.html"><strong aria-hidden="true">6.</strong> 🚧 and ⚠️</a></li><li class="chapter-item expanded "><a href="Chapter_6.html"><strong aria-hidden="true">7.</strong> Comments</a></li><li class="chapter-item expanded "><a href="Chapter_7.html" class="active"><strong aria-hidden="true">8.</strong> Types</a></li><li class="chapter-item expanded "><a href="Chapter_8.html"><strong aria-hidden="true">9.</strong> Type inference</a></li><li class="chapter-item expanded "><a href="Chapter_9.html"><strong aria-hidden="true">10.</strong> Printing 'hello, world!'</a></li><li class="chapter-item expanded "><a href="Chapter_10.html"><strong aria-hidden="true">11.</strong> Display and debug</a></li><li class="chapter-item expanded "><a href="Chapter_11.html"><strong aria-hidden="true">12.</strong> Mutability (changing)</a></li><li class="chapter-item expanded "><a href="Chapter_12.html"><strong aria-hidden="true">13.</strong> The stack, the heap, and pointers</a></li><li class="chapter-item expanded "><a href="Chapter_13.html"><strong aria-hidden="true">14.</strong> More about printing</a></li><li class="chapter-item expanded "><a href="Chapter_14.html"><strong aria-hidden="true">15.</strong> Strings</a></li><li class="chapter-item expanded "><a href="Chapter_15.html"><strong aria-hidden="true">16.</strong> const and static</a></li><li class="chapter-item expanded "><a href="Chapter_16.html"><strong aria-hidden="true">17.</strong> More on references</a></li><li class="chapter-item expanded "><a href="Chapter_17.html"><strong aria-hidden="true">18.</strong> Mutable references</a></li><li class="chapter-item expanded "><a href="Chapter_18.html"><strong aria-hidden="true">19.</strong> Giving references to functions</a></li><li class="chapter-item expanded "><a href="Chapter_19.html"><strong aria-hidden="true">20.</strong> Copy types</a></li><li class="chapter-item expanded "><a href="Chapter_20.html"><strong aria-hidden="true">21.</strong> Collection types</a></li><li class="chapter-item expanded "><a href="Chapter_21.html"><strong aria-hidden="true">22.</strong> Vectors</a></li><li class="chapter-item expanded "><a href="Chapter_22.html"><strong aria-hidden="true">23.</strong> Tuples</a></li><li class="chapter-item expanded "><a href="Chapter_23.html"><strong aria-hidden="true">24.</strong> Control flow</a></li><li class="chapter-item expanded "><a href="Chapter_24.html"><strong aria-hidden="true">25.</strong> Structs</a></li><li class="chapter-item expanded "><a href="Chapter_25.html"><strong aria-hidden="true">26.</strong> Enums</a></li><li class="chapter-item expanded "><a href="Chapter_26.html"><strong aria-hidden="true">27.</strong> Loops</a></li><li class="chapter-item expanded "><a href="Chapter_27.html"><strong aria-hidden="true">28.</strong> Implementing structs and enums</a></li><li class="chapter-item expanded "><a href="Chapter_28.html"><strong aria-hidden="true">29.</strong> Destructuring</a></li><li class="chapter-item expanded "><a href="Chapter_29.html"><strong aria-hidden="true">30.</strong> References and the dot operator</a></li><li class="chapter-item expanded "><a href="Chapter_30.html"><strong aria-hidden="true">31.</strong> Generics</a></li><li class="chapter-item expanded "><a href="Chapter_31.html"><strong aria-hidden="true">32.</strong> Option and Result</a></li><li class="chapter-item expanded "><a href="Chapter_32.html">
</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 (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</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">Easy Rust</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>
</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>
<h2><a class="header" href="#types" id="types">Types</a></h2>
<p>Rust has many types that let you work with numbers, characters, and so on. Some are simple, others are more complicated, and you can even create your own.</p>
<h3><a class="header" href="#primitive-types" id="primitive-types">Primitive types</a></h3>
<p><strong><a href="https://youtu.be/OxTPU5UGMhs">See this chapter on YouTube</a></strong></p>
<p>Rust has simple types that are called <strong>primitive types</strong> (primitive = very basic). We will start with integers and <code>char</code> (characters). Integers are whole numbers with no decimal point. There are two types of integers:</p>
<ul>
<li>Signed integers,</li>
<li>Unsigned integers.</li>
</ul>
<p>Signed means <code>+</code> (plus sign) and <code>-</code> (minus sign), so signed integers can be positive or negative (e.g. +8, -8). But unsigned integers can only be positive, because they do not have a sign.</p>
<p>The signed integers are: <code>i8</code>, <code>i16</code>, <code>i32</code>, <code>i64</code>, <code>i128</code>, and <code>isize</code>.
The unsigned integers are: <code>u8</code>, <code>u16</code>, <code>u32</code>, <code>u64</code>, <code>u128</code>, and <code>usize</code>.</p>
<p>The number after the i or the u means the number of bits for the number, so numbers with more bits can be larger. 8 bits = one byte, so <code>i8</code> is one byte, <code>i64</code> is 8 bytes, and so on. Number types with larger sizes can hold larger numbers. For example, a <code>u8</code> can hold up to 255, but a <code>u16</code> can hold up to 65535. And a <code>u128</code> can hold up to 340282366920938463463374607431768211455.</p>
<p>So what is <code>isize</code> and <code>usize</code>? This means the number of bits on your type of computer. (The number of bits on your computer is called the <strong>architecture</strong> of your computer.) So <code>isize</code> and <code>usize</code> on a 32-bit computer is like <code>i32</code> and <code>u32</code>, and <code>isize</code> and <code>usize</code> on a 64-bit computer is like <code>i64</code> and <code>u64</code>.</p>
<p>There are many reasons for the different types of integers. One reason is computer performance: a smaller number of bytes is faster to process. For example, the number -10 as an <code>i8</code> is <code>11110110</code>, but as an <code>i128</code> it is <code>11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110110</code>. But here are some other uses:</p>
<p>Characters in Rust are called <code>char</code>. Every <code>char</code> has a number: the letter <code>A</code> is number 65, while the character <code></code> (&quot;friend&quot; in Chinese) is number 21451. The list of numbers is called &quot;Unicode&quot;. Unicode uses smaller numbers for characters that are used more, like A through Z, or digits 0 through 9, or space.</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let first_letter = 'A';
let space = ' '; // A space inside ' ' is also a char
let other_language_char = 'Ꮔ'; // Thanks to Unicode, other languages like Cherokee display just fine too
let cat_face = '😺'; // Emojis are chars too
}
</code></pre></pre>
<p>The characters that are used most have numbers less than 256, and they can fit into a <code>u8</code>. Remember, a <code>u8</code> is 0 plus all the numbers up to 255, for 256 in total. This means that Rust can safely <strong>cast</strong> a <code>u8</code> into a <code>char</code>, using <code>as</code>. (&quot;Cast <code>u8</code> as <code>char</code>&quot; means &quot;pretend <code>u8</code> is a <code>char</code>&quot;)</p>
<p>Casting with <code>as</code> is useful because Rust is very strict. It always needs to know the type, and won't let you use two different types together even if they are both integers. For example, this will not work:</p>
<pre><pre class="playground"><code class="language-rust">fn main() { // main() is where Rust programs start to run. Code goes inside {} (curly brackets)
let my_number = 100; // We didn't write a type of integer,
// so Rust chooses i32. Rust always
// chooses i32 for integers if you don't
// tell it to use a different type
println!(&quot;{}&quot;, my_number as char); // ⚠️
}
</code></pre></pre>
<p>Here is the reason:</p>
<pre><code class="language-text">error[E0604]: only `u8` can be cast as `char`, not `i32`
--&gt; src\main.rs:3:20
|
3 | println!(&quot;{}&quot;, my_number as char);
| ^^^^^^^^^^^^^^^^^
</code></pre>
<p>Fortunately we can easily fix this with <code>as</code>. We can't cast <code>i32</code> as a <code>char</code>, but we can cast an <code>i32</code> as a <code>u8</code>. And then we can do the same from <code>u8</code> to <code>char</code>. So in one line we use <code>as</code> to make my_number a <code>u8</code>, and again to make it a <code>char</code>. Now it will compile:</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let my_number = 100;
println!(&quot;{}&quot;, my_number as u8 as char);
}
</code></pre></pre>
<p>It prints <code>d</code> because that is the <code>char</code> in place 100.</p>
<p>The easier way, however, is just to tell Rust that <code>my_number</code> is a <code>u8</code>. Here's how you do it:</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let my_number: u8 = 100; // change my_number to my_number: u8
println!(&quot;{}&quot;, my_number as char);
}
</code></pre></pre>
<p>So those are two reasons for all the different number types in Rust. Here is another reason: <code>usize</code> is the size that Rust uses for <em>indexing</em>. (Indexing means &quot;which item is first&quot;, &quot;which item is second&quot;, etc.) <code>usize</code> is the best size for indexing because:</p>
<ul>
<li>An index can't be negative, so it needs to be a number with a u</li>
<li>It should be big, because sometimes you need to index many things, but</li>
<li>It can't be a u64 because 32-bit computers can't use u64.</li>
</ul>
<p>So Rust uses <code>usize</code> so that your computer can get the biggest number for indexing that it can read.</p>
<p>Let's learn some more about <code>char</code>. You saw that a <code>char</code> is always one character, and uses <code>''</code> instead of <code>&quot;&quot;</code>.</p>
<p>All chars are 4 bytes. They are 4 bytes because some characters in a string are more than one byte. Basic letters that have always been on computers are 1 byte, later characters are 2 bytes, and others are 3 and 4. A <code>char</code> needs to be 4 bytes so that it can hold any kind of character.</p>
<p>We can use <code>.len()</code> to see this for ourselves:</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
println!(&quot;{}&quot;, &quot;a&quot;.len()); // .len() gives the size in bytes
println!(&quot;{}&quot;, &quot;ß&quot;.len());
println!(&quot;{}&quot;, &quot;&quot;.len());
println!(&quot;{}&quot;, &quot;𓅱&quot;.len());
}
</code></pre></pre>
<p>This prints:</p>
<pre><code class="language-text">1
2
3
4
</code></pre>
<p>You can see that <code>a</code> is one byte, the German <code>ß</code> is two, the Japanese <code></code> is three, and the ancient Egyptian <code>𓅱</code> is 4 bytes.</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let slice = &quot;Hello!&quot;;
println!(&quot;Slice is {} bytes.&quot;, slice.len());
let slice2 = &quot;안녕!&quot;; // Korean for &quot;hi&quot;
println!(&quot;Slice2 is {} bytes.&quot;, slice2.len());
}
</code></pre></pre>
<p>This prints:</p>
<pre><code class="language-text">Slice is 6 bytes.
Slice2 is 7 bytes.
</code></pre>
<p><code>slice</code> is 6 characters in length and 6 bytes, but <code>slice2</code> is 3 characters in length and 7 bytes.</p>
<p>If <code>.len()</code> gives the size in bytes, what about the size in characters? We will learn about these methods later, but you can just remember that <code>.chars().count()</code> will do it. <code>.chars().count()</code> turns what you wrote into characters and then counts how many there are.</p>
<pre><pre class="playground"><code class="language-rust">fn main() {
let slice = &quot;Hello!&quot;;
println!(&quot;Slice is {} bytes and also {} characters.&quot;, slice.len(), slice.chars().count());
let slice2 = &quot;안녕!&quot;;
println!(&quot;Slice2 is {} bytes but only {} characters.&quot;, slice2.len(), slice2.chars().count());
}
</code></pre></pre>
<p>This prints:</p>
<pre><code class="language-text">Slice is 6 bytes and also 6 characters.
Slice2 is 7 bytes but only 3 characters.
</code></pre>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="Chapter_6.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="Chapter_8.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="Chapter_6.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="Chapter_8.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></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>