Jekyll2022-09-14T04:14:17+00:00https://cooscoos.github.io/feed.xmlRust blogBlogs about Rust.cooscoos&stress about &Strings2022-09-12T05:33:00+00:002022-09-14T04:50:00+00:00https://cooscoos.github.io/blog/stress-about-strings<p>There’s <a href="https://doc.rust-lang.org/stable/book/ch04-01-what-is-ownership.html">one</a> — <a href="https://doc.rust-lang.org/rust-by-example/std/box.html">a few</a> — <a href="https://blog.thoughtram.io/string-vs-str-in-rust/">lots</a> — even <a href="https://www.becomebetterprogrammer.com/rust-string-vs-str/">dozens</a> — of good articles that explain the differences between a <code class="language-plaintext highlighter-rouge">&str</code>, <code class="language-plaintext highlighter-rouge">&'static str</code>, <code class="language-plaintext highlighter-rouge">&'a str</code>, <code class="language-plaintext highlighter-rouge">String</code>, and <code class="language-plaintext highlighter-rouge">&String</code> in Rust.</p>
<p>Most of these start by covering:</p>
<ul>
<li>the heap and the stack;</li>
<li>ownership, and;</li>
<li>lifetimes;</li>
</ul>
<p>and while that’s all important, it can feel like a lot when you’re starting out.</p>
<p>Let’s try something different.</p>
<p>Here, we’ll use an analogy, and look at some code along the way.</p>
<p>Analogies ain’t perfect, but I hope this one makes the topic stick better for some of you. If it does, you can return to those other articles with some intuition.</p>
<h2 id="you-run-a-desk-nameplate-business-for-dogs">You run a desk nameplate business for dogs</h2>
<p>Bear with me here.</p>
<p>You want to set up a business where you sell plastic desk nameplates for dogs in high places.</p>
<p>To make these nameplates you have two options:</p>
<ol>
<li>
<p>Get some real nice steel moulds made up, and bolted to a shelf in your shop (you can only do this once, ever). You can point to a mould, and your technician will carry a bucket of molten plastic over to cast a nameplate.</p>
</li>
<li>
<p>Send the dog’s name to a 3D printing company and ask them to make you a nameplate on demand.</p>
</li>
</ol>
<figure class="align-center">
<img src="https://cooscoos.github.io/assets/images/post_imgs/nameplate.jpg" alt="" />
<figcaption>A desk nameplate for a mere human being. [img: <a href="https://www.pexels.com/@rodnae-prod/">RODNAE Productions</a>]</figcaption>
</figure>
<h3 id="static-str-point-a-finger-at-moulds-youve-committed-to">&’static str: point a finger at moulds you’ve committed to</h3>
<p>Check you out. You’re smart. You’ve done some market research about dogs, so you know ahead of time that you’ll get lots of requests for “Max”, “Charlie”, and “Rolo” nameplates. For these names, it would make sense to get a stack of steel moulds made up ahead of time.</p>
<p>Let’s do this for “Rolo”:</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">point_finger</span><span class="p">:</span> <span class="o">&</span><span class="nv">'static</span> <span class="nb">str</span> <span class="o">=</span> <span class="s">"Rolo"</span><span class="p">;</span>
<span class="nf">hot_plastic</span><span class="p">(</span><span class="n">point_finger</span><span class="p">);</span>
<span class="p">}</span>
<span class="c">// Ask your technician to pour plastic in, get nameplate out</span>
<span class="k">fn</span> <span class="nf">hot_plastic</span><span class="p">(</span><span class="n">steel_mould_location</span><span class="p">:</span> <span class="o">&</span><span class="nv">'static</span> <span class="nb">str</span><span class="p">)</span> <span class="p">{</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"{steel_mould_location}"</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>The name <code class="language-plaintext highlighter-rouge">"Rolo"</code> in the code above is a “string literal”: a hard-coded string defined in the binary of your program. String literals are objects with a <code class="language-plaintext highlighter-rouge">static</code> lifetime — this means that they will last for as long as our program (or business) is running. You can think of string literals as being like steel moulds, or the laws of the Universe — they are unchanging and unchangeable things that will <a href="https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html">always be there in memory</a>.</p>
<p><code class="language-plaintext highlighter-rouge">point_finger</code>, on the other hand, is not a string literal: it is a variable that makes reference to the string literal <code class="language-plaintext highlighter-rouge">"Rolo"</code>. It has the type <code class="language-plaintext highlighter-rouge">&'static str</code>:</p>
<ul>
<li>the <code class="language-plaintext highlighter-rouge">&</code> part means that we’re pointing to a reference, a “place” — that place is the fixed location on the shelf where your steel mould is bolted;</li>
<li>the <code class="language-plaintext highlighter-rouge">'static</code> part means that we can safely point at this object forever (after all, we’re pointing at a steel mould, so it will always be there).</li>
</ul>
<p>Imagine you lose your finger in a freak accident. If you plan ahead, then you can still use other methods to point to the right location on the shelf:</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c">// Let's go out and buy a signpost</span>
<span class="k">let</span> <span class="n">use_signpost</span><span class="p">:</span> <span class="o">&</span><span class="nv">'static</span> <span class="nb">str</span><span class="p">;</span>
<span class="p">{</span>
<span class="c">// Use your finger to point at a steel mould</span>
<span class="k">let</span> <span class="n">point_finger</span><span class="p">:</span> <span class="o">&</span><span class="nv">'static</span> <span class="nb">str</span> <span class="o">=</span> <span class="s">"Rolo"</span><span class="p">;</span>
<span class="c">// Write on signpost so that it also points there</span>
<span class="n">use_signpost</span> <span class="o">=</span> <span class="n">point_finger</span><span class="p">;</span>
<span class="p">}</span> <span class="c">// Oh no. You lose your finger here.</span>
<span class="c">// If you try this:</span>
<span class="c">// println!("{point_finger}");</span>
<span class="c">// it won't work, cause you ain't got no finger now.</span>
<span class="c">// But this is fine:</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"{use_signpost}"</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>So you see, the <em>variable</em> <code class="language-plaintext highlighter-rouge">point_finger</code> isn’t static, it just directs us to something which is. Fingers can be created or destroyed.</p>
<figure style="width: 250px" class="align-left">
<img src="https://cooscoos.github.io/assets/images/post_imgs/pug.jpg" alt="" />
<figcaption>Future you, handling Rolo with finesse and ease. [img: <a href="https://www.pexels.com/@babydov/">Ivan Babydov</a>]</figcaption>
</figure>
<p>Getting this “Rolo” mould made up as a string literal required foresight, didn’t it? At compile time, you had to know that you wanted to commit resources (be that money or memory) to the name “Rolo”.</p>
<p>In return, you get certainty. The steel mould will always be on the shelf, and nobody (not even you) can ever move it, hide it, or change it (we say that <code class="language-plaintext highlighter-rouge">'static str</code> are “immutable”).</p>
<p>These constraints could be annoying in some circumstances, but you’re happy because you know you’re going to use this mould a lot.</p>
<p>While string literals are not mutable, <code class="language-plaintext highlighter-rouge">&'static str</code> variables <em>are</em> mutable. You can use your finger to point at other things:</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="c">// point at the "Rolo" mould</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">point_finger</span><span class="p">:</span> <span class="o">&</span><span class="nv">'static</span> <span class="nb">str</span> <span class="o">=</span> <span class="s">"Rolo"</span><span class="p">;</span>
<span class="c">// now point at the "Max" mould</span>
<span class="n">point_finger</span> <span class="o">=</span> <span class="s">"Max"</span><span class="p">;</span></code></pre></figure>
<p class="notice">Something that might cause confusion: if you type <code class="language-plaintext highlighter-rouge">let steel_mould = "Rolo"</code>, your IDE will probably display <code class="language-plaintext highlighter-rouge">let steel_mould: &str = "Rolo"</code>. It says the type is just a <code class="language-plaintext highlighter-rouge">&str</code> without the <code class="language-plaintext highlighter-rouge">'static</code> part. Even though your IDE doesn’t explicitly say it, this <code class="language-plaintext highlighter-rouge">&str</code> is a <code class="language-plaintext highlighter-rouge">&'static str</code>.</p>
<h3 id="string-committing-resources-to-unspecific-tasks">String: committing resources to unspecific tasks</h3>
<p>Would it make sense to make steel moulds for every dog name that exists? Not if you want your business to stay afloat! Some names will be rarer; they aren’t worth such a specific investment.</p>
<p>If someone comes in and asks for a nameplate for their completely normal dog called “Harambe794524”, then we’re better off sending that to the 3D printers.</p>
<p>There are three steps to sending a dog name to the 3D printers:</p>
<ol>
<li>we ask the customer what their dog’s name is, and write it down on a note;</li>
<li>we send that note to the 3D printers, and then;</li>
<li>they produce a nameplate that they send to the customer.</li>
</ol>
<p>They don’t return our note to us — we don’t need it.</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c">// Get your peice of paper ready</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">original</span> <span class="o">=</span> <span class="nn">String</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
<span class="c">// Ask for the name of the dog and write it down</span>
<span class="nn">std</span><span class="p">::</span><span class="nn">io</span><span class="p">::</span><span class="nf">stdin</span><span class="p">()</span>
<span class="nf">.read_line</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span> <span class="n">original</span><span class="p">)</span>
<span class="nf">.expect</span><span class="p">(</span><span class="s">"Failed to read input dog name"</span><span class="p">);</span>
<span class="c">// Send the note to the printers</span>
<span class="nf">threedee_print</span><span class="p">(</span><span class="n">original</span><span class="p">);</span>
<span class="p">}</span>
<span class="c">// The printers will print the nameplate</span>
<span class="k">fn</span> <span class="nf">threedee_print</span><span class="p">(</span><span class="n">note</span><span class="p">:</span> <span class="nb">String</span><span class="p">)</span> <span class="p">{</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"{note}"</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>In this analogy, our written note is a <code class="language-plaintext highlighter-rouge">String</code>. A written note or a <code class="language-plaintext highlighter-rouge">String</code> is a good choice when:</p>
<ul>
<li>we can’t anticipate what a dog’s name will be when we open our business (we have no foresight at compile time), and/or;</li>
<li>we want the option to alter what we’ve written down — a notes or a <code class="language-plaintext highlighter-rouge">String</code> can be mutable (unlike a steel mould or string literal).</li>
</ul>
<p>We still want to fulfil these orders for weird dog names because we’re a business and we flippin’ love money. This means we need to commit some flexible resources to this task, but we don’t know how many yet.</p>
<figure style="width: 300px" class="align-right">
<img src="https://cooscoos.github.io/assets/images/post_imgs/gorilla.jpg" alt="" />
<figcaption>Ceci est me dog.[img: <a href="https://www.pexels.com/@pixabay/">Pixabay</a>]</figcaption>
</figure>
<p>The requests for dog names might be short names, they might be long, we might get hundreds of names, thousands, or even none.</p>
<p>To be safe, we keep a heap of paper and pencils aside just in case (paper and pencils are computer memory here, by the way, yeah-I-know-you-knew-that).</p>
<p>Could we send the location of a mould to a 3D printing company who are expecting written notes? In other languages, you could totally do this and expect the language to handle the conversions, but in Rust, the answer is rigidly “no”.</p>
<h3 id="youve-lost-your-note">You’ve lost your note!</h3>
<p>Disaster strikes. The 3D printing company started printing one of your doggy nameplates, but the print failed and they already threw your note away. The customer is waiting.</p>
<p>It was “Harambe” something, right? But can you remember the sequence of numbers? Chances are that you’ve forgotten, and what’s worse, you sent (or “moved”) your one copy of the note to the 3D printers, and they don’t give it back!</p>
<p>You can try calling <code class="language-plaintext highlighter-rouge">threedee_print(note);</code> again in your program, but the Rust compiler will rightly tell you that you’re trying to do the impossible and re-use a note that you no longer own.</p>
<p>This is the problem with sending a String to a function. As soon as you send your one copy, you’ve lost it. You can’t use it again for anything else.</p>
<p>So, what are your options? Well, next time, you could:</p>
<ol>
<li>make a clone of your note and send that instead;</li>
<li>ask the 3D printers to start returning a copy, or;</li>
<li>keep the note, put it up in your shop window, and tell the 3D printers that they need to send someone round to look at it.</li>
</ol>
<p>All of these approaches can be used in Rust.</p>
<h4 id="1-make-a-clone">1. Make a clone()</h4>
<p>Cloning the note before we send it means we can use the original note again afterwards.</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c">// Get your peice of paper ready</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">original</span> <span class="o">=</span> <span class="nn">String</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
<span class="c">// --snip-- (ask customer for dog's name, write it down)</span>
<span class="c">// Make a copy of the note</span>
<span class="k">let</span> <span class="n">note_copy</span> <span class="o">=</span> <span class="n">original</span><span class="nf">.clone</span><span class="p">();</span>
<span class="c">// Send the copy to the printers, keeping the original</span>
<span class="nf">threedee_print</span><span class="p">(</span><span class="n">note_copy</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>In this case <code class="language-plaintext highlighter-rouge">note_copy</code> has “moved” into the function <code class="language-plaintext highlighter-rouge">threedee_print</code>, and therefore it is no longer in scope of <code class="language-plaintext highlighter-rouge">main</code>.</p>
<p>We haven’t moved our <code class="language-plaintext highlighter-rouge">original</code>, so it stays in scope, and so we can use it again.</p>
<h4 id="2-returning-the-string">2. Returning the String</h4>
<p>Asking the 3D printers to return a copy of the note, or the original note, is achieved by modifying the threedee_print function.</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="c">// The printers will print the nameplate and return the note</span>
<span class="k">fn</span> <span class="nf">threedee_print</span><span class="p">(</span><span class="n">note</span><span class="p">:</span> <span class="nb">String</span><span class="p">)</span> <span class="k">-></span> <span class="nb">String</span> <span class="p">{</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"{note}"</span><span class="p">);</span>
<span class="n">note</span> <span class="c">// give a copy (or the original) note back!</span>
<span class="p">}</span></code></pre></figure>
<p>We actually have no way of knowing whether the 3D printers have returned the original note, or an identical copy of it. They’ll do whatever is most efficient, and the Rust compiler is exactly the same in this regard.</p>
<p>Worrying about whether we have an original or a copy is academic — we don’t care — we get an accurate note back, and so can now call:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>let note_back = threedee_print(note);
</code></pre></div></div>
<p>in our <code class="language-plaintext highlighter-rouge">main</code> function, and continue to use <code class="language-plaintext highlighter-rouge">note_back</code> as we please.</p>
<h4 id="3-use-a-reference-with-string">3. Use a reference with &String</h4>
<p>Our last option was to put the note up in our shop window, and ask the 3D printers to look at that note and use it as a reference:</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c">//-- snip --</span>
<span class="c">// Tell the printers to look at your copy</span>
<span class="nf">threedee_print</span><span class="p">(</span><span class="o">&</span><span class="n">original</span><span class="p">);</span>
<span class="c">// Do it again if you like</span>
<span class="nf">threedee_print</span><span class="p">(</span><span class="o">&</span><span class="n">original</span><span class="p">);</span>
<span class="p">}</span>
<span class="c">// The printers will print the nameplate based on a reference</span>
<span class="k">fn</span> <span class="nf">threedee_print</span><span class="p">(</span><span class="n">shop_window</span><span class="p">:</span> <span class="o">&</span><span class="nb">String</span><span class="p">)</span> <span class="p">{</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"{shop_window}"</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>The ampersand in front of <code class="language-plaintext highlighter-rouge">&original</code> means were’re sending <code class="language-plaintext highlighter-rouge">threedee_print</code> a ‘reference to a String’, called a <code class="language-plaintext highlighter-rouge">&String</code>.</p>
<p>Using <code class="language-plaintext highlighter-rouge">println!</code> in this example isn’t great — <code class="language-plaintext highlighter-rouge">println!</code> does a lot of hard work in the backround to be useful, so it will print out the note regardless of whether we pass it an actual note, or point to where the note is (our shop window).</p>
<p>To illustrate what’s happening better, we’ll create a struct called <code class="language-plaintext highlighter-rouge">DeskPlate</code>. This struct is not clever like <code class="language-plaintext highlighter-rouge">println!</code>; it’s very strict about having <code class="language-plaintext highlighter-rouge">dog_name</code> as a <code class="language-plaintext highlighter-rouge">String</code>, and it won’t accept anything else.</p>
<p class="notice--warning"><strong>Warning:</strong> This won’t compile.</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="c">// Define a struct for the Deskplate</span>
<span class="k">struct</span> <span class="n">DeskPlate</span><span class="p">{</span>
<span class="n">dog_name</span><span class="p">:</span> <span class="nb">String</span><span class="p">,</span>
<span class="p">}</span>
<span class="c">// The printers will print the nameplate based on a reference</span>
<span class="k">fn</span> <span class="nf">threedee_print</span><span class="p">(</span><span class="n">shop_window</span><span class="p">:</span> <span class="o">&</span><span class="nb">String</span><span class="p">)</span> <span class="k">-></span> <span class="n">DeskPlate</span><span class="p">{</span>
<span class="n">DeskPlate</span><span class="p">{</span><span class="n">dog_name</span><span class="p">:</span> <span class="n">shop_window</span><span class="p">}</span> <span class="c">// ! This won't work</span>
<span class="p">}</span></code></pre></figure>
<p>In the example above, we’ve told the 3D printers to try and create a DeskPlate based on a location (your shop window). Your shop window is not a dog’s name — it is a place where you can find a dog’s name, and so the code won’t compile.</p>
<p>We need to be more explicit. We need to tell the printers to make their own copy of our shop window note by using <code class="language-plaintext highlighter-rouge">note.to_owned()</code> or <code class="language-plaintext highlighter-rouge">note.clone()</code>:</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">fn</span> <span class="nf">threedee_print</span><span class="p">(</span><span class="n">shop_window</span><span class="p">:</span> <span class="o">&</span><span class="nb">String</span><span class="p">)</span> <span class="k">-></span> <span class="n">DeskPlate</span><span class="p">{</span>
<span class="c">// Ask the 3D printers to make a copy of what they see in your shop window</span>
<span class="k">let</span> <span class="n">note_copy</span> <span class="o">=</span> <span class="n">shop_window</span><span class="nf">.to_owned</span><span class="p">();</span>
<span class="n">DeskPlate</span><span class="p">{</span><span class="n">name</span><span class="p">:</span> <span class="n">note_copy</span><span class="p">}</span> <span class="c">// This runs fine</span>
<span class="p">}</span></code></pre></figure>
<p>Doing this will make the code compile fine.</p>
<h3 id="converting-between-notes-and-moulds-string-and-str">Converting between notes and moulds, String and &str</h3>
<h4 id="static-str-to-string-easy-peasy">&’static str to String: easy peasy</h4>
<p>Could we choose to 3D print a nameplate like “Rolo” even though we already have a steel mould? Yes, because we can always look at our mould and write down what we see in a note, converting a <code class="language-plaintext highlighter-rouge">&'static str</code> into a <code class="language-plaintext highlighter-rouge">String</code> like so:</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="k">let</span> <span class="n">mould_location</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span> <span class="o">=</span> <span class="s">"Rolo"</span><span class="p">;</span>
<span class="c">// Let's write down a note based on what we see in our mould</span>
<span class="k">let</span> <span class="n">note</span> <span class="o">=</span> <span class="n">mould_location</span><span class="nf">.to_string</span><span class="p">();</span>
<span class="nf">threedee_print</span><span class="p">(</span><span class="n">note</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<h4 id="string-to-static-str-hardy--pardy">String to &’static str: hardy … pardy?</h4>
<p>Converting a <code class="language-plaintext highlighter-rouge">String</code> to a <code class="language-plaintext highlighter-rouge">&'static str</code> is not so trivial.</p>
<p>The factory that makes steel moulds (i.e. the compiler) can do this, but it only gets run once.</p>
<p>After we’re running though? No chance. The best you can do is to hope that you already have a steel mould that matches your note, like this:</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c">// Someone has given you a note that says Rolo on it</span>
<span class="k">let</span> <span class="n">note</span><span class="p">:</span> <span class="nb">String</span> <span class="o">=</span> <span class="s">"Rolo"</span><span class="nf">.to_string</span><span class="p">();</span>
<span class="k">let</span> <span class="n">mould_location</span><span class="p">:</span> <span class="o">&</span><span class="nv">'static</span> <span class="nb">str</span> <span class="o">=</span> <span class="k">match</span> <span class="n">note</span> <span class="p">{</span>
<span class="mi">_</span> <span class="k">if</span> <span class="n">note</span> <span class="o">==</span> <span class="s">"Rolo"</span> <span class="k">=></span> <span class="s">"Rolo"</span><span class="p">,</span>
<span class="mi">_</span> <span class="k">=></span> <span class="nd">panic!</span><span class="p">(</span><span class="s">"I don't have the mould!"</span><span class="p">)</span>
<span class="p">};</span>
<span class="p">}</span></code></pre></figure>
<p>What you’ve done here, is looked at the note, gone into the back room and tried to find a mould that matches your note. If the note says “Rolo”, you’re in luck, because past you was wise. Nice.</p>
<p>Did you get given a name that you didn’t anticipate when you set up your business? Well you ain’t using a steel mould then, matey*.</p>
<p class="notice">*Kind of. There are ways to <a href="https://stackoverflow.com/questions/23975391/how-to-convert-a-string-into-a-static-str">leak the memory of a String to produce a &’static str</a>, but they go beyond the scope of this analogy, and it’s probably not something you’ll do a lot.</p>
<figure style="width: 350px" class="align-center">
<img src="https://cooscoos.github.io/assets/images/post_imgs/string_hat.jpg" alt="" />
<figcaption>Eric has panicked when parsing String. [img: <a href="https://www.pexels.com/@vitoriasantos/">Vitoria Santoss</a>] </figcaption>
</figure>
<h4 id="string-to-a-str-you-can-do-this">String to &’a str: you can do this</h4>
<p>A customer with a dog named “Lord Gumzies” is insisting on a moulded nameplate, they do not want a 3D print because “3D prints look all weird and ribbed”.</p>
<p>While you can’t make a new steel mould, you could try and cobble together your own mould out of polystyrene, and leave it lying on the shelf. Your polystyrene mould won’t last as long as a steel one, and it might move.</p>
<p>A polystyrene mould is what a <code class="language-plaintext highlighter-rouge">&'a str</code> is. That cheeky <code class="language-plaintext highlighter-rouge">'a</code> thing is similar to <code class="language-plaintext highlighter-rouge">'static</code> from before, and it’s called a “lifetime”. <code class="language-plaintext highlighter-rouge">&'a str</code> has a lifetime specifier <code class="language-plaintext highlighter-rouge">'a</code> which tells you how long we can safely point to the polystyrene mould (after that lifetime is up, we’re no longer guaranteed to find it at that location).</p>
<p>Rust’s compiler can often (but not always) figure out how long a variable or reference needs to last for, all on its own. Well done, Rust.</p>
<p>To convert a <code class="language-plaintext highlighter-rouge">String</code> to a <code class="language-plaintext highlighter-rouge">&'a str</code>, we do this:</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c">// Get your peice of paper ready</span>
<span class="k">let</span> <span class="k">mut</span> <span class="n">original</span> <span class="o">=</span> <span class="nn">String</span><span class="p">::</span><span class="nf">new</span><span class="p">();</span>
<span class="c">// Ask for the name of the dog and write it down</span>
<span class="c">// -- snip --</span>
<span class="c">// Make a polystyrene mould</span>
<span class="k">let</span> <span class="n">poly_mould</span> <span class="o">=</span> <span class="n">original</span><span class="nf">.as_str</span><span class="p">();</span>
<span class="p">}</span></code></pre></figure>
<p>Beware reader, be very ware. The use of the term “str” in the <code class="language-plaintext highlighter-rouge">as_str()</code> method doesn’t mean you’re producing a string literal or a <code class="language-plaintext highlighter-rouge">&'static str</code>. In fact <code class="language-plaintext highlighter-rouge">as_str()</code> will produce a mould with a lifetime which is <strong>not static</strong>.</p>
<p>A <code class="language-plaintext highlighter-rouge">&'static str</code> needs to be a valid reference for as long as our program runs, so the objects it points to must be permanent. If we define an object <em>after</em> compile time, that means that we don’t have a permanent object by definition.</p>
<p>This all matters because if we try to pour hot plastic into our polystyrene mould:</p>
<p class="notice--warning"><strong>Warning:</strong> This won’t compile.</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"> <span class="c">//Pour plastic in, get nameplate out?</span>
<span class="nf">hot_plastic</span><span class="p">(</span><span class="n">poly_mould</span><span class="p">);</span> <span class="c">// ! won't run</span></code></pre></figure>
<p>we’re going to end up with a hot mess. Remember, the function <code class="language-plaintext highlighter-rouge">hot_plastic</code> is expecting a <code class="language-plaintext highlighter-rouge">&'static str</code> — our technician is expecting to be pointed to a permanent steel mould.</p>
<p>Instead, we’ve pointed out a polystyrene mould that “might still be there”, to a technician who is carrying a bucket of piping hot liquid death.</p>
<p>How can we solve this? We need to define a new function, a new role for our technician, one which accepts a <code class="language-plaintext highlighter-rouge">&'a str</code>. Here’s one:</p>
<figure class="highlight"><pre><code class="language-rust" data-lang="rust"><span class="c">// Pour silicone in, get nameplate out</span>
<span class="k">fn</span> <span class="nf">silicone</span><span class="p">(</span><span class="n">any_mould</span><span class="p">:</span> <span class="o">&</span><span class="nb">str</span><span class="p">)</span> <span class="p">{</span>
<span class="nd">println!</span><span class="p">(</span><span class="s">"{any_mould}"</span><span class="p">);</span>
<span class="p">}</span></code></pre></figure>
<p>We can now pass this function a <code class="language-plaintext highlighter-rouge">poly_mould: &'a str</code> and it will work.</p>
<p class="notice">Hawk-eyed eagles among you have noticed that the function <code class="language-plaintext highlighter-rouge">silicone</code> can be passed a <code class="language-plaintext highlighter-rouge">&str</code>, but I told you earlier that a <code class="language-plaintext highlighter-rouge">&str</code> in your IDE always means <code class="language-plaintext highlighter-rouge">&'static str</code>, didn’t I? Yeah, when you’re defining string literals. If you see the term <code class="language-plaintext highlighter-rouge">&str</code> in a function’s arguments, it implicity means <code class="language-plaintext highlighter-rouge">&'a str</code>. This switching up of nomenclature will feel natural and totally cool one day, I promise.</p>
<h4 id="using-a-static-str-in-a-a-str-function">Using a &’static str in a &’a str function</h4>
<p>We can pass the <code class="language-plaintext highlighter-rouge">fn silicone</code> a <code class="language-plaintext highlighter-rouge">&'a str</code>, but can we pass it a <code class="language-plaintext highlighter-rouge">&'static str</code>? Can we ask our technician to pour silicone into a steel mould?</p>
<p>Yes, because the function <code class="language-plaintext highlighter-rouge">silicone</code> is not very restrictive: our technician doesn’t need to be pointed to references that will be valid “forever”. In this role, our technician will accept references that last any amount of time, including forever.</p>
<h2 id="summary">Summary</h2>
<figure style="width: 200px" class="align-right">
<img src="https://cooscoos.github.io/assets/images/post_imgs/mould.jpg" alt="" />
<figcaption>Plastic YUMMY. [img: <a href="https://www.pexels.com/@andres-ayrton/">Andres Ayrton</a>]</figcaption>
</figure>
<p>If you understood how to run a desk nameplate business for dogs, then you understand the logic behind Rust’s approach to string types.</p>
<p>Now go back and try again. Read all of those good articles that talk about the heap, the stack, ownership and lifetimes. Keep this analogy of writtten notes and steel moulds going if it helps you, but drop it once it becomes cumbersome.</p>
<p>Woof.</p>cooscoosThere’s one — a few — lots — even dozens — of good articles that explain the differences between a &str, &'static str, &'a str, String, and &String in Rust.