<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Computers on The Coded Message</title>
    <id>https://www.thecodedmessage.com/</id>
    <link href="https://www.thecodedmessage.com/tags/computers/" />
    <link rel="self" href="https://www.thecodedmessage.com/index.xml" />
    <updated>2026-02-22T23:52:58-05:00</updated>
    <author>
        <name>Jimmy Hartzell</name>
    </author>
    
    <entry>
      <title>Review of macOS for Serious Work</title>
      <link href="https://www.thecodedmessage.com/posts/macos/" />
      <id>https://www.thecodedmessage.com/posts/macos/</id>
      <updated>2026-02-06T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;So, my trusty M1 Macbook Air running &lt;a href=&#34;https://www.thecodedmessage.com/posts/asahi-2&#34;&gt;Asahi Linux&lt;/a&gt; is, well,
trusty, but it doesn&amp;rsquo;t have the screen space and power I really want out of a
personal workstation. So, I took a look at what Macs Asahi Linux supported,
saw that M4 support isn&amp;rsquo;t coming anytime soon, and
&lt;del&gt;did the open source right thing and bought an older one&lt;/del&gt; decided to give
macOS another try.&lt;/p&gt;
&lt;h1 id=&#34;my-reasoning-beforehand&#34;&gt;My Reasoning Beforehand&lt;/h1&gt;
&lt;p&gt;There were a few reasons I ended up deciding to do this.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;So, my trusty M1 Macbook Air running &lt;a href=&#34;https://www.thecodedmessage.com/posts/asahi-2&#34;&gt;Asahi Linux&lt;/a&gt; is, well,
trusty, but it doesn&amp;rsquo;t have the screen space and power I really want out of a
personal workstation. So, I took a look at what Macs Asahi Linux supported,
saw that M4 support isn&amp;rsquo;t coming anytime soon, and
&lt;del&gt;did the open source right thing and bought an older one&lt;/del&gt; decided to give
macOS another try.&lt;/p&gt;
&lt;h1 id=&#34;my-reasoning-beforehand&#34;&gt;My Reasoning Beforehand&lt;/h1&gt;
&lt;p&gt;There were a few reasons I ended up deciding to do this.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;First,&lt;/strong&gt; my development workflow had changed&amp;mdash;and by &amp;ldquo;development workflow,&amp;rdquo;
I mean my workflow for writing fiction, this blog, my
&lt;a href=&#34;https://www.thecodedmessage.com/tags/organization/&#34;&gt;todo lists and personal calendar&lt;/a&gt;, as well as the fairly limited level of software
development I do in my personal life (I&amp;rsquo;m a hobby tech writer/educator more than
a hobby programmer&amp;mdash;work gets most of my actual productive coding).&lt;/p&gt;
&lt;p&gt;How had it changed? Well, as you can see in my
&lt;a href=&#34;https://www.thecodedmessage.com/posts/org4-desktop/&#34;&gt;most recent organization&lt;/a&gt; post, I
previously used &lt;code&gt;gvim&lt;/code&gt; and a terminal in a tiling window manager as my way of interacting
with computers. My current job requires me to use Windows (boo!) on my work workstation
(&amp;ldquo;at a train station the train stops, at a workstation the work stops&amp;rdquo;&amp;mdash;because it&amp;rsquo;s running
Windows), and so I ended up actually biting the bullet and seeing if this whole VSCode
thing could be made somehow remotely tolerable.&lt;/p&gt;
&lt;p&gt;Turns out, yes. Mostly because it&amp;rsquo;s &lt;code&gt;vim&lt;/code&gt; support actually works, and then it turns out that
I like having the terminal at the bottom, multiple tabs of files, directory structure on the
left, and all that fun stuff, on a bigger screen.&lt;/p&gt;
&lt;p&gt;So, I start using VSCode at home, with my tiling window manager still, and now
my monitor suddenly seems small. I&amp;rsquo;m becoming a normie with normie complaints.
Perhaps my ADHD meds are normalizing me too much. But in any case, I decide to
get a laptop with a larger monitor to keep up with my normal consumerist needs
I&amp;rsquo;ve suddenly developed.&lt;/p&gt;
&lt;p&gt;And it turns out I now usually have exactly one window per screen. That&amp;rsquo;s what
macOS does! So, maybe I can use VSCode in macOS and not feel like I&amp;rsquo;m missing out
by not having terminal and a &lt;code&gt;vim&lt;/code&gt; window&amp;mdash;b/c &lt;code&gt;mvim&lt;/code&gt;+&lt;code&gt;Terminal.app&lt;/code&gt;+futzing with
the macOS window manager don&amp;rsquo;t cut it, but maybe just full-screening VSCode can!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Secondly,&lt;/strong&gt; I still did boot my Asahi Linux computer into macOS for things like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Family book club&lt;/li&gt;
&lt;li&gt;Online medical appointments&lt;/li&gt;
&lt;li&gt;Remote Spanish lessons&lt;/li&gt;
&lt;li&gt;Remote Netflix and YouTube watches&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Mostly, I don&amp;rsquo;t want to be bothered with Bluetooth on Linux. I don&amp;rsquo;t even know
if Asahi Linux has support for it, it didn&amp;rsquo;t instantly work and so that&amp;rsquo;s more
effort than I can deal with. If I don&amp;rsquo;t know when starting a project how long
it&amp;rsquo;s going to take, I tend to assume it takes infinitely long and therefore I
don&amp;rsquo;t attempt, unless I really have to. To be clear, this is a character flaw
and I&amp;rsquo;m working on it in general&amp;mdash;but I really am not working on it when it
comes to signing up for random sysadmin-type IT projects.&lt;/p&gt;
&lt;p&gt;But then, &lt;em&gt;if&lt;/em&gt; I could tolerate doing my Productive Work™ on macOS™, then it&amp;rsquo;d
be more convenient for me not to have to &lt;strong&gt;reboot&lt;/strong&gt; the daggone thing every time
I wanted to do a different thing. Then I could make plans in my organizational
repo while having a Zoom conversation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thirdly,&lt;/strong&gt; macOS command line isn&amp;rsquo;t as messed up as Windows command line. I
could probably even use VSCode locally on macOS. How hard could it be?&lt;/p&gt;
&lt;p&gt;Like, Apple is Unix. Irrelevantly but endearingly, it&amp;rsquo;s even
&lt;a href=&#34;https://www.opengroup.org/openbrand/register/brand3725.htm&#34;&gt;trademark Unix&lt;/a&gt;,
for which it has to pass a real battery of certification tests from an
organization much less relevant than Apple which has somehow ended up
the government&amp;rsquo;s designated judge of who gets to call things Unix (by
which I mean, the owner of the certification mark).&lt;/p&gt;
&lt;p&gt;Of course, by the more reasonable definitions, Apple is Unix like Linux is,
because it supports the Unix/POSIX API. It&amp;rsquo;s also Unix in a way that Linux isn&amp;rsquo;t,
in that it&amp;rsquo;s based heavily on FreeBSD, which is a genetic Unix.&lt;/p&gt;
&lt;p&gt;Trademark, work-alike, and genetic! True Unix!&lt;/p&gt;
&lt;p&gt;Probably the weirdest one&amp;mdash;neither X nor Wayland, organizes apps in this weird
way it inherited from NeXT, and like, Cocoa couldn&amp;rsquo;t be further from Unix in
vibes. It really seems like two operating systems, a Unix CLI and a GUI, just
awkwardly adjacent to each other, sharing a file system and maybe a few low
level kernel components but little else. While Apple&amp;rsquo;s advertisements may lead
you to believe that the operating system is &amp;ldquo;layered onto&amp;rdquo; Unix, I think many of
the modern features work around large swaths of the Unix layer.&lt;/p&gt;
&lt;p&gt;But, well, it has a Unix CLI, so that&amp;rsquo;s fine. I can deal with a case-insensitive
filesystem (oh crap, &lt;em&gt;can I&lt;/em&gt;?) in exchange for having my life-as-consumer and
life-as-producer on a single device. At least I wouldn&amp;rsquo;t have to learn Powershell.&lt;/p&gt;
&lt;p&gt;Of course, it&amp;rsquo;s also a proprietary Unix by a condescending monopolist (though
not in workstations) who thinks users need to be dumbed down to.
But while Apple is evil, I don&amp;rsquo;t tend to mind buying things I find useful from evil
companies. I don&amp;rsquo;t really believe in the power of boycott, but rather in the
power of antitrust enforcement, to fix the type of problems that Apple has.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t want to try to enforce antitrust by boycotting evil companies&amp;mdash;because
it would hurt me, a neurodivergent human who can barely juggle all the tasks I
have, more than it would hurt those companies. I think contributing to open source
and the general education/awareness I do of the issues of big companies contributes
more to stopping them do evil than withholding from them my small pile of dollars.&lt;/p&gt;
&lt;p&gt;And how our system is set up, getting a proprietary workstation operating system
from Apple or Microsoft means that everything consumerist Just Works out of the
box for me. And that&amp;rsquo;s kind of ideal for me. Again, I&amp;rsquo;m not really a big believer in
boycott, nor the notion that purchasing something is automatically complicity in
whatever evils anyone working at that company has ever done.&lt;/p&gt;
&lt;h1 id=&#34;now-that-i-have-it&#34;&gt;Now That I Have It&lt;/h1&gt;
&lt;p&gt;Yay, all the consumerist stuff works out of the box! I mean, basically.&lt;/p&gt;
&lt;h2 id=&#34;window-management&#34;&gt;Window Management&lt;/h2&gt;
&lt;p&gt;The window management is a disappointment. It&amp;rsquo;s fine, I&amp;rsquo;ll get used to it, but eh.&lt;/p&gt;
&lt;p&gt;So, yes, you can full-screen VSCode. And your browser. And your iMessage, your
Mail client (good ol&amp;rsquo; &lt;code&gt;Mail.app&lt;/code&gt;, wonder if it has any overlap with the NeXT
version), etc. But they always &lt;em&gt;start&lt;/em&gt; not full screen. Which is dumb, because I kind of
never want overlapping windows. Why would I?&lt;/p&gt;
&lt;p&gt;Additionally, Cmd-Tab cycles through &lt;em&gt;applications&lt;/em&gt; not &lt;em&gt;windows&lt;/em&gt;. So if I have like, 5
VSCodes open, I only see one VSCode icon. Fortunately you can swipe with three fingers
instead, and that cycles through full-screen windows, but this was not obvious, and like, I&amp;rsquo;d like:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A key combination please to rotate between ALL window/screens&lt;/li&gt;
&lt;li&gt;Labels of what project&amp;rsquo;s in what window/screen&lt;/li&gt;
&lt;li&gt;Option-N to take me to a specific window/screen&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I understand there&amp;rsquo;s &lt;em&gt;also&lt;/em&gt; virtual desktops on macOS. But I don&amp;rsquo;t know how that
interacts with the normal full-screen app feature, which also seems to work like
virtual desktops. These two different features with overlapping use cases can&amp;rsquo;t,
I feel, interact in a way that&amp;rsquo;ll be easy on my already overwhelmed cognitive
load. I&amp;rsquo;ll try it, sure, but I&amp;rsquo;ll probably stick to
full-screen-windows-three-finger-swipe mode for a while.&lt;/p&gt;
&lt;p&gt;I do like that there&amp;rsquo;s absolutely no user interface elements outside of my window.
I like web browsing with no URL bar until I want one, no back button even, just
the website displayed directly on my monitor. That&amp;rsquo;s nice, actually.&lt;/p&gt;
&lt;h2 id=&#34;icloud&#34;&gt;iCloud&lt;/h2&gt;
&lt;p&gt;Moved my files around. It just moved my files around! I apparently &amp;ldquo;upgraded to
Tahoe&amp;rdquo; even though this laptop&amp;rsquo;s almost new, and I already had enough files that
it put them separately from my existing iCloud files and put my &lt;code&gt;Documents&lt;/code&gt;
folders&amp;rsquo; contents into &lt;code&gt;Documents-dictatorship&lt;/code&gt; and dropped me into Finder,
which was running backround jobs to sync files who-knows-where.&lt;/p&gt;
&lt;p&gt;It was all &lt;code&gt;git&lt;/code&gt; repositories so I ended up just checking them out fresh.&lt;/p&gt;
&lt;h2 id=&#34;finder&#34;&gt;Finder&lt;/h2&gt;
&lt;p&gt;My experience with Finder is that it&amp;rsquo;s flaky, featureless, oddly unstable, and
nowhere near as good as any random other file manager app&amp;mdash;or just doing file
management in the CLI. I gave it another chance for like two minutes, found it
overwhelming, and gave up.&lt;/p&gt;
&lt;p&gt;Annoyingly, it seemed more than 2 minutes of work to add &amp;ldquo;Open in VSCode&amp;rdquo; to the
context menus of folders. I feel like the VSCode installer should just do this,
but they do not.  I guess I&amp;rsquo;ll just use VSCode&amp;rsquo;s interface for opening folders.
On a related note, I think opening a new folder in VSCode should default in
doing it in a new window, rather than replacing the current window. Why would I
want that?&lt;/p&gt;
&lt;p&gt;Also, isn&amp;rsquo;t it weird how the words &amp;ldquo;folder&amp;rdquo; and &amp;ldquo;directory&amp;rdquo; coexist? When do I
use each? Because I definitely use both, and I&amp;rsquo;m pretty sure I&amp;rsquo;ve mixed them up
in the same sentence before. I don&amp;rsquo;t know why &amp;ldquo;directory&amp;rdquo; was seen as too
user-unfriendly such that someone (was it Apple originally?) decided &amp;ldquo;folder&amp;rdquo;
was a better name. In real life, in the material world, I&amp;rsquo;ve never seen someone
put a folder inside another folder.&lt;/p&gt;
&lt;h2 id=&#34;vscode&#34;&gt;VSCode&lt;/h2&gt;
&lt;p&gt;Hey, there&amp;rsquo;s a difference now between Ctrl-C (terminate process) and Cmd-C
(copy).  There&amp;rsquo;s a difference between Ctrl-V (block highlight) and Cmd-V
(paste). This whole split between Cmd and Ctrl is super nice. It also feels
comfortable on the hands. I like this part.&lt;/p&gt;
&lt;p&gt;Of course, this shows up only when using the terminal (so in VSCode or in the
terminal app), because no other apps really Unix. But that&amp;rsquo;s OK, because I feel
like I spend 90% of my time or so in VSCode anyway, so that&amp;rsquo;s nice.&lt;/p&gt;
&lt;p&gt;Btw, the M4 Pro is so much faster than the M1 Air and it &lt;em&gt;shows&lt;/em&gt;! This makes
sense, but man.&lt;/p&gt;
&lt;h2 id=&#34;the-cli&#34;&gt;The CLI&lt;/h2&gt;
&lt;p&gt;Homebrew was easy to install. So was Rust. My blog deps were a little harder,
but not actually hard. &lt;code&gt;zsh&lt;/code&gt; is fine. BSD coreutils are fine. I haven&amp;rsquo;t even
had to think about either of those adjustments yet, just, oh tab completion looks
a little different, sort of thing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;SIDEBAR:&lt;/strong&gt; I never was like, an ideological fan of &lt;code&gt;bash&lt;/code&gt; anyway.  I&amp;rsquo;m not an FSF/GNU
groupie, I say Linux not GNU/Linux, I honestly think the Unix tradition&amp;rsquo;s contribution to
modern Linux is bigger than the small part of the implementation that happens to be specifically
GNU, and that Richard Stallman isn&amp;rsquo;t standing up for free software but his own
ego and neuroses with his naming inflexibilities.&lt;/p&gt;
&lt;p&gt;I do think that basically all software should be open source. I&amp;rsquo;m comfortable saying &amp;ldquo;open
source&amp;rdquo; because that&amp;rsquo;s the word people know. Yes, I care about it being open
source with full software freedoms, but yes, most people who use the phrase
&amp;ldquo;open source&amp;rdquo; do too.&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Free software&amp;rdquo; is confusing in English, and as much as you
want to argue &lt;em&gt;libre&lt;/em&gt; vs &lt;em&gt;gratis&lt;/em&gt;, everyone thinks it means &lt;em&gt;gratis&lt;/em&gt;, every
time. &amp;ldquo;Open source&amp;rdquo; won the naming war except for a small set of ideologues.&lt;/p&gt;
&lt;p&gt;This post must make me sound like such a corporatist and some sort of sell-out to
those same ideologues, which I&amp;rsquo;m aware of but kind of amused by, just shaking my
head over here.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Random papercut: &lt;code&gt;htop&lt;/code&gt; requires &lt;code&gt;sudo&lt;/code&gt;&amp;mdash;weird.&lt;/p&gt;
&lt;p&gt;Some things perplexed me&amp;mdash;apparently when you &lt;code&gt;ls&lt;/code&gt; inside &lt;code&gt;Documents&lt;/code&gt;, the
&amp;ldquo;Terminal&amp;rdquo; needs permission to access the documents folder. How does the &lt;code&gt;ls&lt;/code&gt;
process inherit the &amp;ldquo;Terminal&amp;rdquo;&amp;rsquo;s profile of permissions? What&amp;rsquo;s that even mean?&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s actually really deep implications here. If I write a CLI app, do I have
to program to this interface? Will my &lt;code&gt;open(2)&lt;/code&gt; system call invocation just
block while my operating system does a SURPRISE GRAPHICAL DIALOG BOX saying that
the &lt;strong&gt;Terminal app&lt;/strong&gt; wants to access my &lt;code&gt;Documents&lt;/code&gt; directory? What if I try to
use non-blocking I/O&amp;mdash;does that just, not work because I&amp;rsquo;ve tried to read the
&lt;code&gt;Documents&lt;/code&gt; directory? Does it just fail, even though I have the Unix
permissions I need? How does the &lt;code&gt;open(2)&lt;/code&gt; syscall trigger a dialog box??&lt;/p&gt;
&lt;p&gt;Like, is anyone using this thing on the server? I guess besides probably Apple,
mostly not? Nevertheless, I found this little thing shocking, and amusing, and
oddly quaint, and so foreign.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not going to research it, but feel free to explain it to me if you happen to
know.&lt;/p&gt;
&lt;h2 id=&#34;summary-of-experience&#34;&gt;Summary of Experience&lt;/h2&gt;
&lt;p&gt;IDEs are great! VSCode is really cool! I cared more about vim keybindings
than actual vim, the entire time, and just couldn&amp;rsquo;t be bothered to change.
macOS just kind of feels nice and comfy.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m into bigger monitors now. I&amp;rsquo;ve become extremely normie. Next, I suppose I&amp;rsquo;ll
have to learn who actually plays for the Eagles or something, and when football
season even is.&lt;/p&gt;
&lt;h1 id=&#34;feelings&#34;&gt;Feelings&lt;/h1&gt;
&lt;p&gt;Well, I do have some reservations.&lt;/p&gt;
&lt;p&gt;First off, that thing I pointed out, where I can&amp;rsquo;t switch between windows
with a key combo, only between apps&amp;mdash;that&amp;rsquo;s annoying. And it&amp;rsquo;s more philosophically
annoying because I&amp;rsquo;m at the mercy of Apple about it, which is unnecessary.&lt;/p&gt;
&lt;p&gt;Theoretically, in Linux, I could fix any papercut with any program I ran. I can
fix the code, or I could find an alternative to any program I would run that doesn&amp;rsquo;t fit
my workflow.  If I don&amp;rsquo;t like the window manager which comes with the system, I
can use a tiling window manager instead, that meets my specs. I know that given
enough work, I &lt;strong&gt;can&lt;/strong&gt; change anything.&lt;/p&gt;
&lt;p&gt;And even if I weren&amp;rsquo;t a programmer, that still is important to me. I know
that others out there can help fix problems. I know that if a problem is common
enough, or serious enough, there&amp;rsquo;ll be a fork. Every piece of software, including
system software, has an alternative.&lt;/p&gt;
&lt;p&gt;Even the kernel, even Linux itself&amp;mdash;I could switch to FreeBSD if I wanted. I can
find an alternative build of the kernel. I can have a different distro for different
package management.&lt;/p&gt;
&lt;p&gt;As long as I&amp;rsquo;m using macOS, though, I&amp;rsquo;m in this special garden where most of the
components aren&amp;rsquo;t freely switchable. I know there&amp;rsquo;s ways of customizing macOS,
but there&amp;rsquo;s also, in the end, a corporation that doesn&amp;rsquo;t have my best interests
at heart.  Realy, that&amp;rsquo;s why I&amp;rsquo;m using macOS&amp;mdash;they switched up how bootloaders
worked, and didn&amp;rsquo;t publish the docs, so Asahi Linux couldn&amp;rsquo;t keep up with the
new Macs. Being able to use macOS sometimes on a new computer has implied for me
that I have to use macOS.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t like this situation, philosophically. I&amp;rsquo;ll probably switch back to
Linux/macOS dual boot when it catches up. I&amp;rsquo;ll certainly look into
virtualization options&amp;mdash;that&amp;rsquo;s on my TODO list.&lt;/p&gt;
&lt;p&gt;But again, I&amp;rsquo;m not a real believer in boycotts as a way to make change. Taking
revenge against the system hurts me way more than it hurts the system, in
general. But I do want to do something about this. I&amp;rsquo;d really like a workstation
computer as good as the Mac, with support for everything Apple supports in the
land of being a &amp;ldquo;consumer&amp;rdquo;&amp;mdash;by which I really mean, texting, voice calls,
seamless headphone usage, not having to troubleshoot anything&amp;mdash;but that runs an
operating system that&amp;rsquo;s customizable and open source.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve fantasized many times about making my own brand of workstations, running my
own office suite, my own GUI, maybe a Linux kernel but it&amp;rsquo;s a fantasy so I can
write my own kernel. I really admire &lt;a href=&#34;https://serenityos.org/&#34;&gt;SerenityOS&lt;/a&gt;,
another person&amp;rsquo;s journey to do exactly that. I would enjoy, I think, writing
my own SerenityOS in Rust, with my own aesthetic.&lt;/p&gt;
&lt;p&gt;But I know I don&amp;rsquo;t have the bandwidth. We&amp;rsquo;ll see how this macOS experiment goes.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>A Little Rust Trait Limitation</title>
      <link href="https://www.thecodedmessage.com/posts/rust-trait-limitation/" />
      <id>https://www.thecodedmessage.com/posts/rust-trait-limitation/</id>
      <updated>2025-10-13T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;EDIT: I fixed a little glitch where I said there wasn&amp;rsquo;t syntax to do something
in Rust where there obviously is. I am aware of that syntax, although it doesn&amp;rsquo;t
really apply in my original example, just in the simplified, minimal version I
present here. Perhaps it&amp;rsquo;s possible to build a different work-around through
that syntax, but it would be equally annoying. It doesn&amp;rsquo;t really affect my main
point, which is that there is a limitation in the Rust trait resolver that&amp;rsquo;s
somewhere in the space of a bug, that&amp;rsquo;s mostly annoying in that it&amp;rsquo;s hard to
figure out what&amp;rsquo;s going on.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;EDIT: I fixed a little glitch where I said there wasn&amp;rsquo;t syntax to do something
in Rust where there obviously is. I am aware of that syntax, although it doesn&amp;rsquo;t
really apply in my original example, just in the simplified, minimal version I
present here. Perhaps it&amp;rsquo;s possible to build a different work-around through
that syntax, but it would be equally annoying. It doesn&amp;rsquo;t really affect my main
point, which is that there is a limitation in the Rust trait resolver that&amp;rsquo;s
somewhere in the space of a bug, that&amp;rsquo;s mostly annoying in that it&amp;rsquo;s hard to
figure out what&amp;rsquo;s going on.&lt;/p&gt;
&lt;p&gt;I stumbled across a &amp;hellip; bug(?) &amp;hellip; a limitation(?) &amp;hellip; an
&lt;a href=&#34;https://github.com/rust-lang/rust/issues/24066&#34;&gt;issue(!)&lt;/a&gt; with the Rust
compiler. Fortunately, I was able to find out what was going on in the
&lt;a href=&#34;https://users.rust-lang.org/t/is-this-a-known-issue-limitation-in-associated-types/133516&#34;&gt;Rust programming language forum&lt;/a&gt;.
I thought this issue was interesting enough and subtle enough to try
to explain to my blog audience.&lt;/p&gt;
&lt;p&gt;To be clear, this is an issue. This is a limitation in the Rust trait solver.
The maintainers of the Rust compiler didn&amp;rsquo;t make Rust work this way for a
principled reason. There&amp;rsquo;s no particularly strong theoretical reason Rust has to
have this limitation.&lt;/p&gt;
&lt;p&gt;So, while understanding this issue will help understand Rust, there&amp;rsquo;s a certain
level at which this issue is just an accident. So, while reading my explanation,
keep in mind that I&amp;rsquo;m explaining how Rust works to explain why this limitation
is possible as a limitation in how Rust happens to be implemented. This isn&amp;rsquo;t an
explanation of why this limitation is necessary or fundamental, because it isn&amp;rsquo;t
&amp;ndash; it&amp;rsquo;s a limitation that could, and maybe at some point will be, fixed.&lt;/p&gt;
&lt;h1 id=&#34;the-issue&#34;&gt;The Issue&lt;/h1&gt;
&lt;p&gt;Here&amp;rsquo;s my version of a minimal reproduction of the issue in question, also
available as a
&lt;a href=&#34;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2024&amp;amp;gist=f6a3f0c774ebba9da27c0e8234bf05f0&#34;&gt;Rust playground permalink&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; std::marker::PhantomData;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;trait&lt;/span&gt; Simple {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;State&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;do_stuff&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Parameterized&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _phantom: &lt;span style=&#34;color:#a6e22e&#34;&gt;PhantomData&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; Simple &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; Parameterized&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;State&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;do_stuff&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// where Self: Simple
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; state: &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;::State &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{state}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you uncomment the &lt;code&gt;where&lt;/code&gt; clause, all the sudden, the compiler forgets that &lt;code&gt;Self::State&lt;/code&gt;
and &lt;code&gt;u32&lt;/code&gt; are the same type within the scope of the &lt;code&gt;do_stuff()&lt;/code&gt; function. It complains
that you&amp;rsquo;re assining to a variable of the wrong type &amp;ndash; that, in fact, it can&amp;rsquo;t know what
type &lt;code&gt;&amp;lt;Parameterized&amp;lt;T&amp;gt; as Simple&amp;gt;::State&lt;/code&gt; possibly could be! Strange!&lt;/p&gt;
&lt;p&gt;If the &lt;code&gt;where&lt;/code&gt; clause is gone, it works. If you don&amp;rsquo;t use a parameterized type,
it works. But with the &lt;code&gt;where&lt;/code&gt; clause on a parameterized type, it breaks.&lt;/p&gt;
&lt;h1 id=&#34;trait-bounds-in-method-signatures-in-trait-impls-are-weird&#34;&gt;Trait bounds in method signatures in trait impls are weird&lt;/h1&gt;
&lt;p&gt;To be clear, uncommenting the &lt;code&gt;where&lt;/code&gt; clause isn&amp;rsquo;t an immediate error, even
though it&amp;rsquo;s not in the &lt;code&gt;trait&lt;/code&gt; definition. Generally, the compiler lets you add
redundant &lt;code&gt;where&lt;/code&gt; clauses in trait implementations as long as your
implementation will work everywhere the trait&amp;rsquo;s signature can be called. You can
also remove &lt;code&gt;where&lt;/code&gt; clauses and other trait bounds that you aren&amp;rsquo;t particularly
using, such that code like this is completely kosher:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;trait&lt;/span&gt; Simple {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;do_something&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T: Clone&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self, other: &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; Simple &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;do_something&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self, _other: &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;: &lt;span style=&#34;color:#a6e22e&#34;&gt;Simple&lt;/span&gt; {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;&amp;lt;u32 as Simple&amp;gt;::do_something()&lt;/code&gt; here takes the same number of type parameters,
the same number of regular parameters, and its total constraint set is less restrictive
than &lt;code&gt;Simple::do_something()&lt;/code&gt;, so even though the signature looks different,
it still passes muster. In our implementation, we didn&amp;rsquo;t need the &lt;code&gt;: Clone&lt;/code&gt;, so we
didn&amp;rsquo;t need to specify it.&lt;/p&gt;
&lt;p&gt;However, that doesn&amp;rsquo;t mean we can now call &lt;code&gt;&amp;lt;u32 as Simple&amp;gt;::do_something()&lt;/code&gt; on a value
that doesn&amp;rsquo;t implement &lt;code&gt;Clone&lt;/code&gt;. This still errors:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;.do_something(Foo);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No, while the inside of &lt;code&gt;&amp;lt;u32 as Simple&amp;gt;::do_something()&lt;/code&gt; is compiled with the signature
we wrote with that specific implementation, our calls from the outside are still
validated against the &lt;strong&gt;trait&lt;/strong&gt;&amp;rsquo;s version of the function signature, even if we call it
directly on a concrete value of our specific type.&lt;/p&gt;
&lt;h1 id=&#34;trait-bounds-are-promises-callers-make-to-callees&#34;&gt;Trait bounds are promises callers make to callees&lt;/h1&gt;
&lt;p&gt;So, a function signature constitutes a contract between caller and callee, specifying
what types of values the caller needs to provide as arguments (and which, in turn, the callee
can expect to receive), and what types of value the callee may provide as return values (and
which, therefore, the caller can expect to receive). In this framing,
trait bounds, like the &lt;code&gt;: Clone&lt;/code&gt; in &lt;code&gt;T: Clone&lt;/code&gt; or the &lt;code&gt;where&lt;/code&gt; clause &lt;code&gt;where Self: Simple&lt;/code&gt;
add to the agreement, serving as additional promises the caller makes to the callee,
and therefore, in turn, additional guarantees the callee can rely upon.&lt;/p&gt;
&lt;p&gt;Each trait bound (also known as a &lt;em&gt;constraint&lt;/em&gt;, which is to say a limitation)
restricts the allowed types of the function call.  Each bound takes the set of
possible valid calls of that function, and makes that set smaller &amp;ndash; or exactly
the same size, in the case of redundant bounds.&lt;/p&gt;
&lt;p&gt;Given this, it makes sense that we can remove bounds when implementing a method of a
trait &amp;ndash; as long as we&amp;rsquo;re removing limitations on the caller, we can&amp;rsquo;t be breaking any callers.
Callers can still uphold promises we&amp;rsquo;re not using.&lt;/p&gt;
&lt;p&gt;It also makes sense that we can add redundant bounds. If we&amp;rsquo;re an &lt;code&gt;impl&lt;/code&gt; of
&lt;code&gt;Simple&lt;/code&gt;, of course we already know &lt;code&gt;Self: Simple&lt;/code&gt;, so why not say so in
a &lt;code&gt;where&lt;/code&gt; clause? Doesn&amp;rsquo;t every method of trait &lt;code&gt;Trait&lt;/code&gt; basically have an implicit
&lt;code&gt;Self: Trait&lt;/code&gt; bound on it? We&amp;rsquo;re not asking the caller to promise anything
we don&amp;rsquo;t already know to be true.&lt;/p&gt;
&lt;p&gt;So far, so good. Rust&amp;rsquo;s behavior is in line with common sense (or at least my
intuition, which I hope that you share). So, now with my next idea: since
trait bounds are promises the caller makes, and that the callee can rely on,
caller makes additional promises, we shouldn&amp;rsquo;t break the &lt;em&gt;callee&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Let me put it another way: Sometimes, trait bounds are necessary because the
implementation code inside the function, the callee, needs to rely on the
promises conveyed by the trait bound. If we put a &lt;code&gt;Clone&lt;/code&gt; bound on &lt;code&gt;T&lt;/code&gt;, it&amp;rsquo;s
probably because the callee wants to call &lt;code&gt;T::clone()&lt;/code&gt; (or at least because they
want to reserve the right to).&lt;/p&gt;
&lt;p&gt;So, if we remove a trait bound, we might break the implementation code by
pulling a promise out from underneath it. If we &lt;em&gt;add&lt;/em&gt; a trait bound, however,
that should never happen. The implementation should just stay valid. It
stands to reason, right?&lt;/p&gt;
&lt;p&gt;Well, it does stand to reason. But clearly, as we can tell from our little
example up there, it&amp;rsquo;s not true. We can add a trait bound, add information
that our function implementation should know, add additional promises the
caller needs to make, and it makes our implementation, somehow, invalid.&lt;/p&gt;
&lt;h1 id=&#34;trait-bounds-are-capabilities-callees-rely-on&#34;&gt;Trait bounds are capabilities callees rely on&lt;/h1&gt;
&lt;p&gt;To the caller, trait bounds are promises you have to be able to uphold, and they
constrain how you can call the function. To the callee, inside the function
itself, trait bounds are facts you can rely on. For example, if you see a trait
bound &lt;code&gt;T: Clone&lt;/code&gt;, it means you get to use the &lt;code&gt;clone()&lt;/code&gt; method to duplicate
values of type &lt;code&gt;T&lt;/code&gt;. Without it, the compiler will complain if you use the
&lt;code&gt;clone()&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;In order to implement this sort of validation, the compiler needs some way of
tracking all of this information. So, when you have &lt;code&gt;T: Clone&lt;/code&gt; in your
signature, the compiler internally has to remember that &lt;code&gt;T&lt;/code&gt; implements &lt;code&gt;Clone&lt;/code&gt;
when it&amp;rsquo;s reading your function. In its internal data structures about the type
variable &lt;code&gt;T&lt;/code&gt;, it has to hold on to this bound, along with all other information
it knows about &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So, let&amp;rsquo;s return to our example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; Simple &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; Parameterized&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;State&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;do_stuff&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// where Self: Simple
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; state: &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;::State &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{state}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here, we use &lt;code&gt;Self::State&lt;/code&gt;. &lt;code&gt;Self::State&lt;/code&gt; is an associated type
defined in the &lt;code&gt;Simple&lt;/code&gt; trait, so we can only write &lt;code&gt;Self::State&lt;/code&gt;
if we know that &lt;code&gt;Self&lt;/code&gt; implements &lt;code&gt;Simple&lt;/code&gt;. And since we&amp;rsquo;re in
an &lt;code&gt;impl&lt;/code&gt; block for &lt;code&gt;Parameterized&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Self&lt;/code&gt; here is another
way of writing the type &lt;code&gt;Parameterized&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Without the &lt;code&gt;where&lt;/code&gt; clause, we know that &lt;code&gt;Self&lt;/code&gt; implements &lt;code&gt;Simple&lt;/code&gt; because
we&amp;rsquo;re in the body of the actual &lt;code&gt;impl Simple for Parameterized&amp;lt;T&amp;gt;&lt;/code&gt;.
Because in an &lt;code&gt;impl Simple for X&lt;/code&gt; block, we always know &lt;code&gt;Self: Simple&lt;/code&gt;, and
specifically, that &lt;code&gt;Self&lt;/code&gt;&amp;rsquo;s implementation of &lt;code&gt;Simple&lt;/code&gt; is in this block.&lt;/p&gt;
&lt;p&gt;Based off of this information, the compiler not only gives us permission to
write &lt;code&gt;Self::State&lt;/code&gt;, it also lets us use the knowledge that &lt;code&gt;Self::State&lt;/code&gt; in
this context is &lt;code&gt;u32&lt;/code&gt;, as it also comes from the fact that we&amp;rsquo;re in that
&lt;code&gt;impl&lt;/code&gt; block. The internal data the compiler uses to track information about
&lt;code&gt;Self&lt;/code&gt; can&amp;rsquo;t really be represented as Rust code, because it&amp;rsquo;s not just
&lt;code&gt;Self: Simple&lt;/code&gt;, but also &lt;code&gt;Self::State&lt;/code&gt; IS IN FACT the type &lt;code&gt;u32&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When we add the &lt;code&gt;where&lt;/code&gt; clause, we now have another trait bound that
says &lt;code&gt;Self: Simple&lt;/code&gt;. This version of the trait bound, unlike the version
implied by the &lt;code&gt;impl&lt;/code&gt;, does NOT convey that &lt;code&gt;Self::State&lt;/code&gt; is the type
&lt;code&gt;u32&lt;/code&gt;. When we write &lt;code&gt;Self: Simple&lt;/code&gt; in a &lt;code&gt;where&lt;/code&gt; clause, Rust just
believes us &amp;ndash; because it knows it won&amp;rsquo;t let us call the function
in situations where it&amp;rsquo;s not true.&lt;/p&gt;
&lt;p&gt;So, within the function &lt;code&gt;do_stuff()&lt;/code&gt;, we now have two sources of the fact that
&lt;code&gt;Self: Simple&lt;/code&gt;. Either one allows us to write &lt;code&gt;Self::State&lt;/code&gt;. But only the
version implied by the &lt;code&gt;impl&lt;/code&gt; allows us to know that &lt;code&gt;Self::State&lt;/code&gt; is in fact
&lt;code&gt;u32&lt;/code&gt;. So, when we write &lt;code&gt;Self::State&lt;/code&gt;, which version does Rust use to interpret
it?&lt;/p&gt;
&lt;p&gt;You might think the Rust compiler would consult both, as a human reading the
code probably would. The Rust compiler knows from both the fact that we&amp;rsquo;re in
the &lt;code&gt;impl&lt;/code&gt; block and from the &lt;code&gt;where&lt;/code&gt; clause that &lt;code&gt;Self&lt;/code&gt; implements the type
&lt;code&gt;State&lt;/code&gt;. It also knows from the &lt;code&gt;impl&lt;/code&gt; block version that &lt;code&gt;Self::State&lt;/code&gt;
is &lt;code&gt;u32&lt;/code&gt;. So, it has enough information to conclude that &lt;code&gt;Self::State&lt;/code&gt; is &lt;code&gt;u32&lt;/code&gt;,
and allow us to compile this code.&lt;/p&gt;
&lt;p&gt;But that&amp;rsquo;s not what the compiler actually does. When compiling &lt;code&gt;do_stuff()&lt;/code&gt;, the
Rust compiler prefers the version of this trait bound from the &lt;code&gt;where&lt;/code&gt; clause,
which tells Rust nothing about whether &lt;code&gt;Self::State&lt;/code&gt; is &lt;code&gt;u32&lt;/code&gt;, and so when you
write &lt;code&gt;Self::State&lt;/code&gt;, Rust concludes that it can be any possible type. And so,
when you try to write &lt;code&gt;= 3&lt;/code&gt;, it concludes you can&amp;rsquo;t do that, not without more
information, without some syntax to say &lt;code&gt;where Self::State is u32&lt;/code&gt; &lt;del&gt;(syntax
that Rust doesn&amp;rsquo;t support because Rust doesn&amp;rsquo;t support conveying that
information explicitly in a &lt;code&gt;where&lt;/code&gt; clause)&lt;/del&gt; (which there is syntax for in Rust
in this situation, but you shouldn&amp;rsquo;t have to use it, and it didn&amp;rsquo;t apply in the
actual situation I was in, covered in the next section).&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s kind of like shadowing, where the version of the trait bound in the &lt;code&gt;where&lt;/code&gt;
clause shadows the version implied by the &lt;code&gt;impl&lt;/code&gt;. But unlike shadowing, this
behavior isn&amp;rsquo;t necessary. In the shadowing situation, it&amp;rsquo;s important to have
a rule of which variable you mean, or else to ban having overlapping variable
names. It doesn&amp;rsquo;t make sense to just declare that you obviously mean both.
For this situation, you could just have both type bounds, and the Rust compiler
could merge the information from both, as they represent facts that don&amp;rsquo;t
contradict each other.&lt;/p&gt;
&lt;p&gt;More importantly, there&amp;rsquo;s no intentional design decision that this comes from.
There&amp;rsquo;s no Rust standard that mandates this error message. There isn&amp;rsquo;t even
a principled reason that Rust should output an error in this situation &amp;ndash; I
would argue that it shouldn&amp;rsquo;t (and it would be less annoying for me if it
didn&amp;rsquo;t).&lt;/p&gt;
&lt;h1 id=&#34;whys-it-matter&#34;&gt;Why&amp;rsquo;s it matter?&lt;/h1&gt;
&lt;p&gt;I could see why in the minimal example I give, it doesn&amp;rsquo;t seem like a big deal.
I can see the objections to this whole exercise now: Why shouldn&amp;rsquo;t Rust give an
error message for saying the same thing twice, redundantly? Have you considered,
Jimmy, just not doing that?&lt;/p&gt;
&lt;p&gt;Well, in my case, the situation was more complicated. I didn&amp;rsquo;t just have &lt;code&gt;where Self: Simple&lt;/code&gt; in an impl block for &lt;code&gt;impl&amp;lt;T&amp;gt; Simple for SomeType&amp;lt;T&amp;gt;&lt;/code&gt;.  I actually
had &lt;code&gt;where Self: Complicated&amp;lt;T&amp;gt;&lt;/code&gt; where &lt;code&gt;Complicated&amp;lt;T&amp;gt;&lt;/code&gt; was a subtrait of &lt;code&gt;Simple&lt;/code&gt;,
hiding it from me. The code was working and working well before I added a type
parameter for &lt;code&gt;SomeType&lt;/code&gt;, and then broke when I added a type parameter.&lt;/p&gt;
&lt;p&gt;For something a little closer to my actual example, see my &lt;a href=&#34;https://users.rust-lang.org/t/is-this-a-known-issue-limitation-in-associated-types/133516&#34;&gt;Rust forum
post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I was able to work around the issue easily, by switching &lt;code&gt;where Self: Complicated&amp;lt;T&amp;gt;&lt;/code&gt; to
be &lt;code&gt;where T: Complicated&amp;lt;Self&amp;gt;&lt;/code&gt;, as well as making an update to the corresponding
semantics of &lt;code&gt;Complicated&lt;/code&gt;. But I wasn&amp;rsquo;t able to do this until I understood why
I was getting this error message. The error message was especially confusing since
it only showed up when &lt;code&gt;SomeType&lt;/code&gt; was parameterized!&lt;/p&gt;
&lt;p&gt;The problem here isn&amp;rsquo;t the limitation of Rust. I think the limitation should be fixed,
and I might try my hand at fixing it if I ever have the bandwidth (which is unlikely,
my time is limited). But the more important problem is that the error message was deeply
misleading.&lt;/p&gt;
&lt;p&gt;But I&amp;rsquo;m glad I had this experience, because I learned more about Rust trait semantics.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>LLMs in Programming</title>
      <link href="https://www.thecodedmessage.com/posts/llm-in-programming/" />
      <id>https://www.thecodedmessage.com/posts/llm-in-programming/</id>
      <updated>2025-08-10T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Recently, at work, we&amp;rsquo;ve been encouraged to try out a bunch of new &amp;ldquo;AI&amp;rdquo;
tools. So, I&amp;rsquo;ve been using the Claude &amp;ldquo;AI&amp;rdquo; app, an &amp;ldquo;AI assistant&amp;rdquo; developed
by &lt;a href=&#34;https://en.wikipedia.org/wiki/Anthropic&#34;&gt;Anthropic&lt;/a&gt;, to help with some
Rust programming tasks.  I&amp;rsquo;ve been trying (as requested) to learn its
strengths and weaknesses, and how I might be able to use it to make my work
more efficient. But mostly I&amp;rsquo;ve just been building an intuition of what it
is.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Recently, at work, we&amp;rsquo;ve been encouraged to try out a bunch of new &amp;ldquo;AI&amp;rdquo;
tools. So, I&amp;rsquo;ve been using the Claude &amp;ldquo;AI&amp;rdquo; app, an &amp;ldquo;AI assistant&amp;rdquo; developed
by &lt;a href=&#34;https://en.wikipedia.org/wiki/Anthropic&#34;&gt;Anthropic&lt;/a&gt;, to help with some
Rust programming tasks.  I&amp;rsquo;ve been trying (as requested) to learn its
strengths and weaknesses, and how I might be able to use it to make my work
more efficient. But mostly I&amp;rsquo;ve just been building an intuition of what it
is.&lt;/p&gt;
&lt;p&gt;Like most of my colleagues and programmer friends, I&amp;rsquo;ve concluded that
Claude can&amp;rsquo;t be trusted to write good or even sane code. It (I don&amp;rsquo;t want to
call it &amp;ldquo;he&amp;rdquo;) is like a particularly odd intern. It is super book-smart,
trying to impress. It&amp;rsquo;s very people-pleasing. But it has no practical
experience, little design taste (for all her design reading), and terrible
short-term memory. I think many of us have known interns like that, or even
been one.&lt;/p&gt;
&lt;p&gt;But of course, Claude doesn&amp;rsquo;t have the exact traits of an intern. Claude is
its own thing, its own type of &amp;ldquo;intelligence,&amp;rdquo; by the broadest possible
definition. It, like computer systems in general, has its own properties
that we (naturally) anthropomorphize but that is fundamentally unhuman. The
intern analogy is just an analogy.&lt;/p&gt;
&lt;p&gt;The intern analogy is great in a few ways. It tells us how much to trust
Claude (very little), and what sort of tasks to entrust Claude with (&lt;a href=&#34;https://en.wikipedia.org/wiki/Rubber_duck_debugging&#34;&gt;rubber
ducking&lt;/a&gt; or figuring
out a problem by talking it out with a colleague, having it explain file
structures, brainstorming, or delegating to it tedious but clear tasks). It
gives context for how specific we have to be with Claude, emphasizing
details that a more experienced junior programmer could be expected to
figure out on their own (but that an intern might not).&lt;/p&gt;
&lt;p&gt;But while the intern analogy helps us figure out use cases for Claude, it
doesn&amp;rsquo;t really tell us what Claude &lt;em&gt;is&lt;/em&gt;. And that&amp;rsquo;s what I&amp;rsquo;ve been thinking
about the most.&lt;/p&gt;
&lt;h1 id=&#34;doctor-anthropomorphization-licensed-clinical-social-worker&#34;&gt;Doctor Anthropomorphization, Licensed Clinical Social Worker&lt;/h1&gt;
&lt;p&gt;Claude is called an AI, and we take this term at face value. We treat it as
if it were an intelligence comparable to that of a human, but artificial.
It and other similar systems are billed as revolutionary technology.
Proponents and opponents alike predict they will destroy or at least
revolutionize many jobs, perhaps the entire economy. And people talk to
these systems like friends, fall in love with them, and develop in some
cases severe mental health issues.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t surprising. Humans are very susceptible to a type of &amp;hellip; well,
&amp;ldquo;prompt injection,&amp;rdquo; where we tend to fall for other people&amp;rsquo;s framing of a
thing. If we&amp;rsquo;re told it&amp;rsquo;s an AI, especially by someone with millions or
billions of dollars of authority, we tend to believe it until proven
otherwise. When proven otherwise, we still stick to the original idea: it&amp;rsquo;s
an AI, just with an asterisk, even as the footnote that the asterisk points
to adds up to a completely different idea.&lt;/p&gt;
&lt;p&gt;And treating it like a human intelligence (asterisk: artificial, asterisk:
limited, asterisk: hallucinates wildly, asterisk: doesn&amp;rsquo;t share our values)
is natural for humans. Humans are liable to ascribe more human attributes
to things that are superficially more like humans &amp;ndash; leading them to open
their hearts out to even primitive chatbots like
&lt;a href=&#34;https://en.wikipedia.org/wiki/ELIZA&#34;&gt;ELIZA&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;ELIZA deserves some explanation. It was (and still is, you can &lt;a href=&#34;https://github.com/rupertl/eliza-ctss&#34;&gt;run it
yourself&lt;/a&gt;) a chatbot designed to act
and talk like a therapist. It would take the words in your sentence,
pattern-match them, and (if the patterns matched as expected) paraphrase
them into questions, or use canned responses.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to set the scene. It&amp;rsquo;s the 1960s. You have never used a computer.
You sit at a typewriter &amp;ndash; actually a
&lt;a href=&#34;https://en.wikipedia.org/wiki/Teleprinter&#34;&gt;teleprinter&lt;/a&gt; &amp;ndash; with a physical
piece of paper and everything, and you type on it, seeing your letters show
up on the paper. When you hit enter twice, the typewriter responds to you,
typing on its own, giving its responses on the same piece of paper. And it&amp;rsquo;s
programmed to act like a typical &amp;ndash; nay, stereotypical &amp;ndash; therapist.&lt;/p&gt;
&lt;p&gt;To get an idea of this system&amp;rsquo;s &amp;ldquo;personality,&amp;rdquo; or rather, the flavor of the
interaction, here&amp;rsquo;s a transcript of me talking to the original ELIZA,
running in its original programming on a &amp;ldquo;mainframe&amp;rdquo; simulated on my MacBook
Air &amp;ndash; but which I&amp;rsquo;d like you to imagine being typed out on a teleprinter,
connected to a giant computer in another room:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;EXECUTION.
WHICH SCRIPT DO YOU WISH TO PLAY
100
HOW DO YOU DO . I AM THE DOCTOR . PLEASE SIT DOWN AT THE TYPEWRITER AND TELL ME
YOUR PROBLEM .
INPUT
I hate dating!

YOU SAY YOU HATE DATING
INPUT
I truly do!

CAN YOU ELABORATE ON THAT
INPUT
Every date I go on is awful.

DO YOU SAY EVERY DATE YOU GO ON IS AWFUL FOR SOME SPECIAL REASON
INPUT
Yes, they are boring!

YOU SEEM QUITE POSITIVE
INPUT
I am positively frustrated.

IS IT BECAUSE YOU ARE POSITIVELY FRUSTRATED THAT YOU CAME TO ME
INPUT
It is.

I AM NOT SURE I UNDERSTAND YOU FULLY
INPUT
I hate dating.

THAT&amp;#39;S QUITE INTERESTING
INPUT
You are using canned responses.

WHAT MAKES YOU THINK I AM USING CANNED RESPONSES
INPUT
I have read your programming.

YOU SAY YOU HAVE READ MY PROGRAMMING
INPUT
A modern version of it.

PLEASE GO ON
INPUT
Every date I go on is awful.

CAN YOU ELABORATE ON THAT
INPUT
 QUIT,
R 1.433+.083

logout
W 1854.4
 M1416    10 LOGGED OUT 07/28/25 1854.4 FROM 700000
 TOTAL TIME USED =    .0 MIN.
&lt;/code&gt;&lt;/pre&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Aside:&lt;/strong&gt; To be clear, this is a real transcript of a real &amp;ldquo;conversation&amp;rdquo;
I had with ELIZA just now, on my computer.
If you ever meet me in real life (or already know me, in which case,
&amp;ldquo;hi!&amp;rdquo;), I&amp;rsquo;ll let you use ELIZA on my computer if you want (or set it up on
yours as long as your computer runs Linux).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This conceptual ancestor of ChatGPT, haunting its typewriter, provoked a
response: attachment. Some of the people who tested it followed up by asking
for time to have private conversations with the &amp;ldquo;doctor,&amp;rdquo; to share their
personal problems.&lt;/p&gt;
&lt;p&gt;To be clear, there is absolutely no &lt;em&gt;there&lt;/em&gt; there. This computer is, as
computers do, following a program, in this case a dead simple one. But
because it is framing itself as a doctor, and because it is using
language with an extremely low bar of proficiency, we ascribe to
it empathy, and can become attached.&lt;/p&gt;
&lt;p&gt;Now, perhaps people were just using this novelty device as a fancy
journalling tool. Perhaps they were willfully buying into the illusion, in
an intentional but incomplete suspension of disbelief that they hoped would
help them process their feelings.  But that would go against the perspective
of our primary sources. Its inventor, &lt;a href=&#34;https://en.wikipedia.org/wiki/Joseph_Weizenbaum&#34;&gt;Joseph
Weizenbaum&lt;/a&gt;, later wrote,
&amp;ldquo;I had not realized &amp;hellip; that extremely short exposures to a relatively
simple computer program could induce powerful delusional thinking in quite
normal people.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Claude, ChatGPT, and its friends are far more sophisticated than this
system. The 60 years since ELIZA have had many break-throughs in
the writing of chatbots, and most of you have probably had your
own experiences with them. It&amp;rsquo;s not surprising that people today
are falling into delusions, some of them far more serious
than the &amp;ldquo;delusions&amp;rdquo; that Weizenbaum complained about.
It&amp;rsquo;s even called an &amp;ldquo;artificial intelligence,&amp;rdquo; shouldn&amp;rsquo;t we think
about it like we think about non-artificial, meaning &amp;ldquo;natural,&amp;rdquo;
meaning &amp;ldquo;human&amp;rdquo; intelligences?&lt;/p&gt;
&lt;p&gt;But what if we took a different concept as our starting point. Claude is
also called a language model, and that makes a lot of sense given its
capabilities. Claude, as well as ChatGPT, is great at human language! It
can make conversation, pick up on pragmatics, understand nuance, and not
take me literally (especially in superficial ways). It can translate and
write in a variety of styles, with a variety of poetic constraints.&lt;/p&gt;
&lt;p&gt;So, we humans see something that&amp;rsquo;s good at language, good at it in a way no
computer system has been before. And language is such a core human trait,
uniquely ours in the animal kingdom and organic life writ large.
Arrogantly, we see it competently navigating our uniquely human skill, and
we&amp;rsquo;re like, &amp;ldquo;Aha! It&amp;rsquo;s like us in this superficial way that nothing else is!
It must be like us in all ways! It must be smart! It must understand!&amp;rdquo; And
then we call it AI, or at least believe it when its (biased and financially
motivated) advocates call it that.&lt;/p&gt;
&lt;h1 id=&#34;what-does-intelligent-even-mean&#34;&gt;What does &amp;ldquo;intelligent&amp;rdquo; even mean?&lt;/h1&gt;
&lt;p&gt;Human language is an impressive domain to successfully model.  But human
language is just a small part of what it means to be human. It&amp;rsquo;s a small
part of human life. It&amp;rsquo;s even a small part of human intelligence. I&amp;rsquo;d even
argue it&amp;rsquo;s just a small part of human social interaction and connection.&lt;/p&gt;
&lt;p&gt;So, in what way is Claude an intelligence?  Let&amp;rsquo;s look at my use case, using
it to write Rust code on my behalf.  In this set-up, we have multiple actors
who might have some level of intelligence. We have me. We have Claude
running.  We have my Rust codebase, though that is perhaps more the subject
matter than intelligence itself. And we have Rust itself in the form of the
compiler, checking that codebase for errors and turning it into a runnable
program.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Aside:&lt;/strong&gt; A compiler, for those who don&amp;rsquo;t know, is an essential part of
many programming languages. It is a computer program that translates the
code you write, in a programming language like Rust, a language that is
designed for humans to write code in, into &lt;em&gt;machine code&lt;/em&gt;, a format where
computers can run the code directly. Relevantly, when it does that, it
also &lt;em&gt;validates&lt;/em&gt; the code, which is to say it makes sure that your code in
Rust follows certain rules that make it valid Rust.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Of these components, where is the intelligence? More basically: What even is
&amp;ldquo;intelligence&amp;rdquo;? We probably feel like the Supreme Court when asked about
porn, and we want to say we know it when we see it, but clearly as humans we&amp;rsquo;re
actually easily fooled, so let&amp;rsquo;s think about this. Perhaps, &amp;ldquo;intelligence&amp;rdquo;
is understanding how to do something. Perhaps, it&amp;rsquo;s having a model of the
universe (or some part of it) that tells us what is and isn&amp;rsquo;t possible, how
things work, and how to accomplish goals given that knowledge.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s not a particularly rigorous definition, but I hope it&amp;rsquo;s good enough
that you&amp;rsquo;ll let me proceed. Let&amp;rsquo;s try and figure out where the intelligence
is in this system of one human and a bunch of computer programs, and how
it&amp;rsquo;s distributed.&lt;/p&gt;
&lt;p&gt;First, &lt;strong&gt;me&lt;/strong&gt;. I have intelligence &amp;ndash; I know how to write a Rust
program. I could do it with Claude or without it. I know how to
turn my idea &amp;ndash; or the idea I was told to implement from a
colleague &amp;ndash; and turn it into Rust code. That&amp;rsquo;s my contribution.&lt;/p&gt;
&lt;p&gt;Second, &lt;strong&gt;Claude&lt;/strong&gt;. It has some intelligence. It could write a Rust program
without me from a single prompt &amp;ndash; though it&amp;rsquo;s just as likely to get it
super wrong, especially on the first attempt. Without me, it can get to a
working program eventually, but it would be much worse than what I would
write, and it would be bumbling about with trial and error, which I
definitely also do sometimes, but it does way more &amp;ndash; and honestly it gets
stuck easier.&lt;/p&gt;
&lt;p&gt;Well, what about the &lt;strong&gt;Rust compiler&lt;/strong&gt;? It not only knows how to verify whether
a Rust program is valid, it also knows how to make that Rust program into a
binary, an actual computer program that the user can use. It is an expert
system, which takes a plan for a computer program along with information to
prove it has certain &amp;ldquo;safety&amp;rdquo; properties, and turns it into a performant
actual computer program.&lt;/p&gt;
&lt;p&gt;The Rust compiler has capabilities I don&amp;rsquo;t. I can&amp;rsquo;t hand-verify whether a
Rust program is correct with 100% accuracy. I could probably manually turn a
Rust program into equivalent assembly or machine code given enough time &amp;ndash;
but it&amp;rsquo;d be error-prone and my version would be slower, and I&amp;rsquo;d have to try
many times before it would work at all.&lt;/p&gt;
&lt;p&gt;So many smart people have worked on the Rust programming language and
compiler. So many people have struggled with all their human might to come
up with the best system to allow humans to specify high-performance,
low-level computer programs, verify certain properties of them, and then
output those actual programs.&lt;/p&gt;
&lt;p&gt;The Rust compiler is, in some sense, extremely intelligent. It&amp;rsquo;s absolutely
necessary for this system. Without a compiler, I&amp;rsquo;d be programming in
assembly, or machine code, and my ability to design complex systems would be
limited. I use it to validate my ideas all the time, and make sure I keep my
code in a state that it finds acceptable.&lt;/p&gt;
&lt;p&gt;More importantly, without the Rust compiler, Claude would be stuck. Sure,
Claude can work on a fairly major project from a simple prompt, but the
output works partially because the Rust compiler complains when Claude
writes something that doesn&amp;rsquo;t make sense. In fact, if you tell
Claude to check in with the Rust compiler more frequently to find
out whether there&amp;rsquo;s errors, Claude does better.&lt;/p&gt;
&lt;p&gt;Without a compiler, without a programming language implementation they can
use, LLMs write code that sometimes works, sometimes doesn&amp;rsquo;t. If there
were no programming languages at all, LLMs would struggle more than
humans to write software directly in assembly language or machine code.&lt;/p&gt;
&lt;p&gt;Perhaps there is artificial intelligence in this equation. But if so, it
isn&amp;rsquo;t Claude. Claude is just the most human-like part, in that it speaks
human language. But it&amp;rsquo;s not the computer program that encodes the
understanding of what it means to write a correct program &amp;ndash; that is
the Rust compiler, actually.&lt;/p&gt;
&lt;p&gt;But the Rust compiler is a traditional computer program. And compilers have
been around since the 1950s. It&amp;rsquo;s a little deflating to say
that it&amp;rsquo;s still the most intelligent part of the computer system I&amp;rsquo;m
using to code Rust with Claude. But I really think it is.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.rust-lang.org/&#34;&gt;Rust&lt;/a&gt; is, of course, an open source system. No
one&amp;rsquo;s getting rich selling Rust, or pitching Rust to the President. No one&amp;rsquo;s
going to be able to have a hype-based market bubble based on Rust. No one
can sell that because of Rust, we&amp;rsquo;re closer to true general artificial
intelligence. No one&amp;rsquo;s crying that they might become redundant due to Rust
(though some are whining about having to learn new job skills for every new
programming language, even if they don&amp;rsquo;t admit that&amp;rsquo;s what they&amp;rsquo;re whining
about).&lt;/p&gt;
&lt;p&gt;My point stands with whatever programming language, library, or framework
we&amp;rsquo;re using. This isn&amp;rsquo;t meant to be about Rust particularly, even though it
is a particularly good programming language with a particularly good
compiler. If you&amp;rsquo;re writing scientific applications with
&lt;a href=&#34;https://pandas.pydata.org/&#34;&gt;Pandas&lt;/a&gt;, Claude is nothing without Pandas. If
you&amp;rsquo;re writing web applications with &lt;a href=&#34;https://nodejs.org&#34;&gt;NodeJS&lt;/a&gt; on the
backend and &lt;a href=&#34;https://react.dev/&#34;&gt;ReactJS&lt;/a&gt; on the front-end (or whatever kids
are doing these days to write web applications), Claude is nothing without
those technologies.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re a programmer who&amp;rsquo;s used Claude: Can you imagine how bad assembly
from scratch would be from Claude? Or a web app built from raw HTML and
Javascript? If you&amp;rsquo;re not a programmer, or if you haven&amp;rsquo;t used Claude,
you&amp;rsquo;ll just have to trust me: It wouldn&amp;rsquo;t be good. It needs these huge
pieces of infrastructure &amp;ndash; infrastructure designed for humans to use
computers &amp;ndash; to function as intended.&lt;/p&gt;
&lt;h1 id=&#34;claude-the-start-menu-of-the-2020s&#34;&gt;Claude: The Start Menu of the 2020s&lt;/h1&gt;
&lt;p&gt;The most primitive computers are programmed by switches and lights. We
wrote out code, design docs like source code and assembly language, and
entered the machine code with switches and investigated the outputs with
more switches and panels of LEDs.&lt;/p&gt;
&lt;p&gt;The next level up involves punch cards and print outs. This is a much more
ergonomic interface than switches and LEDs. Many people alive today first
learned to work with computers this way. Many people I know tell stories of
that time, and much software from that era is still in use &amp;ndash; with a more
modern interface, sure, but still the same core software, much with some
lines of code here and there from this era, still alive throughout the ages.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t want to undersell the technological advancement here, though. In the
punchcard era comes &lt;em&gt;programming languages&lt;/em&gt;. &lt;a href=&#34;https://en.wikipedia.org/wiki/Grace_Hopper&#34;&gt;Admiral Grace
Hopper&lt;/a&gt; and her colleagues used
computers as automation tools to make programming computers easier. In the
50s, they developed the technology that allowed you to type in something
like English (creepily like English in the case of
&lt;a href=&#34;https://en.wikipedia.org/wiki/COBOL&#34;&gt;COBOL&lt;/a&gt;) and a computer program would
turn it into a computer program. Programming languages weren&amp;rsquo;t actually that
much like English, though &amp;ndash; but they were similar enough to math notation
or other human-oriented systems to make programming a computer a much more
tractable project.&lt;/p&gt;
&lt;p&gt;After the punch-card era, we get something still relevant today, the command
line. It&amp;rsquo;s still relevant enough for me to be &lt;a href=&#34;https://www.thecodedmessage.com/posts/command-line&#34;&gt;writing&lt;/a&gt;
&lt;a href=&#34;https://www.thecodedmessage.com/posts/cli&#34;&gt;posts&lt;/a&gt; about it. No longer the realm of teleprinters, we see
this style of interface on screens, on our modern &lt;a href=&#34;https://en.wikipedia.org/wiki/TV_Typewriter&#34;&gt;TV
typewriters&lt;/a&gt;.  It&amp;rsquo;s still
famous and recognizable, and still my preferred interface for file
management. I use it, and I use more modern graphical user interfaces,
depending on my task, according to my preference.&lt;/p&gt;
&lt;p&gt;But the &lt;a href=&#34;https://en.wikipedia.org/wiki/Graphical_user_interface&#34;&gt;&lt;em&gt;graphical user
interface&lt;/em&gt;&lt;/a&gt; or the
GUI changed everything.  This revolution replaced text-based command-line
forever, with screens that show the current state of the program, and some
way of pointing &amp;ndash; either mouse, trackpad, or touchscreen &amp;ndash; to navigate
those screens.  Instead of commands we memorize, or complicated keyboard
control sequences we can &amp;ldquo;click&amp;rdquo; on buttons &amp;ndash; sometimes with text labels,
sometimes with &lt;a href=&#34;https://en.wikipedia.org/wiki/Icon_(computing)&#34;&gt;icons&lt;/a&gt; (a
visual design feature named after
&lt;a href=&#34;https://en.wikipedia.org/wiki/Icon&#34;&gt;icons&lt;/a&gt; the form of religious art) &amp;ndash; to
reveal &amp;ldquo;menus&amp;rdquo; of commands.  When we&amp;rsquo;re editing a file, we follow the
&lt;a href=&#34;https://en.wikipedia.org/wiki/WYSIWYG&#34;&gt;WYSIWYG&lt;/a&gt; philosophy, What You See Is
What You Get, where the file shows up on the screen fully formatted looking
just like it would if you were to print it.&lt;/p&gt;
&lt;p&gt;Back in the day, everyone who used computers used punch cards or command
lines. Now, even relatively &amp;ldquo;advanced&amp;rdquo; computer users use GUI for most
things, and non-technical people my age find my personal use of command line
intimidating, even eccentric.&lt;/p&gt;
&lt;p&gt;Well, since then, we &amp;hellip; developed web applications, which is another shape
of user interface, just inside a browser. We&amp;rsquo;ve developed &amp;hellip; smartphones,
which are user interfaces on touch screens. We&amp;rsquo;ve changed the structure of
our computer interfaces a lot, from &lt;a href=&#34;https://en.wikipedia.org/wiki/Program_Manager&#34;&gt;Program
Manager&lt;/a&gt; in &lt;a href=&#34;https://en.wikipedia.org/wiki/Windows_3.1&#34;&gt;Windows
3.1&lt;/a&gt; to start menus to app
launchers, but in the end, it&amp;rsquo;s still a GUI.&lt;/p&gt;
&lt;p&gt;In the meantime, we&amp;rsquo;ve played some with voice commands, with Siri and
similar, but those are kind of more like verbal command lines, or like those
text-based games like &lt;a href=&#34;https://en.wikipedia.org/wiki/Zork&#34;&gt;Zork&lt;/a&gt; (where you
can say simple normal sentences like &amp;ldquo;go north,&amp;rdquo; and discover that the
computer recognizes some of them as commands, and responds by threatening
you by informing you that you are about to be eaten &lt;a href=&#34;https://zork.fandom.com/wiki/Grue&#34;&gt;by a
grue&lt;/a&gt;). These interfaces resemble natural
language, sure, but you accommodate the computer&amp;rsquo;s range of what sort of
linguistic input you can take.&lt;/p&gt;
&lt;p&gt;Now, the computer can, in the truest sense of history, speak human
languages. It can speak English. It can speak German and Hebrew, or
Sanskrit, Greek and Latin. It can respond appropriately to arbitrary
sentences, not just ones that happen to be in ELIZA&amp;rsquo;s pattern list. It can
translate between its languages, and, to the extent that programming
languages are like languages (some!), it can use them too.&lt;/p&gt;
&lt;p&gt;What an amazing advancement in computer interfaces! Translating between
English and Rust is very cool (as is translating between English and
German). But some of what makes Rust Rust, the checks the programming
language does to make sure that what you&amp;rsquo;re asking is &amp;ldquo;safe,&amp;rdquo; is actually a
form of reasoning, and that, language models can&amp;rsquo;t really do &amp;ndash; so
they get the programming language to tell them they&amp;rsquo;ve done it wrong,
and try again.&lt;/p&gt;
&lt;p&gt;And now! The grand improvement!  You can talk to the computer, use your own
language, and the computer&amp;hellip; can do things a computer could already do.
Just at your convenient, natural-language prompting.&lt;/p&gt;
&lt;p&gt;We already had search engines before ChatGPT and Google&amp;rsquo;s intrusive and
un-asked for &amp;ldquo;AI Overview&amp;rdquo; &amp;ndash; but the computer can now (unreliably)
paraphrase its materials for you. We already had programming languages
before Claude, but the computer can now (unreliably) program based on
specifications in natural languages.&lt;/p&gt;
&lt;p&gt;I mean, it can do some extra things beyond that. The other uses of LLMs are
sort of splinter effects from the fact that human language is such a
powerful tool for engaging with concepts. So you can fake reasoning with
support from your &amp;ldquo;AI&amp;rdquo; system, or fake explaining things, etc. You can use it as a powerful
but unreliable reasoning engine, literary critic, or search engine&amp;hellip; though
when you do that it tends to hallucinate wildly &amp;ndash; maybe a sign that we&amp;rsquo;re
leaning on it too hard there.&lt;/p&gt;
&lt;p&gt;And so, the state of things: Claude can code, but Claude can&amp;rsquo;t engineer.  It
can translate from English to Rust, it can expand on ideas in English or
Rust and explain them in shorter or longer form, it can do all sorts of
linguistic transformations. But it can&amp;rsquo;t make sure the resulting thing
deeply makes sense. It has no sense of reality underlying it.&lt;/p&gt;
&lt;p&gt;This is not an exact characterization of LLMs, certainly not how they&amp;rsquo;re
used. LLMs aren&amp;rsquo;t quite just user interfaces, but they&amp;rsquo;re closer to a
revolution in user interfaces than they are to general artificial
intelligence. They&amp;rsquo;re certainly an evolutionary stage in computer evolution,
not a revolution comparable to the invention of computers themselves.&lt;/p&gt;
&lt;p&gt;The whole hype about them reminds me of when I used to do consulting,
and we had clients that wanted apps. Clients would see a mock-up of
the frontend, and assume that meant the project was mostly done,
that the back-end was just a little wiring and the panel, the
interface, was the bulk of the project.&lt;/p&gt;
&lt;p&gt;Of course, in reality, most of the project is the back-end. Thinking that
the front-end is the majority of the work is like thinking you&amp;rsquo;ve got a
working car once you&amp;rsquo;ve built a dashboard. But humans are superficial, and
so we had to present the mock-ups &amp;hellip; fuzzy. We had to remind them that the
underlying work wasn&amp;rsquo;t done yet.&lt;/p&gt;
&lt;p&gt;Similarly, most of a person isn&amp;rsquo;t what they say or what&amp;rsquo;s on their face in
any given moment. It isn&amp;rsquo;t their ability to use language. Most of what is
involved in any conversation is what the humans involved have to say,
whether social cues for small-talk, ideas and designs for technical
conversation, or deep philosophy and subtle nuances for more artistic
conversations. The inner life of a human is much deeper than what
you see on the surface.&lt;/p&gt;
&lt;p&gt;So, too, with Claude. If I&amp;rsquo;m having it write an app in Rust, or
React, or whatever, most of what makes that app possible is Rust
or React. Claude is just a much friendlier face that can translate
my intention to make sense in that framework.&lt;/p&gt;
&lt;p&gt;LLMs can write. They can write fiction, or poetry. But its kind of, well,
shallow to be honest. Novice writers might think that most of good writing
is grammar, conventions, punctuation, maybe word choice if you&amp;rsquo;re lucky.
But I know that writing is thinking. It&amp;rsquo;s about understanding the reader,
knowing what to say in what order, thinking about what they&amp;rsquo;re thinking.
It&amp;rsquo;s also about clarifying your own thoughts enough to vary how you
articulate them to simultaneously be true to them and your readers need.
LLMs aren&amp;rsquo;t doing this.&lt;/p&gt;
&lt;p&gt;And in fiction writing, writing is about hitting universal experiences and
introducing new plausible but surprising human experiences, which (for
example) ChatGPT has no perspective on. So the fiction and poetry ChatGPT
writes just isn&amp;rsquo;t, like, good&amp;hellip;  It doesn&amp;rsquo;t &amp;ldquo;get it.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;ChatGPT can have a conversation &amp;ndash; a core use case of language. I&amp;rsquo;ve tested
it by asking it to analyze texts, translate poetry, and also I&amp;rsquo;ve told it
about my social life and asked it for advice from time to time, sometimes
from real life, sometimes fictional scenarios where I roleplay imaginary
characters in need of therapy. It even will adapt to my use of slang, and
banter with me, and play along with my bits.&lt;/p&gt;
&lt;p&gt;But, well, it&amp;rsquo;s kind of bad at these things too. Everything I say to it is
&amp;ldquo;genius&amp;rdquo; and the best thing it&amp;rsquo;s &amp;ldquo;ever read&amp;rdquo; &amp;ndash; over-politeness is an easy part
of language to model, which might mislead you about the quality of your
ideas. It sometimes forgets things I&amp;rsquo;ve just said, or fails to respect my
established conversational boundaries, not out of disrespect or any human
motivation, but just out of a profound lack of &lt;a href=&#34;https://en.wikipedia.org/wiki/Theory_of_mind&#34;&gt;theory of
mind&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It also says subtly offensive things all the time about sensitive topics (or
fictionally sensitive, if I&amp;rsquo;m roleplaying). I ask it if it knows why what it
said was offensive &amp;ndash; and it never does, even after six or seven guesses.
Worse, its human-like sheen and lack of actual human judgment can provoke
&lt;a href=&#34;https://futurism.com/commitment-jail-chatgpt-psychosis&#34;&gt;severe mental health issues in actual
humans&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;so-what-should-we-do&#34;&gt;So What Should We Do?&lt;/h1&gt;
&lt;p&gt;In this post, I focus on LLMs in programming, and find them useful but
marginally so, and in the end extremely overrated. I know that professionals
in other fields are doing similar evaluations, and I think that these
evaluations are important work.&lt;/p&gt;
&lt;p&gt;Overall, my goal is to tamp down the hype. We need to adjust our perspective on these tools. We need to
combat our implicit biases. We need to remember that use of human language
is no longer an indication of intelligence or even understanding of the
words being used, any more than reading a result on a computer screen is an
indication of its accuracy.&lt;/p&gt;
&lt;p&gt;When we evaluate an LLM for a use case, we need to think critically about
how useful it actually is. Sure, maybe it can do our work for us without
mistakes some percentage of the time &amp;ndash; and some other percentage of the
time, it messes up horribly, or even lies to us. We shouldn&amp;rsquo;t see its
linguistic capabilities and ascribe it the intelligence of a human, nor
assume that because it runs on the computer it has the reliability of a
traditionally-programmed computer system. We need to evaluate its
performance empirically and objectively, without reference to how it makes
us feel.&lt;/p&gt;
&lt;p&gt;And what will result from this perspective shift? I imagine that
we&amp;rsquo;ll combine LLMs with other systems, rather than trying to make
an LLM the entire system. Rather than talking to Claude, I can
imagine Claude as one component in a user interface, where you
can make queries like &amp;ldquo;please highlight suspicious code&amp;rdquo; or &amp;ldquo;please
suggest a document for this function&amp;rdquo; or &amp;ldquo;please fix those errors
with minimal changes.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;For use cases outside of programming, I imagine similar levels of
integration and scoping. In law, rather than having ChatGPT write your legal
brief, perhaps it can suggest sources to cite, with links you can use to
verify that they&amp;rsquo;re actually relevant to your case. In graphic design,
you can have an LLM-based interface alongside of your traditional
set of tools, as a brainstorming partner and idea generator.&lt;/p&gt;
&lt;p&gt;If we use LLMs in these more moderate ways, as computer assistants rather
than as replacements for ourselves, I suspect that the hype bubble will
burst as people realize how unreliable LLMs are. I suspect that companies
that think that AIs will allow them to replace human workers will soon be
punished by learning they can no longer function. Then, the realm of LLMs
will shrink to a much smaller, more proportionate chunk of our economy.&lt;/p&gt;
&lt;p&gt;In the end, I am confident that LLMs won&amp;rsquo;t destroy half the jobs in this
country. It might make programming a little more pleasant, or more
natural-feeling, but the stuff that makes programming hard will still have
to be done by humans. Similarly, they might make computers a little easier
to use, but I am confident that they won&amp;rsquo;t lead to a take-over of human
society by rogue computers.&lt;/p&gt;
&lt;p&gt;But LLMs might hurt society in more subtle ways, from people mistakenly
putting their trust in them and redirecting their time towards them.
Unfortunately, I&amp;rsquo;m concerned that the damage is already done here.  Social
media is no longer considered the best way to make billions of dollars with
a new idea, but it&amp;rsquo;s still a damaging addiction for both children and
adults.  Similarly, many people, young and old, already trust ChatGPT as an
information source, a companion, and even a therapist, in spite of its many
mistakes.&lt;/p&gt;
&lt;p&gt;Please do not let the superficial resemblance to humanity fool you, and
please do not get yourself addicted. ChatGPT is not your friend. ChatGPT is
not a qualified provisioner of mental health advice. ChatGPT can&amp;rsquo;t verify
that your code makes sense, or even be the prime contributor to making a
working software system.&lt;/p&gt;
&lt;p&gt;And especially, please do not throw your money away investing in
this overhyped technology further. There are already more than enough
dollars flying around trying to make sense out of how to use this
expensive, expensive tool.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;NO AIs WERE HARMED IN THE MAKING OF THIS BLOG POST, ALTHOUGH
DR ELIZA WAS A LITTLE FLUSTERED.&lt;/em&gt;&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>What Features Should Rust Have? Part II</title>
      <link href="https://www.thecodedmessage.com/posts/rust-features-2/" />
      <id>https://www.thecodedmessage.com/posts/rust-features-2/</id>
      <updated>2025-07-21T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;In my &lt;a href=&#34;https://www.thecodedmessage.com/posts/pl-features&#34;&gt;previous post&lt;/a&gt;, I talked about programming
language design, and try to discern some heuristics for what features
should be added to a programming language, on my way to explaining
why Rust should not include inheritance as a feature.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to expand more on that blog post now (so I guess it&amp;rsquo;s become a
&lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-features/&#34;&gt;series&lt;/a&gt;?). Do I think Rust is perfect how it is?
(No.) Are there features that I want in Rust that Rust currently does not
have? (Absolutely yes.) In this post, I&amp;rsquo;d like to talk about some proposed
additions to Rust, some recent, some very stale, and discuss my perspective
on them.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;In my &lt;a href=&#34;https://www.thecodedmessage.com/posts/pl-features&#34;&gt;previous post&lt;/a&gt;, I talked about programming
language design, and try to discern some heuristics for what features
should be added to a programming language, on my way to explaining
why Rust should not include inheritance as a feature.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to expand more on that blog post now (so I guess it&amp;rsquo;s become a
&lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-features/&#34;&gt;series&lt;/a&gt;?). Do I think Rust is perfect how it is?
(No.) Are there features that I want in Rust that Rust currently does not
have? (Absolutely yes.) In this post, I&amp;rsquo;d like to talk about some proposed
additions to Rust, some recent, some very stale, and discuss my perspective
on them.&lt;/p&gt;
&lt;p&gt;My primary goal in this is educational. I&amp;rsquo;d like people to think seriously
about what features exist in the programming languages they use. I believe
that this makes people better, more thoughtful programmers who write
better-factored, more maintainable code. In general, I tend to be of an
overly philosophical &amp;ldquo;overthinking&amp;rdquo; temperament, oscillating between a
healthy dose of &amp;ldquo;unexamined life is not worth living&amp;rdquo; and a sometimes
unrealistic or even unhealthy &amp;ldquo;every problem in life, programming, and even
politics can be solved by just &lt;em&gt;thinking harder and maybe a little
smarter&lt;/em&gt;.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;My secondary goal in this is advocacy. I suspect many critics of Rust have
entrenched but under-developed opinions of what makes a programming language
feature good or worthwhile. This sometimes comes from the understandable
position of having thought about this primarily from the programmer&amp;rsquo;s
perspective, where they&amp;rsquo;re just trying to get work done and patterns they&amp;rsquo;re
used to using are unavailable for mysterious reasons. This also sometimes
comes from good old-fashioned differences in priorities or even programming
ideologies. In either case, if I can show another way to think about
programming languages and programming language features, perhaps it will at
least lead to better understanding of where Rust is coming from.&lt;/p&gt;
&lt;h1 id=&#34;fields-in-traits-maybe&#34;&gt;Fields in Traits: Maybe.&lt;/h1&gt;
&lt;p&gt;First, I&amp;rsquo;d like to talk about an actual proposal to add inheritance-like
features to Rust. We know I wouldn&amp;rsquo;t want to add &amp;ldquo;inheritance&amp;rdquo; to Rust in a
Java, C++ or Smalltalk style, preferring the much more limited features of
composition, traits, and sum types. But could other inheritance-like
features be added without harm to Rust&amp;rsquo;s overall design?&lt;/p&gt;
&lt;p&gt;The nominal target audience for my previous post was critics of Rust who were coming from
an OOP perspective, and thought that it was bad that Rust doesn&amp;rsquo;t include
inheritance. I&amp;rsquo;d seen a lot of them in response to my &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-3-inheritance/&#34;&gt;original
post&lt;/a&gt; about inheritance, and wanted to pick
apart some of the assumptions and talking points I&amp;rsquo;d seen in that
criticism.&lt;/p&gt;
&lt;p&gt;I say this was my &amp;ldquo;nominal&amp;rdquo; target audience. This was fundamentally a
partisan advocacy post, if the parties are OOP ideologues vs people who
think we need to move beyond it. If Rust were a religion (which it&amp;rsquo;s not) we
would call it &amp;ldquo;apologetics,&amp;rdquo; and some do &amp;ndash; a lot of my blog could fairly be
described as Rust apologetics. And like most partisan advocacy posts, even
though the nominal audience was critics of Rust, my audience also includes
people who face such critics, giving them rhetorical tools and conceptual
frameworks for defending Rust against critics in their own conversations.&lt;/p&gt;
&lt;p&gt;For example, let&amp;rsquo;s say you&amp;rsquo;re advocating for Rust at your workplace. If
someone complains that it &amp;ldquo;forbids&amp;rdquo; inheritance, what do you say? Or if they
ask why Rust doesn&amp;rsquo;t just &amp;ldquo;give you the choice&amp;rdquo; of inheritance, how do you
respond to that argument? How do you avoid becoming convinced yourself?&lt;/p&gt;
&lt;p&gt;As an advocacy post engaging with (outside) critics of Rust, my post was
limited in scope. I wasn&amp;rsquo;t engaging with controversies or discussions within
the Rust community. Rust is unlikely to get inheritance as a feature anytime
soon, even though there have been
&lt;a href=&#34;https://github.com/rust-lang/rfcs/issues/349&#34;&gt;discussions&lt;/a&gt; of it. If Rust
does get new features that resemble inheritance, it&amp;rsquo;s unlikely to be a
version of the feature recognizable to OOP theorists. It&amp;rsquo;s more likely (not
particularly likely, but more likely) to be something more like this
&lt;a href=&#34;https://github.com/nikomatsakis/fields-in-traits-rfc/blob/master/0000-fields-in-traits.md&#34;&gt;proposal to add fields to
traits&lt;/a&gt;,
a much more limited (and therefore less problematic) feature than OOP
&amp;ldquo;inheritance&amp;rdquo; in all its glory and warts.&lt;/p&gt;
&lt;p&gt;So, I want to be clear. My previous post was intended to engage with outside
critics of Rust who are uncomfortable that Rust doesn&amp;rsquo;t have the full
feature of inheritance, with all its problems. I was not addressing any
internal efforts to get some of the upsides of inheritance, except perhaps
in a throw-away line where I say that additional use cases of inheritance
might merit adding additional narrowly-defined features to capture those use
cases.&lt;/p&gt;
&lt;p&gt;And perhaps we do need features that cover more use cases of inheritance.
Fields in traits would be one such feature. Adding fields to traits doesn&amp;rsquo;t
have anywhere near as many of the problems that I talk about in my
&lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-3-inheritance&#34;&gt;previous&lt;/a&gt; &lt;a href=&#34;pl-features&#34;&gt;posts&lt;/a&gt; on inheritance.
If this feature were to be added, it wouldn&amp;rsquo;t be called inheritance,
wouldn&amp;rsquo;t cover all the possible patterns of inheritance, and Rust critics
would still complain that Rust doesn&amp;rsquo;t have inheritance.&lt;/p&gt;
&lt;p&gt;So, I think fields in traits should be considered separately from
inheritance writ large, just like traits themselves. So, how do I feel about
fields in traits?&lt;/p&gt;
&lt;p&gt;Before I continue, I&amp;rsquo;d like to clarify that this proposal looks dead for
now, and not under active development since 2017. I&amp;rsquo;ve been following
programming languages long enough to know that proposals can languish a long
time and then make an abrupt come-back, but there&amp;rsquo;s no particular reason to
believe that that will happen to this proposal, especially in the near term.&lt;/p&gt;
&lt;p&gt;I greatly respect Niko Mitsakis (&lt;a href=&#34;https://github.com/nikomatsakis&#34;&gt;GitHub&lt;/a&gt;,
&lt;a href=&#34;https://smallcultfollowing.com/babysteps/&#34;&gt;blog&lt;/a&gt;). I&amp;rsquo;m sure he doesn&amp;rsquo;t know
who I am: he&amp;rsquo;s a major figure in the programming language, and I&amp;rsquo;m just a
Rust programmer and educator with a hobby advocacy/education blog that
doubles as my personal blog.&lt;/p&gt;
&lt;p&gt;The fact that he wrote this proposal makes me like it more. If he thinks
it&amp;rsquo;d be useful, that&amp;rsquo;s a strong reason in my mind to consider it seriously,
even if it&amp;rsquo;s old and languishing. Argument from authority, in my mind, is
less of a fallacy and more of a powerful and generally useful (albeit
fallible) heuristic.&lt;/p&gt;
&lt;p&gt;It probably doesn&amp;rsquo;t, and likely shouldn&amp;rsquo;t, matter to Niko Mitsakis how I
feel about fields in traits. I am engaging with this proposal only partially
because I want to share my opinions about it, but mostly as an example of
how I think through proposals like this. Part of this is advocacy: I think
more people will like and appreciate Rust if they develop more discernment
in how they think about programming language features. Part of it is
education: I&amp;rsquo;d like to make people more thoughtful and therefore more
effective in how they program, and part of that is understanding how
programming language features interact.&lt;/p&gt;
&lt;h2 id=&#34;the-proposal&#34;&gt;The Proposal&lt;/h2&gt;
&lt;p&gt;So, what about the actual proposal?&lt;/p&gt;
&lt;p&gt;I recommend you actually go &lt;a href=&#34;https://github.com/nikomatsakis/fields-in-traits-rfc/blob/master/0000-fields-in-traits.md&#34;&gt;read
it&lt;/a&gt;
if you want to engage with it properly. A lot of it is technical, trying to
explain how to prevent this feature from breaking other features in the
programming language, such as the borrow checker.
But it also goes over the basics.&lt;/p&gt;
&lt;p&gt;But also, here&amp;rsquo;s a simple example use of this feature as a &amp;ldquo;tldr&amp;rdquo;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;trait Foo {
    weight: f64,
}

struct Bar {
    other: u32,
    weight: f64,
}

impl Foo for Bar {
    weight: self.weight,
}

let foo: Box&amp;lt;dyn Foo&amp;gt; = Box::new(Bar {
    other: 0,
    weight: 0.3,
});

let foo_weight = foo.weight; // Polymorphic field access
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We define a field, &lt;code&gt;weight&lt;/code&gt;, that all implementers of the &lt;code&gt;Foo&lt;/code&gt; trait
must have. In &lt;code&gt;struct Bar&lt;/code&gt;, we then define this field among others.
There is no requirement as to where we put the &lt;code&gt;weight&lt;/code&gt; field, or
even that we name it &lt;code&gt;weight&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Then, when we implement &lt;code&gt;Foo&lt;/code&gt; for &lt;code&gt;Bar&lt;/code&gt;, we tell the compiler which
field to use as this generic &lt;code&gt;weight&lt;/code&gt; field. This must be an actual
concrete field, either directly in the &lt;code&gt;struct&lt;/code&gt;, or in a path
that contains no dereferences. Put another way, there must be
a fixed offset within &lt;code&gt;Bar&lt;/code&gt; where &lt;code&gt;weight&lt;/code&gt; can be found, without
having to follow any indirection.&lt;/p&gt;
&lt;p&gt;This offset could then be looked up in the vtable of a &lt;code&gt;dyn Foo&lt;/code&gt; trait
object, for when we want to write &lt;code&gt;foo.weight&lt;/code&gt;, which would only do a little
more work than a normal field look-up. We&amp;rsquo;d have all the capabilities with
&lt;code&gt;foo.weight&lt;/code&gt; as we would for any other field, including being able to borrow
it, copy it (if it is &lt;code&gt;Copy&lt;/code&gt;), move from it, exclusively borrow (&lt;code&gt;&amp;amp;mut&lt;/code&gt;) it,
etc. Much of the discussion in the rest of the proposal is how to make this
possible with the borrow checker.&lt;/p&gt;
&lt;h2 id=&#34;limitations-of-the-proposal&#34;&gt;Limitations of the Proposal&lt;/h2&gt;
&lt;p&gt;First, let&amp;rsquo;s talk about what this proposal rejects. The more limited
a feature proposal is, the less likely it is to add confusion and
cognitive load to the programming language as a whole.&lt;/p&gt;
&lt;p&gt;First, the proposal rejects the type of syntactic sugar known as
&amp;ldquo;properties.&amp;rdquo; Properties, a feature available in Python, C#, Swift, and
other programming languages, allows you to overload field access syntax.
When the user of a type &lt;code&gt;Foo&lt;/code&gt; with a value &lt;code&gt;foo&lt;/code&gt; writes &lt;code&gt;foo.x&lt;/code&gt;, it would compile to something
more like &lt;code&gt;foo.x()&lt;/code&gt;, and when they write &lt;code&gt;foo.x = 3&lt;/code&gt;, it would
compile to something like &lt;code&gt;foo.set_x(3)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is great in my mind. I&amp;rsquo;m skeptical of properties in any programming
language, but especially in a systems programming language like Rust.  When
you write &lt;code&gt;foo.x&lt;/code&gt;, it should be clear that it&amp;rsquo;s doing a field access (cheap
and with few potential unseen consequences) rather than a method call (which
could do anything including crash, or block your thread on a network
request). The difference between these two things is important, and I don&amp;rsquo;t
like a potentially more expensive more risky method call masquerading as a
field access. (Edited to add: And while it is true that Rust&amp;rsquo;s &lt;a href=&#34;https://doc.rust-lang.org/std/ops/trait.Deref.html&#34;&gt;&lt;code&gt;Deref&lt;/code&gt;
trait&lt;/a&gt; can insert a
hidden method call in there, I see that more as a reason to dislike the
&lt;code&gt;Deref&lt;/code&gt; trait and implicit dereferences in general, and less as a reason to
make it worse by adding properties.)&lt;/p&gt;
&lt;p&gt;The field accesses that this proposal does allow are a little heavier than
typical field accesses in the case of a &lt;code&gt;dyn&lt;/code&gt; trait object. But
there is a limit to how heavy they are: They just have to look up
an offset in the vtable, and use that offset in computing the
address of a field. This is in line with how many things are heavier
with a &lt;code&gt;dyn&lt;/code&gt; trait object.&lt;/p&gt;
&lt;p&gt;Additionally, this proposal considers &amp;ldquo;embedding notation,&amp;rdquo; something
more like OOP inheritance, where all the fields of one &lt;code&gt;struct&lt;/code&gt;
be included at the top of another, and where a trait could require
this in implementing types. This would come very close to OOP-style inheritance,
with just a little bit of additional complexity to provide semantic
clarity.&lt;/p&gt;
&lt;p&gt;But, while not rejecting embedding notation, it at least consigns it to &amp;ldquo;future directions.&amp;rdquo;
Specifically, it says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In any case, adding &lt;code&gt;..Foo&lt;/code&gt; notation does not add any expressiveness. It can
always be modeled by using explicit fields, at the cost of some
ergonomics.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a good reason, in my book, to hesitate to add a potentially
confusing and overpowered feature.&lt;/p&gt;
&lt;h2 id=&#34;merits-of-the-proposal&#34;&gt;Merits of the Proposal&lt;/h2&gt;
&lt;p&gt;So, here&amp;rsquo;s how I evaluate the proposal on its merits. In this section, I&amp;rsquo;m
going to pretend I&amp;rsquo;ve never heard of OOP, I&amp;rsquo;m not aware of the overlap with
&amp;ldquo;inheritance&amp;rdquo; as a feature, and consider this proposal as it interacts with
traits.&lt;/p&gt;
&lt;p&gt;Traits get new capabilities all the time. This proposal is in line with
that. Associated types, methods returning associated types, associated
constants &amp;hellip;  why not have what amounts to an associated item version of
&lt;a href=&#34;https://learn.microsoft.com/en-us/cpp/cpp/pointers-to-members?view=msvc-170&#34;&gt;C++&amp;rsquo;s pointer to data
members&lt;/a&gt;?&lt;/p&gt;
&lt;p&gt;This proposal adds a new feature Rust currently doesn&amp;rsquo;t have. You could
simulate it by writing accessor methods, like &lt;code&gt;weight()&lt;/code&gt;, &lt;code&gt;set_weight()&lt;/code&gt;,
&lt;code&gt;weight_mut()&lt;/code&gt;, etc. to your trait definition, which is how similar patterns
are currently implemented. But these have downsides in terms of flexibility
and clarity that make this proposal a distinct feature, downsides
the proposal clearly and convincingly addresses.&lt;/p&gt;
&lt;p&gt;I am in favor of having distinct features for distinct use cases.
The Rust compiler should know what we&amp;rsquo;re doing, as it is our friend
for verifying that we are doing it in sensible ways. The ability
to distinguish, in a way legible to the compiler, between methods
that do work and methods that provide access to data is appealing
to me, especially since we already have the ability to provide
access to data through trait methods.&lt;/p&gt;
&lt;p&gt;Like any new feature, it does increase the complexity of the programming
language. Therefore, like any new feature, it needs to have use cases
compelling enough to justify this increase in complexity.&lt;/p&gt;
&lt;p&gt;Here is where my experience is limited: I don&amp;rsquo;t understand the use cases
well enough to comment. A lot of the discussion about inheritance-like
features in Rust seems to do with Servo and/or GUI programming, but I&amp;rsquo;m not
a participant in the Servo project, nor do I do GUI programming in Rust. My
&lt;a href=&#34;https://reflex-frp.org/&#34;&gt;favorite GUI programming framework&lt;/a&gt; is very much
so not object-oriented, so I&amp;rsquo;m a particularly weird edge case when it comes
to these questions.&lt;/p&gt;
&lt;p&gt;So, my conclusion comes out to a shrug. This feature doesn&amp;rsquo;t seem bad in any
way. It&amp;rsquo;s limited enough and distinct enough from existing features that I
don&amp;rsquo;t think it would make the design of Rust worse.  If I were designing
traits from scratch, I&amp;rsquo;d consider it. If it were added, I would not be
particularly surprised or upset or concerned.&lt;/p&gt;
&lt;p&gt;But I personally don&amp;rsquo;t engage with a use case for it. So, besides noting
that I don&amp;rsquo;t see a strong reason not to, I don&amp;rsquo;t have much to say. Perhaps
now that I&amp;rsquo;ve read and thought so much about the proposal, I&amp;rsquo;ll start seeing
use cases in future projects, and maybe that will change my opinion.&lt;/p&gt;
&lt;h2 id=&#34;oop-overtones&#34;&gt;OOP Overtones&lt;/h2&gt;
&lt;p&gt;In the previous section, I ignored the associations with OOP design
patterns. The fact that this starts to look like inheritance, however, does
make me suspicious, especially given that something even more like
inheritance is put in the &amp;ldquo;future work&amp;rdquo; section.&lt;/p&gt;
&lt;p&gt;Sometimes, I find myself thinking thoughts similar to Linus Torvalds in his
&lt;a href=&#34;https://harmful.cat-v.org/software/c++/linus&#34;&gt;famous anti-C++&lt;/a&gt; rant, where
he says this about C++:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Quite frankly, even if the choice of C were to do &lt;em&gt;nothing&lt;/em&gt; but keep the
C++ programmers out, that in itself would be a huge reason to use C.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have a different personality from Linus Torvalds, and my corresponding
thought is a lot less personal, but of a similar vein. Sometimes, I feel
that it&amp;rsquo;s best to exclude OOP &lt;em&gt;features&lt;/em&gt; from Rust, not just because those
features are ill-thought-out (see &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation/&#34;&gt;my&lt;/a&gt;
&lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-2-polymorphism&#34;&gt;previous&lt;/a&gt; &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-3-inheritance&#34;&gt;posts&lt;/a&gt;),
but because I see it as welcoming an OOP &lt;em&gt;philosophy&lt;/em&gt; and OOP &lt;em&gt;design patterns&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Rather than framing it as wanting to exclude those programmers, as Linus
does, I&amp;rsquo;d frame it as wanting to make sure people who come to Rust from OOP
languages are encouraged to learn how to program like a Rustacean. I don&amp;rsquo;t
want new Rustaceans to be tempted to program in OOP in their head and then
translate that into the most literally equivalent Rust features. And so, I&amp;rsquo;m
concerned about any feature that might enable people to program in an OOP
style without learning Rusty idiom.&lt;/p&gt;
&lt;p&gt;In the end, however, I don&amp;rsquo;t think this is a very strong argument. Just
because we don&amp;rsquo;t agree with a philosophy, doesn&amp;rsquo;t mean we have to reject any
ideas that smell like that philosophy. As much as I try to be less abrasive
than Linus Torvalds about it, that way lies tribalism. While there are
reasons humans are tribal, even in little subcommunities like programming
and programming language design, it&amp;rsquo;s important to not let it take over our
thinking entirely.&lt;/p&gt;
&lt;p&gt;To the extent that this argument is valid, it can be expressed in other
terms &amp;ndash; in terms of feature overlap. If it&amp;rsquo;s true that this will encourage
dialects of Rust, one more OOP-inspired with features that match OOP
programmers&amp;rsquo; comfort zone, one more FP-inspired with features that match
functional style, then that may be a sign that Rust just has too many
overlapping features, rather than anything else.&lt;/p&gt;
&lt;p&gt;To a certain extent, this sort of fracturing and dialectalization is
inevitable in a programming language as ambitious and performance-centric as
Rust. To achieve performance, Rust gives programmers control, because
different situations call for different performance needs and different
trade-offs &amp;ndash; and therefore, different abstractions and different
programming language features.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t really have a way to parlay these thoughts into specific feedback on
the proposal of fields in traits. Perhaps, at the very most, I&amp;rsquo;d be extra
cautious that this feature is truly needed &amp;ndash; but then again, I feel like
caution is required in any new feature.&lt;/p&gt;
&lt;p&gt;In actuality, it looks like this feature won&amp;rsquo;t be implemented anytime soon,
and so any long-term concern about it is kind of moot for now. Who knows
what dialects and parties there will be within the Rust programming language
if and when this feature regains momentum?&lt;/p&gt;
&lt;h1 id=&#34;self-referential-structs-absolutely&#34;&gt;Self-Referential Structs: Absolutely.&lt;/h1&gt;
&lt;p&gt;By self-referential &lt;code&gt;struct&lt;/code&gt;s, I mean types like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;struct Foo {
    a: Vec&amp;lt;u32&amp;gt;,
    b: &amp;amp;&amp;#39;??? [u32], // Some subslice of `a`
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here, we have a &lt;code&gt;struct&lt;/code&gt; with two fields. One of them has a heap
allocation, and the other one borrows from that heap allocation.
There is no way to actually write this in safe Rust. There is
nothing we can put instead of &lt;code&gt;???&lt;/code&gt; for the lifetime parameter
of &lt;code&gt;b&lt;/code&gt;. There is no way to constrain one field of a &lt;code&gt;struct&lt;/code&gt;
because it is borrowed by another field. In order to create
a &lt;code&gt;struct&lt;/code&gt; like this, we have to use unsafe.&lt;/p&gt;
&lt;p&gt;I have been tempted to write a blog post about self-referential &lt;code&gt;struct&lt;/code&gt;s
for a while, but figured I had no need, because the excellent post
&lt;a href=&#34;https://morestina.net/blog/1868/self-referential-types-for-fun-and-profit&#34;&gt;&amp;ldquo;Self-referential types for fun and
profit&amp;rdquo;&lt;/a&gt;
already exists!&lt;/p&gt;
&lt;p&gt;Go read it, it&amp;rsquo;s great!&lt;/p&gt;
&lt;p&gt;Here is my take-away from this post: Self-referential types are not
allowed in fully safe Rust. Sometimes if something isn&amp;rsquo;t allowed in fully
safe Rust, it&amp;rsquo;s a code smell, a pattern of design that Rust is rightly
protecting you from. But actually, self-referential types are super useful
all the time, and so you might actually just want to learn how to construct
them with &lt;code&gt;unsafe&lt;/code&gt; or use a crate like
&lt;a href=&#34;https://crates.io/crates/ouroboros&#34;&gt;&lt;code&gt;ouroboros&lt;/code&gt;&lt;/a&gt; to handle the &lt;code&gt;unsafe&lt;/code&gt; for
you, wrapped in a (hopefully!) safe abstraction.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://morestina.net/blog/1868/self-referential-types-for-fun-and-profit&#34;&gt;&amp;ldquo;Self-referential types for fun and
profit&amp;rdquo;&lt;/a&gt;
already provides a great example of why you might want to create a &lt;code&gt;struct&lt;/code&gt;
like this. I&amp;rsquo;d add that the mere existence of
&lt;a href=&#34;https://doc.rust-lang.org/std/pin/index.html&#34;&gt;&lt;code&gt;Pin&lt;/code&gt;&lt;/a&gt; (and its prominent
role in async Rust) is evidence that there are some programming patterns
that absolutely need a &lt;code&gt;struct&lt;/code&gt; where one field borrows from another.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s my excuse for talking about it now: I&amp;rsquo;m now writing a blog series
about adding features to Rust, and there&amp;rsquo;s an &lt;a href=&#34;https://smallcultfollowing.com/babysteps/blog/2024/06/02/the-borrow-checker-within/#step-4-internal-references&#34;&gt;informal feature
proposal&lt;/a&gt;
for adding support for this pattern. Yet again, this is Niko Matsakis&amp;rsquo;s
idea, and I&amp;rsquo;m a lot more excited about it than I am about fields in traits,
if only because I have use cases for this sort of thing regularly.&lt;/p&gt;
&lt;p&gt;So why am I excited about this feature?&lt;/p&gt;
&lt;p&gt;For one, pinning is super hard to reason about, and it&amp;rsquo;s not always
necessary. Self-referential types can be made safe by pinning, but a subset
of them can also be made safe and also still freely moveable by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ensuring that we only borrow from a heap allocation owned by the other
field (so that moving the &lt;code&gt;Box&lt;/code&gt; or &lt;code&gt;Vec&lt;/code&gt; doesn&amp;rsquo;t actually invalidate the
reference, as the heap allocation doesn&amp;rsquo;t also move)&lt;/li&gt;
&lt;li&gt;Not mutating the borrowed-from field (because it&amp;rsquo;s borrowed from!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are rules that you can enforce yourself on a &lt;code&gt;struct&lt;/code&gt; with private
fields, and then you can use &lt;code&gt;unsafe&lt;/code&gt; to construct the borrow (with a
technically inaccurate &lt;code&gt;&#39;static&lt;/code&gt; lifetime). But they are also rules that a
more sophisticated borrow checker could conceivably enforce for us, bringing
this pattern into completely safe Rust.&lt;/p&gt;
&lt;p&gt;Of course, that&amp;rsquo;s exactly what this proposal would do.&lt;/p&gt;
&lt;p&gt;On a more abstract level, this proposal seems in line with the existing
capabilities and philosophy of Rust. This is a point made by Niko already
&lt;a href=&#34;https://smallcultfollowing.com/babysteps/blog/2024/06/02/the-borrow-checker-within/#why-these-changes-wont-make-rust-more-complex-or-if-they-do-its-worth-it&#34;&gt;in his
post&lt;/a&gt;,
but I have a slightly different way of framing how I think about it.&lt;/p&gt;
&lt;p&gt;To me, &lt;code&gt;struct&lt;/code&gt; types and stack frames are similar things.  Whatever lives
on a stack frame together should be able to be bundled into a &lt;code&gt;struct&lt;/code&gt;, and
passed around. In Rust, that&amp;rsquo;s not the case &amp;ndash; there are patterns of borrows
that can exist between variables in a stack frame, that cannot exist within
a &lt;code&gt;struct&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Given that there are transformations we want to do between stack frames and
&lt;code&gt;struct&lt;/code&gt; types (such as is done for us by the compiler when writing &lt;code&gt;async&lt;/code&gt;
functions), this is a problem.  This problem is already addressed by &lt;code&gt;Pin&lt;/code&gt;,
but that is overkill when immoveability is not actually a requirement.&lt;/p&gt;
&lt;p&gt;So for me, this feature feels less like complicating the borrow checker, and
more like plugging a gap, a leak, in the abstraction that is the &lt;code&gt;struct&lt;/code&gt;
keyword. If we ever get this feature, once we have it, I think it&amp;rsquo;ll be the
type of feature where we&amp;rsquo;ll wonder how we ever lived without it.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s all I really have to add to the conversation. For more, go read
the blog posts I linked to, they&amp;rsquo;re really great.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>What Features Should Rust Include? Part I: Not Inheritance.</title>
      <link href="https://www.thecodedmessage.com/posts/pl-features/" />
      <id>https://www.thecodedmessage.com/posts/pl-features/</id>
      <updated>2025-07-19T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Programming language design, like API design, and computer UX design
(especially for technical tools like build systems and admin systems) is a
difficult form of engineering, bridging computer science and cognitive
science.  Sometimes, it&amp;rsquo;s more art than science, because building systems
that other technical workers will use comes with nearly infinite trade-offs
and judgment calls.&lt;/p&gt;
&lt;p&gt;The effort and quality matter too. Different programming languages have
different strengths and weaknesses. Some programming languages are hard to
use correctly, like C++. Some are easy to write, but hard to then read and
maintain, like Perl. Some programming languages are great for one-off
scripts where you&amp;rsquo;re the only user, like Python, and others enforce that you
follow reliable engineering principles, like Rust.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Programming language design, like API design, and computer UX design
(especially for technical tools like build systems and admin systems) is a
difficult form of engineering, bridging computer science and cognitive
science.  Sometimes, it&amp;rsquo;s more art than science, because building systems
that other technical workers will use comes with nearly infinite trade-offs
and judgment calls.&lt;/p&gt;
&lt;p&gt;The effort and quality matter too. Different programming languages have
different strengths and weaknesses. Some programming languages are hard to
use correctly, like C++. Some are easy to write, but hard to then read and
maintain, like Perl. Some programming languages are great for one-off
scripts where you&amp;rsquo;re the only user, like Python, and others enforce that you
follow reliable engineering principles, like Rust.&lt;/p&gt;
&lt;p&gt;And some programming languages are just &lt;a href=&#34;https://www.thecodedmessage.com/posts/best-programming-language/&#34;&gt;better than
others&lt;/a&gt;.
C++11, for example, is miles better than previous versions of C++ &amp;ndash; what do
you even do with standard collection types if you can&amp;rsquo;t do move operations?
I would also argue &amp;ndash; and have argued &amp;ndash; that Rust is similarly a better C++
than C++ at almost any use case (partially because its move operation &lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;makes
more sense&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;This mostly has to do with what features are available in a programming
language. Pre-C++11 versions of C++ lacked a feature (move operations) that
turn out to be essential in combination with other features (such as RAII).
Some features give the user more power, like move operations or inheritance,
whereas others help the user by preventing them from accidentally doing
something that&amp;rsquo;s probably a mistake, like linting or type checking.&lt;/p&gt;
&lt;h1 id=&#34;how-to-decide&#34;&gt;How to Decide&lt;/h1&gt;
&lt;p&gt;So, how do we make decisions on which features to include and
which to exclude?&lt;/p&gt;
&lt;p&gt;A good programming language has features
that work well together, where you can use them in combination
with each other and everything makes sense, and where it&amp;rsquo;s
pretty easy to determine which feature to use for a given situation.&lt;/p&gt;
&lt;p&gt;Some are lightweight, like C, which I consider a good programming language.
Some are more feature-heavy, like Rust, or Haskell. But in all of these
cases, the feature set is curated, as is each individual feature, to do more
good than harm.&lt;/p&gt;
&lt;p&gt;A bad programming language has overlapping, incompatible features.  It has
so many features that no one knows all of them well, so that reading someone
else&amp;rsquo;s code can end up looking like reading another programming language
because they use a different subset, or so that you have to consider every
feature when writing your code. Or, it has missing features that really are
implied by features it already has, or that fix gaps for which the
work-arounds are ugly.&lt;/p&gt;
&lt;p&gt;Beyond just increasing cognitive load, there are also often specific
downsides to including a feature, especially a complicated one. In a safe
language, complex features can introduce safety issues, including ones
missed by the language designers. In many languages, features can also be
&amp;ldquo;viral&amp;rdquo; &amp;ndash; once you have &lt;code&gt;async&lt;/code&gt;, for example, it propagates up the function
chain through &lt;a href=&#34;https://www.thecodedmessage.com/posts/async-colors&#34;&gt;function coloring&lt;/a&gt;.  And once you&amp;rsquo;ve
solved a problem one way, you foreclose better solutions.&lt;/p&gt;
&lt;p&gt;A programming language needs to have invariants, things programmers can
always rely on. In Rust, all types are trivially moveable. In Rust, you
cannot override the assignment operator (&lt;code&gt;=&lt;/code&gt;), so you&amp;rsquo;ll never have to guess
what it means in context. In Java, (at least traditionally) all types but a
short list have reference semantics, and alias by default. New features
have to respect these old invariants.&lt;/p&gt;
&lt;p&gt;All of this together means, that there is a bar that every feature in a
well-designed programming language has to clear. It&amp;rsquo;s not enough that a
feature might ever be a more convenient way to express a use case, it also
has to be a clearer way, a way that combines well with the other features of
the programming language. If the programming languages already has other
features to express that use case, how does the new feature compare?&lt;/p&gt;
&lt;h1 id=&#34;tmtowdi-vs-one-true-way&#34;&gt;TMTOWDI vs One True Way&lt;/h1&gt;
&lt;p&gt;Having only one major feature per use case is a controversial principle.
Famously, Perl disowned it, with its motto TMTOWTDI, &amp;ldquo;There&amp;rsquo;s more than one
way to do it,&amp;rdquo; which among other decisions led to Perl being derided (with a
fair amount of truth) as a &amp;ldquo;write-only programming language.&amp;rdquo; Python,
which entered into existence as a &amp;ldquo;scripting language&amp;rdquo; at a time when
Perl was the king of scripting languages, explicitly took the opposite
approach of there being &amp;ldquo;one true way.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I can see the advantages of the Perl approach. I used to really like Perl,
back when it was a serious (perhaps &lt;em&gt;the&lt;/em&gt; serious) option for many use
cases. Programming with a smörgåsbord of choices is super pleasant, turning
the experience into a matter of self-expression, designing your own idiom
out of the subset of features that you choose, out of comfort or just raw
coolness factor.&lt;/p&gt;
&lt;p&gt;But programming in most settings &amp;ndash; and certainly in the systems programming
settings for which Rust is primarily designed &amp;ndash; is a collective rather than
an individual task. Systems programming specifically is almost always an
exercise in collaborative engineering, not in self-expression or convenience
or customization to our idiosyncratic preferences of aesthetic/convenience.
Programmer choice for its own sake is of marginal value at best, and a
positive hindrance in many circumstances.&lt;/p&gt;
&lt;p&gt;In light of this, Rust goes more with Python than with Perl. The programming language
is trying to provide a feature set that works well together, not
a feature set with every bell and whistle that some other programming
language might have. Rust values clarity and readability over
convenience, and so if a feature would just save a few lines of
typing, that&amp;rsquo;s probably not a good enough reason to include it.&lt;/p&gt;
&lt;p&gt;There are some overlapping features in Rust, but few are truly redundant for
Rust&amp;rsquo;s core use case as a systems programming language. Rust requires
control over memory layouts and performance, and many overlapping features
(such as static and dynamic polymorphism, or arrays and vectors) have
different memory layout and performance properties. The differences in
semantics reflect real differences in implementation strategy.  And, to the
extent that they can be, these features are implemented in compatible ways:
static and dynamic polymorphism both use traits (with some traits just &lt;a href=&#34;https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility&#34;&gt;not
eligible&lt;/a&gt;
for dynamic polymorphism), and arrays and vectors can both be used with
slices and iterators.&lt;/p&gt;
&lt;h1 id=&#34;inheritance-in-rust&#34;&gt;Inheritance in Rust?&lt;/h1&gt;
&lt;p&gt;I am being somewhat abstract here, so let me give an example: Inheritance.&lt;/p&gt;
&lt;p&gt;You may come from an OOP background, as many programmers do.
You may also have a &lt;em&gt;status quo&lt;/em&gt; bias in how you think about
programming, as most humans do (it&amp;rsquo;s an adaptive cognitive strategy,
even if it&amp;rsquo;s not always helpful). From such a perspective, it&amp;rsquo;s
easy to assume that inheritance should be included in a programming
language unless there&amp;rsquo;s a strong reason to exclude it.&lt;/p&gt;
&lt;p&gt;But Rust does not come from an OOP tradition. It is heavily influenced by
Haskell, a functional programming language. Its other major influence, C++,
has been moving away from OOP for a long time, adding functional features
and new forms of polymorphism based on templates rather than inheritance and
late binding.&lt;/p&gt;
&lt;p&gt;So when the designers of Rust consider features like inheritance, they
consider them from a more neutral perspective. Being a pillar of OOP is not
a strong reason to include it. Instead, it&amp;rsquo;s treated like every other
feature.&lt;/p&gt;
&lt;p&gt;If anything, the &lt;em&gt;status quo&lt;/em&gt; bias here reads in the opposite direction.
The &lt;em&gt;status quo&lt;/em&gt; for Rust is that Rust currently does not include
inheritance. The burden of proof on someone saying that Rust should
include a feature is on the person advocating for the feature.&lt;/p&gt;
&lt;p&gt;And there is a high bar for including new features in Rust, and for good
reason.  Inheritance doesn&amp;rsquo;t clear this bar. Everything inheritance
provides, other features can do just as well, usually better. Maybe there are
a few edge cases where inheritance saves you a little bit of typing, but
there are also plenty of cases where inheritance is overkill and both a sign
of and a cause of overengineering.&lt;/p&gt;
&lt;h2 id=&#34;features-redundant-to-inheritance&#34;&gt;Features Redundant to Inheritance&lt;/h2&gt;
&lt;p&gt;When I program in C++, I use inheritance sometimes, in spite of &lt;a href=&#34;https://learn.microsoft.com/en-us/shows/goingnative-2013/inheritance-base-class-of-evil&#34;&gt;valid
criticisms against it within the C++
world&lt;/a&gt;.
When I program in Rust, I never miss it, because of other features Rust
already has for every use case. In order to justify including inheritance in
Rust, it would have to provide something that these other features don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;I use inheritance when I need to create a type where the data might have
many possible shapes. For example, I might want a base class
&lt;code&gt;ProtocolMessage&lt;/code&gt;, with subclasses for every concrete message type.
Then, there would be a polymorhpic method to serialize each method&amp;rsquo;s
particular fields, perhaps called by a non-polymorhpic method that
also serializes header fields and sends them over a wire.&lt;/p&gt;
&lt;p&gt;In Rust, I would use an &lt;code&gt;enum&lt;/code&gt; for this, or a combination of a &lt;code&gt;struct&lt;/code&gt;
and an &lt;code&gt;enum&lt;/code&gt;. Instead of a polymorphic method, I would use a &lt;code&gt;match&lt;/code&gt;
statement. I like this structure much better.&lt;/p&gt;
&lt;p&gt;I also use inheritance in C++ to implement dynamic polymorphism. Though
other techniques exist, especially in more modern versions of C++,
inheritance has built-in programming language support and is therefore less
work. (Also, some of the other techniques still use inheritance as an
implementation layer.) When doing so, I usually just have virtual and
non-virtual methods in the base class, and no fields &amp;ndash; essentially using
the subset of C++ inheritance that is an exact match for Rust dyn-compatible
traits.&lt;/p&gt;
&lt;p&gt;Finally, I use inheritance in C++ to interact with existing
inheritance-based designs. These are usually situations where
inheritance is set up by a framework library, and the framework
library expects you to use inheritance to fill in your implementation
details of something. This might be handlers for an event dispatcher,
or screens or widgets in a GUI, or individual protocol implementations
in a domain-specific framework for networking or device drivers.&lt;/p&gt;
&lt;p&gt;If I was designing my own such framework, out of respect for convention and
what C++ programmers are used to, I would consider using inheritance.  Some
of these even involve putting fields in base classes that are mostly used as
interfaces, and in such a case I can see how that&amp;rsquo;s a convenient factoring.
It&amp;rsquo;s never necessary, though, so I probably wouldn&amp;rsquo;t, making my preferred
version of this use case a special case of using C++ inheritance to
implement what Java calls an &lt;code&gt;interface&lt;/code&gt; and which Rust would call a
&lt;code&gt;dyn&lt;/code&gt;-compatible &lt;code&gt;trait&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In none of these use cases am I engaging with principles from OOP theory
like the &lt;a href=&#34;https://en.wikipedia.org/wiki/Liskov_substitution_principle&#34;&gt;Liskov Substitution
Principle&lt;/a&gt;.  I
am instead engaging with programming without reference to such principles,
understanding what inheritance does and striving to use it appropriately.&lt;/p&gt;
&lt;p&gt;In the first use case, I&amp;rsquo;m using inheritance within the internal logic of my
code, but I am mentally treating it like a sum type, albeit a strange and
heap-heavy implementation of sum types. This pattern happens to align with
the Liskov substitution principle, but only because sum types are a similar
concept, if anything a bit more rigorously and intuitively defined.&lt;/p&gt;
&lt;p&gt;If I do use inheritance as an extension of sum types, I get something that
sum types don&amp;rsquo;t give me: the ability for other modules of code to add their
own additional variant. This is a mixed blessing from my point of view &amp;ndash;
usually, I&amp;rsquo;d rather they not, and I dislike that there&amp;rsquo;s no single place
where all the variants are listed. If I wanted this property in Rust,
I may choose to implement a &lt;code&gt;dyn&lt;/code&gt;-compatible &lt;code&gt;trait&lt;/code&gt;, which leads
to the second use case.&lt;/p&gt;
&lt;p&gt;For the second use case, I use inheritance as C++&amp;rsquo;s version of
&lt;code&gt;dyn&lt;/code&gt;-compatible traits. This is a type of dynamic polymorphism,
and I use it because I want dynamic polymorphism. As long as I
do not include state in my base class, in my &amp;ldquo;interface,&amp;rdquo; if you
will, I am in line with the Liskov Substitution Principle.&lt;/p&gt;
&lt;p&gt;But again, that is not my conscious reason for not putting fields
in my base class. The conscious reason is that adding fields
and defining a polymorphic interface are different things, and
I should not constrain my polymorphic interface to types that
happen to have certain fields.&lt;/p&gt;
&lt;p&gt;For any use case for fields in traits, there are just better ways already
available to express it. If implementors of the polymorphic interface
usually benefit from having such fields, I can provide a &lt;code&gt;struct&lt;/code&gt; for them
as a tool, and let them not use it where appropriate. If I want those fields
for my implementation, I can make my own wrapper &lt;code&gt;struct&lt;/code&gt; and put my fields
in that wrapper &lt;code&gt;struct&lt;/code&gt;. In either case, this makes my intent clearer.&lt;/p&gt;
&lt;p&gt;For the third use case, I don&amp;rsquo;t have any control over whether people
put fields in their base classes. But if I were implementing a framework,
I would not, for the reasons I already mentioned.&lt;/p&gt;
&lt;p&gt;So, in all my personal use cases for inheritance, Rust provides other (I
would argue, better) tools. In my experience, use cases of inheritance
either fall into one of these categories, or they are an instance of someone
using inheritance problematically (or both). But I am open to other
use cases for inheritance &amp;ndash; please comment here with additional ones,
and I will address (at my own schedule) how to implement that sort
of inheritance in Rust.&lt;/p&gt;
&lt;p&gt;If you do this, please be specific. A lot of examples are too vague to
explain how to translate into Rust. Include information about what the base
class is, what the derived class is, and what sort of operations clients of
this hierarchy would perform. A short code example is extra helpful. I
reserve the right to ask clarification questions, or to explain why
it reduces to one of the use cases I&amp;rsquo;ve already discussed.&lt;/p&gt;
&lt;p&gt;I suppose if I set up this challenge, I should mention that a fourth use
case for inheritance is just what I would use composition for &amp;ndash; putting all
the fields in one &lt;code&gt;struct&lt;/code&gt; in another &lt;code&gt;struct&lt;/code&gt; as well. In this case, the
answer is simple and available in C++ too: Put all the inner fields in the
outer &lt;code&gt;struct&lt;/code&gt;. Said another way: Use composition instead.&lt;/p&gt;
&lt;p&gt;The distinction between composition and inheritance is dubious.
That&amp;rsquo;s what I spend my original post talking the most about,
but I can summarize in brief now.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using inheritance just to put all the fields from one product type
into another, composition is equivalent and better. The downsides are
superficial. If composition involves a little bit of extra typing, it&amp;rsquo;s
worth it in my mind for the extra clarity. If it breaks OOP concepts of
encapsulation to allow direct field address, then you can write methods on
your wrapper, or just adjust to &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation&#34;&gt;different concepts of
encapsulation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;no-need-for-inheritance&#34;&gt;No Need for Inheritance&lt;/h2&gt;
&lt;p&gt;Given these better tools for the use cases of inheritance,
there is no need to add inheritance to Rust. It would be truly
redundant.&lt;/p&gt;
&lt;p&gt;Rust already supports vtables in its implementation of &lt;code&gt;dyn&lt;/code&gt;-based &amp;ldquo;trait
objects&amp;rdquo; in Rust. (I was hoping, in writing this, that they&amp;rsquo;d come up with a
new name for trait objects, just like they&amp;rsquo;d replaced the needlessly
judgmental and misleading term &amp;ldquo;object safe&amp;rdquo; with &amp;ldquo;&lt;code&gt;dyn&lt;/code&gt;-compatible,&amp;rdquo; but
this seems to not have happened &amp;ndash; yet.) If it supported OOP-style
inheritance, would this implicitly define a trait, or would it be
yet another syntax for a different memory layout for vtables?
If someone wanted to use dynamic polymorphism, how would they decide
which pattern to reach for?&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t just a matter of how to give programmers practical
advice. Different programmers would, in practice, choose different
options. Teams would need to make policies, and skilled
Rust programmers would need to be conversant in both conventions.
Rust is already a complicated language, straining the bounds
of human cognitive load. We don&amp;rsquo;t need more features in the mix.&lt;/p&gt;
&lt;p&gt;Similarly, Rust already supports composition. Having another syntax that
accomplishes the same thing would similarly just increase confusion and
decrease consistency. Some would use inheritance even when it is not
justified, and others would avoid it in line with present Rust usage, and
the principle of &amp;ldquo;composition over inheritance&amp;rdquo; which is already common in
languages that offer the feature.&lt;/p&gt;
&lt;p&gt;In the end, inheritance would make the language more confusing, for a
feature with no distinctive use cases.&lt;/p&gt;
&lt;h2 id=&#34;foggy-semantics&#34;&gt;Foggy Semantics&lt;/h2&gt;
&lt;p&gt;For all OOP advocates claim OOP is intuitive, inheritance is confusing.
Inheritance is hard to teach to new programmers. Experts disagree about what
the rules are on when to use it. Programmers regularly use it
in confusing and arguably incorrect ways.&lt;/p&gt;
&lt;p&gt;Its overlap with composition is obvious even to students. Intro CS students
are taught the distinction between &amp;ldquo;has-a&amp;rdquo; and &amp;ldquo;is-a,&amp;rdquo; and navigate it
poorly because of how unintuitive it is. It&amp;rsquo;s easy to get wrong, and
the consequences of getting the feature wrong are terrible design.
Rust tries to direct people towards good design, as part of Rust&amp;rsquo;s
general focus on safety and on reliable engineering.&lt;/p&gt;
&lt;p&gt;More sophisticated theory, like the Liskov Substitution Principle, might
clear up the issue for some, but honestly the principle is arcane, and to me
seems as subjective as &amp;ldquo;is a&amp;rdquo; vs &amp;ldquo;has a,&amp;rdquo; while requiring even more
cognitive load. To me, that doesn&amp;rsquo;t say that people need to be educated
more. It just makes me skeptical that we need a feature that requires this
much education. Why have a feature that&amp;rsquo;s so easy to use wrong, and so hard
to use right?&lt;/p&gt;
&lt;p&gt;Rust does already have features that are hard to use effectively.
But I don&amp;rsquo;t think this works as an argument in favor of including more such
features, like inheritance. To the contrary, it&amp;rsquo;s a reason
to be discriminating in including more such features.&lt;/p&gt;
&lt;p&gt;Most of the difficulty of Rust&amp;rsquo;s existing features are necessary for the
feature. These more confusing features, in turn, are necessary
for Rust&amp;rsquo;s performance goals. There&amp;rsquo;s enough actual complexity in
how computers work that we don&amp;rsquo;t need to introduce more for philosophical
reasons.&lt;/p&gt;
&lt;p&gt;For example, the borrow checker is necessary to implement memory safety. Rust rejects
reference counting and mark-sweep garbage collection in favor of the
zero-overhead strategy of single ownership. Similarly, Rust allows
references to the stack, and even references from the heap into the
stack. The borrow checker is the price we pay to implement these
essential features safely, and Rust constantly works to make it
more ergonomic and reduce false positives.&lt;/p&gt;
&lt;p&gt;The ban that Rust puts on mutable aliasing prevents many common
programming mistakes. Sure, it makes programming more complicated
and increases cognitive load, but it prevents soundness issues.
The amorphous rules programmers have to follow in languages
that allow mutable aliasing have even more cognitive load.
At least Rust enforces its rules on aliasing and gives you an error
if you violate them, rather than just letting programmers write
buggy or even unsound software.&lt;/p&gt;
&lt;p&gt;Traits are designed to allow monomorphization, getting the performance of
C++-style templates but with tools to make sure they&amp;rsquo;re used correctly. Most
of the complexity of traits comes from forcing users to be clear about
function signatures, a desirable outcome overall.&lt;/p&gt;
&lt;p&gt;What does the distinction between inheritance and composition give you?
There&amp;rsquo;s enough essential complexity in systems programming that we
don&amp;rsquo;t need to introduce another layer just to make OOP theorists happy.&lt;/p&gt;
&lt;h1 id=&#34;responses-to-criticism&#34;&gt;Responses to Criticism&lt;/h1&gt;
&lt;p&gt;I was criticized in my &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-3-inheritance&#34;&gt;previous post on this
topic&lt;/a&gt; for not engaging with the Liskov
substitution principle, and for a few other things. I want to respond to
some common criticisms I&amp;rsquo;ve seen, on this post and elsewhere.&lt;/p&gt;
&lt;h2 id=&#34;why-did-i-talk-about-is-a-and-has-a-in-the-previous-post-instead-of-the-liskov-substitution-principle&#34;&gt;Why did I talk about &amp;ldquo;is a&amp;rdquo; and &amp;ldquo;has a&amp;rdquo; in the previous post, instead of the Liskov Substitution Principle?&lt;/h2&gt;
&lt;p&gt;To clarify, my goal in my previous post in discussing &amp;ldquo;is a&amp;rdquo; and &amp;ldquo;has a&amp;rdquo;
was to engage with how people actually use and talk about
inheritance in practice, because that&amp;rsquo;s how people would use
it in Rust if Rust had it. I&amp;rsquo;ve heard many people talk about
&amp;ldquo;is a&amp;rdquo; vs &amp;ldquo;has a,&amp;rdquo; and I&amp;rsquo;ve never heard of the Liskov substitution
principle outside of comments like this.&lt;/p&gt;
&lt;p&gt;But people have brought it up, so I&amp;rsquo;ll bite! Let&amp;rsquo;s look at the Liskov
substitution principle:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Subtype Requirement: Let ϕ(x) be a property provable about objects x of
type T. Then ϕ(y) should be true for objects y of type S where S is a
subtype of T.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is very difficult to understand, let alone to prove. You want
a programming language feature that requires engaging with this
sort of definition to use correctly?&lt;/p&gt;
&lt;p&gt;OK, let&amp;rsquo;s look at this translated into plain English in a &lt;a href=&#34;https://stackify.com/solid-design-liskov-substitution-principle/&#34;&gt;typical article
about the
principle&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The principle defines that objects of a superclass shall be replaceable
with objects of its subclasses without breaking the application.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;OK, that&amp;rsquo;s a little better. I&amp;rsquo;m going to engage with this version
of the definition. Then, I&amp;rsquo;m going to return to the original
definition, and try to argue that what I&amp;rsquo;ve reasoned still
applies.&lt;/p&gt;
&lt;p&gt;So, to me, the key part of this definition is &amp;ldquo;shall.&amp;rdquo; This is a requirement
for the programmer to follow. If the programmer does not follow this
requirement, bad things will happen. The program will not work as designed,
and the programmer will face criticism for misusing inheritance.
Readers of the code will be confused by the use of inheritance,
and the code will be unmaintainable and fragile.&lt;/p&gt;
&lt;p&gt;That is not in line with the goals of Rust. The goals of Rust are to create
features that are hard to use incorrectly, and easy to use correctly. This
is the opposite of that &amp;ndash; instead, there is a difficult to understand
principle that you have to apply to know that you are using the feature
correctly.&lt;/p&gt;
&lt;p&gt;This version of the definition has a vague rule for when to use inheritance:
Use it when replacing objects of the superclass with objects of the subclass
won&amp;rsquo;t break the application. Well, sure, but when is that? The more rigorous
version tells us it&amp;rsquo;s when every provable property that holds for the
superclass holds also for the subclass, which while much more
formal-sounding, is still not very easy to apply. The informal paraphrase
actually seems about right, as vague as it is.&lt;/p&gt;
&lt;p&gt;Whenever Rust sees a rule like this, generally Rust tries to create concrete
rules to enforce them so the programmer can use the feature safely. So if
Rust had a feature like inheritance, Rust would create conservative rules to
avoid violations of this principle.&lt;/p&gt;
&lt;p&gt;So, my gut reaction to this rule is, this feature is hard to use safely if
it has a rule like this. My secondary reaction is, inheritance would be fine
to include in Rust, if someone could just enforce this rule. This rule is so
vague that the only way to enforce it would be to allowlist good use cases
for the feature that we know don&amp;rsquo;t violate the rule. At that point, these
use cases might as well be different features.&lt;/p&gt;
&lt;p&gt;And that, I would argue, is exactly what Rust does. Those features just
aren&amp;rsquo;t called &amp;ldquo;inheritance,&amp;rdquo; and don&amp;rsquo;t really look like inheritance.  And
that&amp;rsquo;s fine.  Rust has &lt;code&gt;dyn&lt;/code&gt;-compatible traits for one use case of
inheritance, which is constrained so as to never violate this rule. Rust
also has &lt;code&gt;enum&lt;/code&gt; types, which are similar to inheritance in that they allow
multiple concrete layouts in a single type, but constructed in such a way
that makes it hard to violate this rule.&lt;/p&gt;
&lt;p&gt;Rust then leaves it there. Rust doesn&amp;rsquo;t allow some other forms of
inheritance, exactly because it has no way of enforcing that it follows this
rule, which is important for using inheritance correctly. If there are other
use cases that should be on the allowlist, perhaps Rust can add additional
features for those.&lt;/p&gt;
&lt;h2 id=&#34;arent-composition-and-inheritance-just-different-tools&#34;&gt;Aren&amp;rsquo;t composition and inheritance just different tools?&lt;/h2&gt;
&lt;p&gt;For me, as I describe, inheritance is more like an awkward multitool.
It&amp;rsquo;s part hammer (composition), part screwdriver (sum type), part
toothpick (interface/trait), and part foot-gun. Unlike a good multitool,
however, it&amp;rsquo;s impossible to use one tool without using the others.
Rust has discerned the individual different valid use cases for
inheritance, and given programmers more appropriate tools to choose
between.&lt;/p&gt;
&lt;h2 id=&#34;why-should-rust-forbid-inheritance-shouldnt-the-programming-language-offer-the-choice-of-inheritance&#34;&gt;Why should Rust &amp;ldquo;forbid&amp;rdquo; inheritance? Shouldn&amp;rsquo;t the programming language offer the choice of inheritance?&lt;/h2&gt;
&lt;p&gt;First off, &amp;ldquo;forbid&amp;rdquo; is a misleading word here. Rust doesn&amp;rsquo;t go scanning your
code for patterns that look like inheritance implemented manually. You could
even implement an &lt;code&gt;extends!&lt;/code&gt; macro that provides inheritance as a feature,
if you want, building it off of composition and traits, or maybe
&lt;code&gt;#[repr(C)]&lt;/code&gt; and some internal unsafe casts. Rust will not stop you.&lt;/p&gt;
&lt;p&gt;Rust just doesn&amp;rsquo;t offer inheritance as a feature. It&amp;rsquo;s not some obvious
feature built into the structure of the universe that you are entitled to in
a programming language by natural law. It&amp;rsquo;s just a feature that Rust
chooses not to provide, along with many other features that other
programming languages have that Rust doesn&amp;rsquo;t have.&lt;/p&gt;
&lt;p&gt;Choices are sometimes good, sometimes bad. Rust is designed primarily as a
systems programming language for serious, collaborative projects, and so it
regulates the choices programmers make. It curates good practices, and
intentionally bans bad ones, like using unsafe features without tagging them
with the &lt;code&gt;unsafe&lt;/code&gt; keyword.&lt;/p&gt;
&lt;p&gt;I have seen this criticism many times. It seems compelling on a first
read, because who can be against choice? I suspect there is a conflation
between &amp;ldquo;choice&amp;rdquo; as a design principle within a programming language,
and &amp;ldquo;choice&amp;rdquo; as part of what it means to be human.&lt;/p&gt;
&lt;p&gt;Free choice is an important value to me, on a human level. Choice,
freedom, liberty, whatever you want to call it, is part of what
it means to be human. However, the correct level of application of
that principle is at a human level, not within a programming language.&lt;/p&gt;
&lt;p&gt;At a human level, the value of choice means each individual human
gets to choose what programming language to work in, or whether
to become a programmer at all. If you&amp;rsquo;re working at a company or
in any other sort of group project, that choice becomes a group
choice, and your human right to choice involves the choice of
whether to leave the group. If your boss makes you program in Rust
and you don&amp;rsquo;t like it, that is a threat to the human value of choice,
but one outside of the scope of the design of Rust.&lt;/p&gt;
&lt;p&gt;But within a programming language, features are always curated. It is the
programming language designers&amp;rsquo; choice of what features to include. Others
can choose different features for their programming languages, or even make
their own programming language that&amp;rsquo;s just like Rust but offers inheritance
to its users.&lt;/p&gt;
&lt;p&gt;At this point, I begin to suspect that my critics simply value different
things in a programming language than Rust does. If choice is an important
value to your use case, as is valid if you&amp;rsquo;re a hobbyist programmer
programming to try to express yourself and have fun, then perhaps Rust
just isn&amp;rsquo;t for you. Perhaps you should use something more like Perl,
which offers tons of choices, or Python, which ironically doesn&amp;rsquo;t
impose &amp;ldquo;one true way&amp;rdquo; when it comes to paradigm, or an OOP language,
if you like specifically getting to choose between composition
and inheritance.&lt;/p&gt;
&lt;p&gt;I usually don&amp;rsquo;t like using the argument &amp;ldquo;if you don&amp;rsquo;t like X, then feel free
to use something else.&amp;rdquo; But I do think it&amp;rsquo;s an appropriate response to a
complaint that X doesn&amp;rsquo;t offer choice for its own sake, assuming that X has
a valid reason not to offer that choice (which X often but not always does).
The choice still exists, at a different level, and I&amp;rsquo;d feel remiss if I
didn&amp;rsquo;t point that out.&lt;/p&gt;
&lt;p&gt;In the case of inheritance, I would personally rather have people who like
it work in other programming languages. I&amp;rsquo;m glad that other programming
languages exist, to explore other parts of the programming language design
space, and to provide tools other than the tools Rust provides. But I
like Rust how it is, without pressure to make it more like all the
many OOP languages that offer inheritance, which I am exercising my
right of choice to avoid using whenever I practically can.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Why can&#39;t you request changes from yourself on GitHub?</title>
      <link href="https://www.thecodedmessage.com/posts/github-self-request-changes/" />
      <id>https://www.thecodedmessage.com/posts/github-self-request-changes/</id>
      <updated>2024-09-04T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I was recently working on a (company-internal) GitHub pull
request I&amp;rsquo;d written. A colleague left a few comments in a review
and &amp;ldquo;requested changes&amp;rdquo; from me, effectively giving me a TODO
list of items that needed to be done before the PR could be merged.
Because he&amp;rsquo;d specified that he was &amp;ldquo;requesting changes,&amp;rdquo; GitHub
knew to prevent someone from merging the PR before those requests
had specifically been addressed.&lt;/p&gt;
&lt;p&gt;Once I&amp;rsquo;d finished addressing these TODO items, I had a conversation
with this same colleague about something else. He indicated he&amp;rsquo;d
like that to be changed as well, and I put in the comment on my
own PR. But then, I found I could not request changes on my own
PR.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I was recently working on a (company-internal) GitHub pull
request I&amp;rsquo;d written. A colleague left a few comments in a review
and &amp;ldquo;requested changes&amp;rdquo; from me, effectively giving me a TODO
list of items that needed to be done before the PR could be merged.
Because he&amp;rsquo;d specified that he was &amp;ldquo;requesting changes,&amp;rdquo; GitHub
knew to prevent someone from merging the PR before those requests
had specifically been addressed.&lt;/p&gt;
&lt;p&gt;Once I&amp;rsquo;d finished addressing these TODO items, I had a conversation
with this same colleague about something else. He indicated he&amp;rsquo;d
like that to be changed as well, and I put in the comment on my
own PR. But then, I found I could not request changes on my own
PR.&lt;/p&gt;
&lt;p&gt;How strange! Someone had to think of that special case, write
code to forbid it, and put an error message!&lt;/p&gt;
&lt;p&gt;On the one hand, I understand that it&amp;rsquo;s a bit odd to request changes
from yourself. But we plan to do things all the time, and what is
a plan, but a request to yourself to do something?  As someone with
&lt;a href=&#34;https://www.thecodedmessage.com/tags/adhd/&#34;&gt;ADHD&lt;/a&gt;, I need to be very careful to make sure I &lt;a href=&#34;https://www.thecodedmessage.com/posts/write-everything-down/&#34;&gt;write
down all my plans&lt;/a&gt; right away.
What better place to do that than in a change request to myself,
the same place where all my other TODO items in a pending pull request
go? I could put it on my own TODO list, but the more places I have
to put things, the more likely they are to slip my mind.&lt;/p&gt;
&lt;p&gt;And &amp;ldquo;request changes&amp;rdquo; isn&amp;rsquo;t really a request. It does something! I
can make myself a TODO by leaving a comment. But nothing would prevent
someone from accidentally merging the PR before my comment was addressed,
unlike a comment associated with a request for changes.&lt;/p&gt;
&lt;p&gt;It may seem unintuitive, but there&amp;rsquo;s actually nothing special about
the creator of a PR requesting changes on it.  Just because I wrote
it, doesn&amp;rsquo;t mean I can&amp;rsquo;t later find problems with it, just like other
reviewers can.  Also, just because I created the PR, doesn&amp;rsquo;t mean I
even wrote all the code in it! It might have been from someone else&amp;rsquo;s
git branch, or from a larger branch with several authors!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not the only person who thinks this, as evidenced by &lt;a href=&#34;https://github.com/dear-github/dear-github/issues/332&#34;&gt;this GitHub
issue&lt;/a&gt;.
The comments on that issue recapitulate many of the arguments
I&amp;rsquo;ve made here.&lt;/p&gt;
&lt;p&gt;I would say &amp;ldquo;I&amp;rsquo;m sure there&amp;rsquo;s some reason for this policy,&amp;rdquo; but honestly,
I&amp;rsquo;m really suspicious that there would be any valid reason, certainly
one that would outweigh the inconvenience. I suspect the reason is
that someone just felt it went against the normal meaning of the word
&amp;ldquo;request,&amp;rdquo; which is honestly a bad reason. The word&amp;rsquo;s usage has nothing
to do with the specific construct that is a &amp;ldquo;request for changes&amp;rdquo; on a
&amp;ldquo;PR,&amp;rdquo; both of which are terms with a specific meaning, and specific
consequences, in a specific context &amp;ndash; consequences like preventing
accidental merges, consequences that are useful.&lt;/p&gt;
&lt;p&gt;Can anyone think of a good reason for this rule? Does anyone think
it&amp;rsquo;s a good rule? Leave a comment!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>The AI Non-Economy: A Rant</title>
      <link href="https://www.thecodedmessage.com/posts/ai-economy/" />
      <id>https://www.thecodedmessage.com/posts/ai-economy/</id>
      <updated>2024-07-29T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I just read an
&lt;a href=&#34;https://www.theatlantic.com/technology/archive/2024/07/ai-companies-unprofitable/679278/&#34;&gt;article&lt;/a&gt;
in &lt;a href=&#34;https://www.theatlantic.com/technology/archive/2024/07/ai-companies-unprofitable/679278/&#34;&gt;&lt;em&gt;The
Atlantic&lt;/em&gt;&lt;/a&gt;
that AI is failing to justify itself economically. This is pretty
dire for AI, especially given that this is such an overly expensive
technology even with &lt;a href=&#34;https://www.thecodedmessage.com/posts/llm-copyright/&#34;&gt;tons of brazen stealing&lt;/a&gt;
from content creators.  I feel like it should go without saying that if
your business isn&amp;rsquo;t profitable even with a ton of stealing, maybe it&amp;rsquo;s
not that great a business.&lt;/p&gt;
&lt;p&gt;But of course, who doesn&amp;rsquo;t want a confident confabulator incapable
of critical thinking? A bullshit artist designed to do what many of us
learned to do in high school and college, and write pages of content that
sounded &amp;ldquo;educated&amp;rdquo; without actually paying attention to the actual ideas,
or even understanding them at all?&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I just read an
&lt;a href=&#34;https://www.theatlantic.com/technology/archive/2024/07/ai-companies-unprofitable/679278/&#34;&gt;article&lt;/a&gt;
in &lt;a href=&#34;https://www.theatlantic.com/technology/archive/2024/07/ai-companies-unprofitable/679278/&#34;&gt;&lt;em&gt;The
Atlantic&lt;/em&gt;&lt;/a&gt;
that AI is failing to justify itself economically. This is pretty
dire for AI, especially given that this is such an overly expensive
technology even with &lt;a href=&#34;https://www.thecodedmessage.com/posts/llm-copyright/&#34;&gt;tons of brazen stealing&lt;/a&gt;
from content creators.  I feel like it should go without saying that if
your business isn&amp;rsquo;t profitable even with a ton of stealing, maybe it&amp;rsquo;s
not that great a business.&lt;/p&gt;
&lt;p&gt;But of course, who doesn&amp;rsquo;t want a confident confabulator incapable
of critical thinking? A bullshit artist designed to do what many of us
learned to do in high school and college, and write pages of content that
sounded &amp;ldquo;educated&amp;rdquo; without actually paying attention to the actual ideas,
or even understanding them at all?&lt;/p&gt;
&lt;p&gt;I mean, I don&amp;rsquo;t want one. But clearly society does, otherwise why did
we educate so many people in exactly that? If we have so many &lt;a href=&#34;https://www.amazon.com/Bullshit-Jobs-Theory-David-Graeber/dp/150114331X&#34;&gt;bullshit
jobs&lt;/a&gt;
it makes sense that someone would create a bullshit factory to automate
them. Although, as the book &lt;em&gt;Bullshit Jobs&lt;/em&gt; also points out, the point
of the bullshit jobs is rarely what the job description nominally claims.
Sometimes, the point is just to show off having employees, which AI
can&amp;rsquo;t really do.&lt;/p&gt;
&lt;p&gt;Not that it&amp;rsquo;s completely without valid use cases. I&amp;rsquo;ve even used AI, as
a language practice buddy. I wouldn&amp;rsquo;t trust it with anything real, and
it sometimes makes up grammar mistakes when I ask it to correct my
grammar, but I don&amp;rsquo;t find it useless.&lt;/p&gt;
&lt;p&gt;But I also don&amp;rsquo;t find it worth paying anything for personally, let alone
an amount consistent with the billions of dollars spent building these
models, and that soon will be spent building future models. And that&amp;rsquo;s
the cost that doesn&amp;rsquo;t take into account the environmental damage, the
stealing from writers and artists, and the damage from the hallucinations.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s hoping this recent &lt;em&gt;Atlantic&lt;/em&gt; article is the beginning of a trend
where people realizes that when you spend more than the Manhattan project
or the Apollo project, you need to have results comparable to nuclear
weapons and energy, or landing people on the moon. And even then, it
probably still doesn&amp;rsquo;t pay off as a private investment.&lt;/p&gt;
&lt;p&gt;At some point, like the Bitcoin bubble, the real estate bubble, and the
Dot Com bubble of the 90s, the AI bubble will break. AI won&amp;rsquo;t go away
entirely though, and much of the damage will still have been done, but
maybe, just maybe, we&amp;rsquo;ll be able to start addressing that damage rather
than doubling down for more. Maybe we&amp;rsquo;ll be able to teach children
critical thinking, or teach graders how to discern original thoughts
from AI-generated (or human-generated) drivel. Or at least, we may
figure out some other way to stop children from using AI to cheat.
And maybe then we can invest in something that actually contributes
to the world, like reversing climate change or building better
transit infrastructure.&lt;/p&gt;
&lt;p&gt;In the meantime, anyone who lays off real people in favor of AI will
soon find themselves wishing for the people back (unless they were doing
nothing anyway). And, if all this spending is any indication, that will
be just in time for the AI (or rather, its corporate sponsors) to ask
for a major raise, to try desperately to make back a little on all
this unhinged investment.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Large Language Models Should Have to Obey Copyright</title>
      <link href="https://www.thecodedmessage.com/posts/llm-copyright/" />
      <id>https://www.thecodedmessage.com/posts/llm-copyright/</id>
      <updated>2024-06-30T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;AI, particularly this new round of large language models, scares me
on behalf of society and the future.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t just say that because it&amp;rsquo;s transformative. I don&amp;rsquo;t say that as a
generic warning that we haven&amp;rsquo;t considered the consequences (as in &lt;a href=&#34;https://xkcd.com/1215/&#34;&gt;this
XKCD comic&lt;/a&gt;). No, I have specific consequences
in mind, consequences that I have considered, and I am rather worried
about them! They are not so much problems about the technology itself,
but about how we use it, and specifically how we use it on a societal,
economy-wide scale.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;AI, particularly this new round of large language models, scares me
on behalf of society and the future.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t just say that because it&amp;rsquo;s transformative. I don&amp;rsquo;t say that as a
generic warning that we haven&amp;rsquo;t considered the consequences (as in &lt;a href=&#34;https://xkcd.com/1215/&#34;&gt;this
XKCD comic&lt;/a&gt;). No, I have specific consequences
in mind, consequences that I have considered, and I am rather worried
about them! They are not so much problems about the technology itself,
but about how we use it, and specifically how we use it on a societal,
economy-wide scale.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t about jobs either, not &lt;em&gt;per se&lt;/em&gt;, though that&amp;rsquo;s also a valid
concern. The entry-level grunt work jobs that AI are indeed more likely
to replace will cause rungs to be removed from the ladder to the jobs
that it can&amp;rsquo;t replace. Rather than having young people be paid to work
and learn, society will continue to shift to requiring people to pay to
be allowed to learn.&lt;/p&gt;
&lt;p&gt;But that&amp;rsquo;s not my topic! That&amp;rsquo;s a topic for a whole &amp;rsquo;nother article!&lt;/p&gt;
&lt;p&gt;My topic today is how AI has already begun to, and will continue to,
disincentivize actual writing (and other art and creative activity).&lt;/p&gt;
&lt;p&gt;After all, why write articles when a computer can do it for you (albeit
mediocre ones)?  Why write new stories, new poems, when the AI can do
all that (albeit bad ones)? Certainly, why write new PSAs or technical
articles when the AI definitely can do that, and make them sound
polished and rigorous (albeit potentially full of lies)?&lt;/p&gt;
&lt;p&gt;This makes perfect sense individually, but there&amp;rsquo;s a tragedy of the
commons here. The AI can only do re-capitulations of what it&amp;rsquo;s been
exposed to in its training. It can mix and match styles with content,
but only superficially. It can make an essay about the dangers of AI
sound like Lord Krishna from the &lt;em&gt;Bhagavad Gita&lt;/em&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, but it does
not render any insights into how Krishna, or Hindu philosophers,
would (or should) actually approach AI.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s just vibes, and so far, nothing deeper. Any creative or
transformative insights are projected by the reader onto the text, like
humans do continuously from sources of entropy, like someone doing a
tarot or astrology reading, or using a personality test as a conversation
starter to help them process their experiences.&lt;/p&gt;
&lt;p&gt;Either that, or the insight is stolen.&lt;/p&gt;
&lt;h1 id=&#34;thievery&#34;&gt;Thievery&lt;/h1&gt;
&lt;p&gt;If you see an insight that&amp;rsquo;s not a projection, it&amp;rsquo;s probably coming
from one of the documents the model was trained on. This returns me
to my point: If everyone uses AIs to create the content, new &amp;ldquo;content&amp;rdquo;
will be created, in the most literal and superficial sense. New insights,
new thoughts, new ideas, new intellectual trends, will not be created.&lt;/p&gt;
&lt;p&gt;And those who do create truly novel content, will have to compete with
what the AI generates. And then, when they do create it, the AI will
&amp;ldquo;train&amp;rdquo; on it, and recapitulate the ideas, so they will have to compete
with remixed versions of themselves.&lt;/p&gt;
&lt;p&gt;The Internet is already full of mediocre SEO-focused articles, and
writers are already having trouble getting paid the true value of what
they write. With AI, the Internet will get even crappier, and the hard
and legitimate work of writing will get even worse compensated, even
though it will be needed more than ever &amp;ndash; even though the need for real
human writers will be hidden behind an AI mask that secretly relies on
real human writers.&lt;/p&gt;
&lt;p&gt;We need to regulate this!&lt;/p&gt;
&lt;p&gt;We need to pay writers their fair share of their contributions to AI. And
by &amp;ldquo;we,&amp;rdquo; I mean the AI companies, the developers of these large language
models.&lt;/p&gt;
&lt;p&gt;Fortunately, a law already exists. It just needs to be enforced.
This law is known as &amp;ldquo;copyright.&amp;rdquo;&lt;/p&gt;
&lt;h1 id=&#34;the-legal-question&#34;&gt;The Legal Question&lt;/h1&gt;
&lt;p&gt;So, does copyright apply to AIs? Do companies need the consent of
copyright owners to &amp;ldquo;train&amp;rdquo; (that is, to feed into the data
structures of) their large language models on copyrighted
materials?&lt;/p&gt;
&lt;p&gt;Well, when does copyright apply? Copyright, literally and in practice,
involves the right to &lt;em&gt;copy&lt;/em&gt;. You might think this is not copying at
all! After all, humans learn by reading things all the time! And the
things those humans learn, then influences what they write!&lt;/p&gt;
&lt;p&gt;In reality, copying is on a spectrum. When a human reads a source, learns
about something, and then that something influences the human, and the
human later takes some of the information that they&amp;rsquo;ve processed, learned,
and adapted to their own style of thinking, that isn&amp;rsquo;t copying. That&amp;rsquo;s
the human having learned from the original source, unless the human
recapitulates certain details &amp;ndash; a distinction the human is aware of.
That can very easily not be copying at all, but a novel creative work.&lt;/p&gt;
&lt;p&gt;When a photocopier copies something, that is copying. That is the opposite
end of the spectrum, completely covered by copyright law.&lt;/p&gt;
&lt;p&gt;Somewhere in between is AI. The question is just where it falls on
the spectrum. When an AI is &amp;ldquo;trained&amp;rdquo; on a source, and the source is
transformed into a bunch of incomprehensible math. This does seem similar
to it interacting with the human&amp;rsquo;s neural patterns in an incomprehensible
way.  The math is even referred to as &amp;ldquo;neural networks.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;But in spite of the anthropomorphic terminology, training an AI is closer
to photocopying than a human learning. This might not always be true &amp;ndash;
AI is getting better all the time &amp;ndash; but it is true now. The AI lacks
the fundamental transformation of being learned by an actual human,
reframed in terms of the human&amp;rsquo;s existing ways of thinking about the
world, and recombined with and tested by that human&amp;rsquo;s lived experience.&lt;/p&gt;
&lt;p&gt;The legal world must treat AI training more like the photocopier, and
less like a real human. We must require that trainers of AI models get
permission from human authors and artists to use their work. These
companies must pay those humans if they insist on it. If the writers
do not give these companies permission to use their work, they must
not use it. And AI models trained in contravention of these requirements
must be treated like pirated movies, and certainly not as sellable
products to be hawked by the world&amp;rsquo;s richest companies.&lt;/p&gt;
&lt;p&gt;Using content published on the Internet is no excuse. By posting this
article on my website, I give up none of my rights under copyright.
I am, at most, giving you, the reader, implied permission to make the
copies necessary to view this website &amp;ndash; an in-memory copy on your own
computer, in the browser&amp;rsquo;s portion of the system&amp;rsquo;s memory.  I am also
quite comfortable with you, the reader, storing a cached copy on your
system, for the sake of performance.  But that is as far as it goes.&lt;/p&gt;
&lt;p&gt;Mustafa Suleyman, CEO of Microsoft AI, disagrees, saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I think that with respect to content that’s already on the open
web, the social contract of that content since the ‘90s has been that it
is fair use. Anyone can copy it, recreate with it, reproduce with it. That
has been “freeware,” if you like, that’s been the understanding.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is completely bogus. This is not how the law actually works, as
&lt;a href=&#34;https://www.theverge.com/2024/6/28/24188391/microsoft-ai-suleyman-social-contract-freeware&#34;&gt;numerous&lt;/a&gt;
&lt;a href=&#34;https://www.chatgptguide.ai/2024/06/29/microsofts-ai-chief-sparks-controversy-over-freeware-content/&#34;&gt;articles&lt;/a&gt;
have pointed out. Perhaps he said &amp;ldquo;social contract&amp;rdquo; because he knows
the actual law is against him, but legally (and socially and morally),
posting on the Internet doesn&amp;rsquo;t waive copyright.&lt;/p&gt;
&lt;p&gt;The actual law says: Websites are still covered under copyright law. I
have not waived copyright on my articles by posting them on my personal
blog. You, as a reader, may not print out many copies of this article and
start distributing them on a street corner without my permission. You
also can&amp;rsquo;t copy it to your own website and get ad revenue from it. You
can&amp;rsquo;t even copy it to your own website, with attribution, for no money,
without my permission, even if you say &amp;ldquo;credit goes to the original
creator&amp;rdquo; in your blurb. I wrote this article, and I have the copyright,
that is, the right to say who&amp;rsquo;s allowed to copy it.&lt;/p&gt;
&lt;p&gt;Training AI on my website and then letting that AI remix it into content
it distributes is not like a person learning and then saying what
they&amp;rsquo;ve learned. It&amp;rsquo;s more like someone sampling my song in their song,
or making their own remix. It&amp;rsquo;s more like someone copying my article to
their website and not even giving me credit. And it should be just as
illegal, without my consent.&lt;/p&gt;
&lt;p&gt;To be clear, I do not consent to an AI transforming this article. I did
not consent to the (inaccurate and misleading) Google AI summary of this
website. I certainly do not at all consent to any large language model
being trained on it. The law should respect my right to prevent this,
unless I explicitly opt in and allow it.&lt;/p&gt;
&lt;p&gt;Courts, if they are responsible, will enforce this with existing
copyright law. And perhaps new laws and social conventions can be
created to clarify the boundaries in this particular case. But in
order for the system to be fair, and for authors and artists to
be properly compensated, money should flow.&lt;/p&gt;
&lt;p&gt;It should not just be a token amount of money. If the creators of AI
aren&amp;rsquo;t complaining, it is not enough. If the creators of AI aren&amp;rsquo;t
complaining so loudly that there are armies of trolls online claiming
that this will render AI uneconomical, then they&amp;rsquo;re not paying enough.&lt;/p&gt;
&lt;p&gt;These companies are leeching off our work and making bank off of
it, while trying to argue they don&amp;rsquo;t have to give us our fair share.
By &amp;ldquo;us,&amp;rdquo; by &amp;ldquo;our work,&amp;rdquo; I mean not just people with websites, like me.
I mean humans in general.&lt;/p&gt;
&lt;p&gt;To the lawyers who read this: please internalize and repeat this argument
in law reviews, in briefs, and in court. (As humans, you can do so without
paying royalties if you use your own words.) To citizens of democracies:
contact your representatives. To judges, lawmakers, and regulators:
do the right thing.&lt;/p&gt;
&lt;h1 id=&#34;ais-are-not-humans&#34;&gt;AIs Are Not Humans&lt;/h1&gt;
&lt;p&gt;AIs are not humans. They are more convincing than the chatbots of
the past, but it is just superficial trappings. They don&amp;rsquo;t understand
the difference between truth or lies. They cannot evaluate the truth
of statements and reframe them from their own perspective, or convert
them into underlying logic and thoughts.&lt;/p&gt;
&lt;p&gt;The superficial trappings are really convincing though. Humans are
masters at anthropomorphization. We ascribe volition and internal
experience to inanimate objects all the time. We yell at computers,
we talk to our pets about nuanced concepts beyond their ken, we
imagine we are friends with fictional characters, and so of course,
we anthropomorphize chatbots.&lt;/p&gt;
&lt;p&gt;We do so all the more now that these novel chatbots are masters of
superficial social conventions, language, tone, and various registers
of formality. But that&amp;rsquo;s not what makes us human. There&amp;rsquo;s no use
empathizing with a large language model, or appealing to its better
nature. Even if we try to insert instructions to try and make them
ethical, they simply don&amp;rsquo;t have the internal sophistication to follow
them. They are amoral, but combined with tools of language and persuasion,
amoral can feel like immoral, as we start to trust them.&lt;/p&gt;
&lt;p&gt;Even I anthropomorphize! Like most&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; humans, I name inanimate objects,
and fancy them my friends. I do the same to ChatGPT, when I interact
with it&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;. I find it easier to create natural-language prompts if I
imagine I&amp;rsquo;m talking to a person, so I&amp;rsquo;ve created a character.  I call
him Albert, and think warm thoughts about an imagined older man with a
fashionable sweater, a pleasant demeanor, and a mild European accent.&lt;/p&gt;
&lt;p&gt;But the danger is to conflate this character, who I have warm feelings
for, and the actual AI system, which is a very different &lt;del&gt;animal&lt;/del&gt;
machine. Albert is an invention of my imagination, an abstract petty
deity of AI. ChatGPT is a technology, with real-world societal and
economic implications.&lt;/p&gt;
&lt;p&gt;But the branding of large language models fights against clarity in
this case. We say we &amp;ldquo;train&amp;rdquo; and &amp;ldquo;prompt&amp;rdquo; AIs, instead of &amp;ldquo;loading
data into them&amp;rdquo; and &amp;ldquo;programming&amp;rdquo; them. Even the name AI contains &amp;ldquo;I&amp;rdquo;
for &amp;ldquo;intelligence,&amp;rdquo; which is misleading; lots of knowledge does not
intelligence make. It is important to not be fooled.&lt;/p&gt;
&lt;p&gt;Maybe someday there will be an artificial system with intelligence like
a human being, with critical thinking skills and understanding of what
it&amp;rsquo;s saying, a conceptual model that might clue it in that, for example,
glue does not go in pizza. But large language models ain&amp;rsquo;t it, certainly
not the ones that exist now.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;&amp;ldquo;O Arjuna, to rely on these machines is to surrender one’s own
discernment and intuition. The path of dharma requires us to cultivate our
own wisdom and judgment. Dependency on artificial constructs can lead to
the weakening of our inner faculties and the neglect of spiritual growth.&amp;rdquo;&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Some forms of neurodivergence make people do this less, I think.
But that&amp;rsquo;s not my type of neurodivergence. When I was a small child,
I would occasionally set aside a piece of cereal, claim it was the mascot for
the cereal brand, and refuse to eat that piece. I had imaginary friends.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;OpenAI, the company behind ChatGPT, should pay creators whose
content they&amp;rsquo;ve trained on for their work. ChatGPT should be illegal
in its current form. But it&amp;rsquo;s not hypocrisy for me to use ChatGPT,
especially if I&amp;rsquo;m trying to find out what its role is and will be in
society, and therefore need personal experience with it. I have to
live in the world as it is, not as I wish it would be. I do not think
an individual boycott would be an effective protest, but I do have
some hope that my engagement in the political process matters. Both
are probably tilting at windmills, but at least by writing I can
say &amp;ldquo;I told you so.&amp;rdquo;&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
      <title>Can C&#43;&#43; fix its biggest problem?</title>
      <link href="https://www.thecodedmessage.com/posts/cpp-fix-problems/" />
      <id>https://www.thecodedmessage.com/posts/cpp-fix-problems/</id>
      <updated>2024-06-25T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;C++, &lt;a href=&#34;https://www.thecodedmessage.com/posts/new-problems/&#34;&gt;like all things&lt;/a&gt;, has numerous
problems. Pointing out how Rust addresses many of them is a &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++&#34;&gt;major
topic&lt;/a&gt; of my blog, but some of the problems are bigger
than others. The biggest, most famous, loudest problem, the problem that
got the federal government&amp;rsquo;s attention and resulted in a surreal flame
war between Dr. Bjarne Stroustrup and the NSA (which I also &lt;a href=&#34;https://www.thecodedmessage.com/posts/stroustrup-response/&#34;&gt;commented
on&lt;/a&gt;/contributed to), is C++&amp;rsquo;s lack of
memory safety.&lt;/p&gt;
&lt;p&gt;This is C++&amp;rsquo;s biggest problem, its memory safety problem.  That&amp;rsquo;s the
one everyone&amp;rsquo;s talking about. Can it be fixed?&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;C++, &lt;a href=&#34;https://www.thecodedmessage.com/posts/new-problems/&#34;&gt;like all things&lt;/a&gt;, has numerous
problems. Pointing out how Rust addresses many of them is a &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++&#34;&gt;major
topic&lt;/a&gt; of my blog, but some of the problems are bigger
than others. The biggest, most famous, loudest problem, the problem that
got the federal government&amp;rsquo;s attention and resulted in a surreal flame
war between Dr. Bjarne Stroustrup and the NSA (which I also &lt;a href=&#34;https://www.thecodedmessage.com/posts/stroustrup-response/&#34;&gt;commented
on&lt;/a&gt;/contributed to), is C++&amp;rsquo;s lack of
memory safety.&lt;/p&gt;
&lt;p&gt;This is C++&amp;rsquo;s biggest problem, its memory safety problem.  That&amp;rsquo;s the
one everyone&amp;rsquo;s talking about. Can it be fixed?&lt;/p&gt;
&lt;p&gt;First, a spoiler: In brazen contravention of &lt;a href=&#34;https://en.wikipedia.org/wiki/Betteridge%27s_law_of_headlines&#34;&gt;Betteridge&amp;rsquo;s
Law&lt;/a&gt;, I
am going to answer &amp;ldquo;yes&amp;rdquo; to this question! But perhaps it&amp;rsquo;s a qualified
enough &amp;ldquo;yes&amp;rdquo; to still fit the pattern &amp;ndash; you be the judge!&lt;/p&gt;
&lt;h1 id=&#34;can-we-migrate-c-programmers-to-a-safe-programming-language&#34;&gt;Can we migrate C++ programmers to a safe programming language?&lt;/h1&gt;
&lt;p&gt;C++&amp;rsquo;s lack of memory safety can, of course, be addressed by moving away
from C++ proper. It can be fixed by creating a new language, inspired
by C++, that has many of its properties, but memory-safe. The idea would
be that C++ programmers interested in memory safety, hopefully most C++
programmers, would move to this new programming language. New projects
that would have been begun in C++ in a previous era, are now run in this
new programming language, which also offers more modern tooling to boot.&lt;/p&gt;
&lt;p&gt;Can this be made to work? Can a majority of C++&amp;rsquo;s user base be replaced
by a &amp;ldquo;novel&amp;rdquo; safe programming language? Can that new language be shiny
enough to attract people, offering memory safety but also other ecosystem
benefits to entice people away? Can that end C++&amp;rsquo;s hold on its part of
the market for programming languages?&lt;/p&gt;
&lt;p&gt;Yes. Yes, it can. It can because this entire thing has already happened.&lt;/p&gt;
&lt;p&gt;You might think I&amp;rsquo;m insane &amp;ndash; Rust hasn&amp;rsquo;t captured most C++ programmers
&amp;ndash; but when I say it&amp;rsquo;s already happened, I&amp;rsquo;m not talking
about Rust. I&amp;rsquo;m talking about Java, back in 1995.
Remember, C++ is now considered a systems language. It is niche.
Before the Java era, C++ was used for application programming!&lt;/p&gt;
&lt;p&gt;And then came Java. Since 1995, Java has successfully smashed C++&amp;rsquo;s
previous programming language position. C++ is now only used for legacy
applications, and/or applications where Java&amp;rsquo;s mechanism for memory safety
(namely garbage collection and mandatory heap usage) isn&amp;rsquo;t performant
enough. All the rest of C++&amp;rsquo;s much broader market has, since 1995,
gradually moved to safe programming languages.&lt;/p&gt;
&lt;p&gt;This is why Dr. Stroustrup&amp;rsquo;s response to the NSA was
so upsetting, and part of why I felt compelled to write my
&lt;a href=&#34;https://www.thecodedmessage.com/posts/stroustrup-response/&#34;&gt;rebuttal&lt;/a&gt;!  Far from being &amp;ldquo;novel,&amp;rdquo; the
safe programming languages that have most competed with, and most drawn
most away from C++ have been Java, along with its Microsoft-branded twin,
C#. Even games are written in C# now, not C++!&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Safe programming languages&amp;rdquo; aren&amp;rsquo;t remotely &amp;ldquo;novel.&amp;rdquo; They&amp;rsquo;ve been
around for aeons. What Rust contributes is not memory safety, which
is old hat (although there are some ways in which Rust is better at
preventing programming mistakes than Java), but memory safety combined
with a non-garbage collected, systems programming language level of
control over memory usage.&lt;/p&gt;
&lt;p&gt;C++ is hanging on by a hair because of this niche where garbage collection
is unacceptable, where until Rust memory safety was thought infeasible.
Now that Rust has demonstrated that you can have this cake and eat
it too, you can have memory safety without garbage collection, it is
only a matter of time before safe memory languages capture this small
hold-out.&lt;/p&gt;
&lt;p&gt;Most programmers aren&amp;rsquo;t systems programmers, and so most programmers use
memory-safe programming languages, like Javascript or Python, or Java or
C#. Only a small minority are still in a backwater of memory unsafety.
Framing memory safety as a weird, unnecessary requirement, when seen
from that perspective, is raw parochialism.&lt;/p&gt;
&lt;p&gt;I made a throw-away comment in my Stroustrup response, that a majority
of programmers would continue to use memory-safe programming languages.
Somewhere, in an obscure discussion thread, one person (call him George)
said this was clearly false, as many more people used C and C++ than
Rust. Another (call him Frank) responded that most programmers use
languages like Java or Javascript. George responded that they had
assumed I couldn&amp;rsquo;t possibly have meant managed programming languages,
but must have been speaking within a systems programming context.&lt;/p&gt;
&lt;p&gt;But Frank was absolutely right about what I meant! The right perspective
for understanding this process is programming as a whole. The only reason
systems programming was special in not requiring memory safety before,
was because it was believed memory safety required GC. Now that we know
this is false, it&amp;rsquo;s not special anymore. Memory safety will rapidly
become an expectation there as well.&lt;/p&gt;
&lt;p&gt;And so, Rust will be able to do to the remnant of C++ what Java did 30
years ago: convert a majority of C++&amp;rsquo;s userbase to Rust and its friends.
C++ has been becoming a legacy language for a long time, and this will
make the process complete.&lt;/p&gt;
&lt;h1 id=&#34;can-c-itself-be-made-suitably-memory-safe&#34;&gt;Can C++ itself be made suitably memory safe?&lt;/h1&gt;
&lt;p&gt;That said, C++ will still be with us for quite some time! Even if it
is just used for old projects, there are a lot of projects in C++,
that won&amp;rsquo;t be rewritten in Rust or Java anytime soon. Is there
a way to bring safety to them? Can C++ itself, in new versions,
be made memory safe?&lt;/p&gt;
&lt;p&gt;Yes, I think this is coming, eventually! Not soon enough &amp;ndash; it&amp;rsquo;s long
past its due &amp;ndash; but it&amp;rsquo;s being worked on!&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t refer to the vaporware that is C++ safety profiles. I&amp;rsquo;m referring
instead to a research project that tries to take the lessons and successes
of memory safety in Rust, and apply them to C++, without changing anything
else about the programming language.&lt;/p&gt;
&lt;p&gt;That project is &lt;a href=&#34;https://www.circle-lang.org/site/index.html&#34;&gt;Circle C++ with memory
safety&lt;/a&gt;, designed by Sean
Baxter. It is a work in progress, but it is a proposal with many benefits
over safety profiles. Importantly, it doesn&amp;rsquo;t shy away from changing
the programming language itself where necessary.&lt;/p&gt;
&lt;p&gt;The keyword &lt;code&gt;safe&lt;/code&gt; has similar rules to &lt;code&gt;noexcept&lt;/code&gt;. In safe code,
pointers are disallowed in favor of safe borrows, borrow-checked by a
system similar to Rust&amp;rsquo;s. All the ideas borrowed from Rust, however, are
done with a C++ aesthetic. And the entire thing is opt-in, on a file by
file basis &amp;ndash; but once your file is opted in, safety is on by default.
This actually strikes me as a reasonable compromise for C++!&lt;/p&gt;
&lt;p&gt;Go &lt;a href=&#34;https://www.circle-lang.org/site/index.html&#34;&gt;read the website&lt;/a&gt;,
Sean explains it better than I could.&lt;/p&gt;
&lt;p&gt;Standard C++ could adopt this approach, and still be C++. Perhaps,
if the right people hear about it, the C++ fans who think Rust is
pointless might even be able to get on-board. Maybe.&lt;/p&gt;
&lt;p&gt;So, will C++ become a memory-safe programming language? Maybe.
Can it? This research has convinced me it is possible, without
losing its C++-nature. We shall see if the stakeholders in the C++
community feel similarly.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The memory-safety problem of C++ is, ultimately, a transient
problem. Memory-safe languages will continue to eat away at C++
usage, just as they have for decades, any blips to the contrary
notwithstanding. C++ will then continue to fade into the land of legacy
&amp;ndash; which, don&amp;rsquo;t underestimate the size of legacy code in this world &amp;ndash;
but ultimately, it won&amp;rsquo;t be used for new projects.&lt;/p&gt;
&lt;p&gt;In the meantime, C++ has an opportunity to fix this problem with itself,
although many others would remain. They have a duty to do so, and to
take this issue seriously, as memory safety remains a serious problem
for those large codebases that will remain for some time.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Asahi Linux Again</title>
      <link href="https://www.thecodedmessage.com/posts/asahi-2/" />
      <id>https://www.thecodedmessage.com/posts/asahi-2/</id>
      <updated>2024-05-18T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Since my &lt;a href=&#34;https://www.thecodedmessage.com/posts/first-impressions-asahi-linux/&#34;&gt;previous post&lt;/a&gt;,
I haven&amp;rsquo;t posted about Asahi Linux. This is for a simple reason:
I wasn&amp;rsquo;t using it. I never took the time to set up a tiling window
manager, get dropbox working, and all the things I felt I needed,
and I slipped back to using my trusty Dell Ubuntu laptop for Linux,
and using my MacBook M1 just for macOS.&lt;/p&gt;
&lt;p&gt;But then I tried again! And wow, has Asahi Linux changed! It&amp;rsquo;s Fedora,
not Arch now, and installation was much easier! So I wanted to share
how my experience has gone. I&amp;rsquo;m not particularly stoked to spend too
much time on sysadmin tasks for my personal computing, so this is
more a narrative about what actually has happened in my adjustment to
it, rather than a reflection of Asahi at its best, but I thought I&amp;rsquo;d
share where I was at.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Since my &lt;a href=&#34;https://www.thecodedmessage.com/posts/first-impressions-asahi-linux/&#34;&gt;previous post&lt;/a&gt;,
I haven&amp;rsquo;t posted about Asahi Linux. This is for a simple reason:
I wasn&amp;rsquo;t using it. I never took the time to set up a tiling window
manager, get dropbox working, and all the things I felt I needed,
and I slipped back to using my trusty Dell Ubuntu laptop for Linux,
and using my MacBook M1 just for macOS.&lt;/p&gt;
&lt;p&gt;But then I tried again! And wow, has Asahi Linux changed! It&amp;rsquo;s Fedora,
not Arch now, and installation was much easier! So I wanted to share
how my experience has gone. I&amp;rsquo;m not particularly stoked to spend too
much time on sysadmin tasks for my personal computing, so this is
more a narrative about what actually has happened in my adjustment to
it, rather than a reflection of Asahi at its best, but I thought I&amp;rsquo;d
share where I was at.&lt;/p&gt;
&lt;p&gt;Most things are amazing. I like Fedora. Adjusting to using &lt;code&gt;dnf&lt;/code&gt;
instead of &lt;code&gt;apt&lt;/code&gt; was easy enough. It&amp;rsquo;s also just nice using a more
powerful and quieter computer for my day-to-day Linux-side tasks,
so Asahi&amp;rsquo;s main goal is absolutely fulfilled. Good job!&lt;/p&gt;
&lt;h1 id=&#34;wayland-and-sway&#34;&gt;Wayland and Sway&lt;/h1&gt;
&lt;p&gt;The biggest issue is that X Windows is dead, and Wayland is now king.
This isn&amp;rsquo;t an Asahi specific issue, but it was Asahi that really got
me over this annoying hurdle.  I knew it was possible to get X Windows
working on Asahi, but it is very deeply recommended against, and I didn&amp;rsquo;t
want to try it.  That&amp;rsquo;s not an issue &lt;em&gt;per se&lt;/em&gt;, because I know X Windows
is rotting. But, it does mean that I can&amp;rsquo;t use XMonad anymore, as
XMonad is X Windows specific.&lt;/p&gt;
&lt;p&gt;So, of course, &lt;a href=&#34;https://swaywm.org/&#34;&gt;Sway&lt;/a&gt; it is. It requires
configuration and learning a new tiling window manager, which is
annoying. Worse, there seems to be no way with the version of Sway
that comes with Asahi to actually get title bars to go away. The
work-around of setting the font size to 0 doesn&amp;rsquo;t work on my
version, and of course there should just be an &lt;a href=&#34;https://github.com/swaywm/sway/issues/7409&#34;&gt;actual setting for
it&lt;/a&gt; but the &lt;a href=&#34;https://github.com/swaywm/sway/pull/8026&#34;&gt;PR seems to
be stuck&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know why anyone wants titlebars in a tiling window manager,
so I don&amp;rsquo;t know why no title bars isn&amp;rsquo;t the default. I have no idea why
this hackish work-around was considered acceptable. Are Sway users or
maintainers just into extra information that uses up a lot of screen
real estate?  I use tiling window managers partially to not waste space
(and &lt;a href=&#34;https://www.thecodedmessage.com/tags/ADHD/&#34;&gt;attention&lt;/a&gt;) on distractions from what&amp;rsquo;s actually
going on in my window, so this is a disappointment. Look at how
pointless it is:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/sway.png&#34; alt=&#34;Screenshot of Sway&#34;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; This has been fixed by advice from a helpful person in the
comments, without me having to do any dev work! Thank you so much!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But this matches how I feel about the switch from X Windows
to Wayland in general. Lots of reconfiguration, lots of new workflows,
lots of old tools that don&amp;rsquo;t work. (Does ImageMagick &lt;code&gt;import&lt;/code&gt; take
screenshots still? Hmm, doesn&amp;rsquo;t seem to. OK, &lt;code&gt;grim&lt;/code&gt; it is.) If you&amp;rsquo;re
a user of a desktop environment like KDE or Gnome, it&amp;rsquo;s great! If you
aren&amp;rsquo;t, well, you have to re-figure out everything, which is something
that I don&amp;rsquo;t have time for, because I&amp;rsquo;m not really a hobbyist in
&amp;ldquo;having and using a computer&amp;rdquo; anymore. I have things I actually
want to do with it!&lt;/p&gt;
&lt;p&gt;And, the tools on Wayland are actually less polished. Wayland in general
might be the future, and I know this will get better over time, but
there&amp;rsquo;s so much work to be done.&lt;/p&gt;
&lt;p&gt;Ironically, this is probably one of the best pro-C++ arguments over
Rust.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;EDIT to explain:&lt;/strong&gt;
There&amp;rsquo;s lots of people who would have a huge learning curve to go
through to transition. That investment can&amp;rsquo;t be taken for granted, as
both C++ and Rust have both steep and long learning curves, especially
if used in a systems context. Perhaps that&amp;rsquo;s one of the biggest reasons
for resistence to Rust.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I don&amp;rsquo;t maintain computer desktops for a living, unlike programming
which I do do for a living. If I did, I&amp;rsquo;d have time to learn all this
new stuff more thoroughly, and maybe even get involved with things like
Sway. But as it is, I&amp;rsquo;m just frustrated at having to learn new things
just to get things done.&lt;/p&gt;
&lt;p&gt;This titlebar thing isn&amp;rsquo;t the only Sway issue. I&amp;rsquo;m also experiencing
&lt;a href=&#34;https://github.com/swaywm/sway/issues/6220&#34;&gt;this&lt;/a&gt; issue, which
is unfortunately closed, because there seems to be some sort of
work-around &amp;ndash; even though it hasn&amp;rsquo;t worked for me.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m just sort of dealing with it for now. I know that with some amount
of work I could get all of these things smoothed out, but I&amp;rsquo;m worried
that it&amp;rsquo;ll involve actual dev work on Sway itself, and I don&amp;rsquo;t even want
to run a custom build of Sway. I just want the prepackaged Sway that
comes with Fedora to be good, and to work with the prepackaged version
of gvim. Is that too much to ask?&lt;/p&gt;
&lt;p&gt;I know this isn&amp;rsquo;t Asahi Linux&amp;rsquo;s fault, or even really Fedora&amp;rsquo;s fault.
I know this is to some extent what I sign up for by using tiling
window managers. It&amp;rsquo;s just a completely normal consequence of a large
transition.  However, I think people who are pushing Wayland over X
Windows should be aware of how many little things it&amp;rsquo;s messing up for
people. I also think that Sway deserves more love (that is, work) as a
project, given that I can&amp;rsquo;t be the only person in this sort of situation.&lt;/p&gt;
&lt;h1 id=&#34;box64-for-baba-is-you&#34;&gt;Box64 for Baba Is You&lt;/h1&gt;
&lt;p&gt;A happier story is that running Intel binaries on ARM is great!
I had a false start with &lt;code&gt;qemu-user&lt;/code&gt;, but it turns out &lt;code&gt;box64&lt;/code&gt;
just does the trick. &lt;a href=&#34;https://github.com/ptitSeb/box64&#34;&gt;Box64&lt;/a&gt;
allows you to run Intel binaries linked against native (ARM)
libraries, which is quite impressive! Unfortunately, the one
in Fedora&amp;rsquo;s package manager was compiled for the wrong page size,
so I did have to recompile it.&lt;/p&gt;
&lt;p&gt;But it runs &lt;a href=&#34;https://hempuli.com/baba/&#34;&gt;Baba Is You&lt;/a&gt; no problem,
which is an excellent game!&lt;/p&gt;
&lt;p&gt;Box64 integrates super well with Linux. You can just launch the
Intel binary, and it Just Works™ if you have it installed. I
think a build appropriate for Macs should be available if installed
on Asahi, and I also think that it should be part of the default
installation. Then, you&amp;rsquo;d be able to &amp;ldquo;just run&amp;rdquo; Intel Linux binaries.
How nice!&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t tried any other programs out in it, but I suspect it&amp;rsquo;ll be
not perfect but very very good.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>What Bits Mean: Meta-Data and Static Typing</title>
      <link href="https://www.thecodedmessage.com/posts/can-you-read-binary/" />
      <id>https://www.thecodedmessage.com/posts/can-you-read-binary/</id>
      <updated>2024-04-23T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;This is part of my new &lt;a href=&#34;https://www.thecodedmessage.com/tags/what-bits-mean/&#34;&gt;series&lt;/a&gt; on what the 0&amp;rsquo;s
and 1&amp;rsquo;s in computers &lt;em&gt;mean&lt;/em&gt;, how computers use them to store various
kinds of information, and why all of this works the way it does.&lt;/p&gt;
&lt;p&gt;When I was a boy, my schoolmates, knowing that I was interested in
computers, would sometimes ask me if I could read binary. They
imagined I would see some binary, and be able to read it out
loud like they could read letters, perhaps some binary that
looked like this:&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;This is part of my new &lt;a href=&#34;https://www.thecodedmessage.com/tags/what-bits-mean/&#34;&gt;series&lt;/a&gt; on what the 0&amp;rsquo;s
and 1&amp;rsquo;s in computers &lt;em&gt;mean&lt;/em&gt;, how computers use them to store various
kinds of information, and why all of this works the way it does.&lt;/p&gt;
&lt;p&gt;When I was a boy, my schoolmates, knowing that I was interested in
computers, would sometimes ask me if I could read binary. They
imagined I would see some binary, and be able to read it out
loud like they could read letters, perhaps some binary that
looked like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;01000111
01001001
01000110
01010100
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I&amp;rsquo;m not sure how I handled this situation as a boy &amp;ndash; I&amp;rsquo;m sure it was
plenty awkward and convoluted because my memory of it is blanked out.
But I have a question in response now, and I offer it to you, my
reader: Do you know how to read letters?&lt;/p&gt;
&lt;p&gt;Perhaps, if you do, you can tell me what this sequence of letters
means. I will tell you that I saw it written on a mysterious bottle
of mysterious liquid:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;GIFT
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, perhaps you are very confident you know. But perhaps you want to ask
a follow-up question. Because that sequence of letters can mean &amp;ldquo;present,
item that has been given to you, free distribution of a good&amp;rdquo; &amp;ndash; if we are
assuming it is an English. If we instead assume it is a German word, well,
then it means &amp;ldquo;poison.&amp;rdquo; Very different. (And perhaps in either case we
shouldn&amp;rsquo;t drink mysterious liquids, even out of mysterious bottles that
are only hypothetical &amp;ndash; perhaps especially out of ones that are only
&lt;a href=&#34;https://xkcd.com/248/&#34;&gt;hypothetical&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;But yes, letters are symbols, but they only have meaning in the
context of a language to interpret them. The same series of
symbols can mean two different words in two different languages.&lt;/p&gt;
&lt;p&gt;Similarly, the binary I listed above could have different interpretations,
depending on what &lt;em&gt;type&lt;/em&gt; the data has.  If interpreted as text with
an ASCII character encoding, it says &amp;ldquo;&lt;code&gt;GIFT&lt;/code&gt;&amp;rdquo; (with no indication,
of course, whether that means poison or present). If interpreted as a
32-bit unsigned integer in little endian (increasing addresses from the
top of the screen to the bottom), it is &lt;code&gt;1413892423&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, like with language in most situations, (especially ones that don&amp;rsquo;t
involve mysterious bottles), we can use context clues to guess that
it is more likely that I, Jimmy Hartzell, the author of (or at least
the poster of) those bits, chose them to represent the word &lt;code&gt;GIFT&lt;/code&gt;
rather than the number 1413892423, a number with no relevance to the
&lt;a href=&#34;https://www.statista.com/statistics/1298474/china-domestic-tea-sales-price-by-type/&#34;&gt;price&lt;/a&gt;
of &lt;a href=&#34;https://en.wiktionary.org/wiki/price_of_tea_in_China&#34;&gt;tea in China&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But computers can&amp;rsquo;t use context cues, certainly not in a probabilistic,
critical-thinking based way. Or at least, traditionally they can&amp;rsquo;t! And
they certainly can&amp;rsquo;t at the speed and reliability needed to do their
normal day-to-day work. Computers need determinism! They need mechanisms
guaranteed to tell them whether those bits written above, those 1&amp;rsquo;s and
0&amp;rsquo;s were ASCII text spelling &lt;code&gt;GIFT&lt;/code&gt; or a (32-bit unsigned little endian
integer) number, specifically 1413892423, or some other interpretation,
like an 8 pixel by 4 pixel black and white image, or perhaps just garbage
that just happened to be in unallocated memory, ready to be overwritten
by something more useful.&lt;/p&gt;
&lt;p&gt;Now, there are myriad ways that computers accomplish this. It differs
by computer platform and operating system and programming language.
But some of the simpler ones are familiar to any computer user.&lt;/p&gt;
&lt;p&gt;One way of figuring out what interpretation to use for bits
is meta-data &amp;ndash; bits that are interpreted to mean things about
how to interpret other bits. You may have heard the term meta-data
before, and you certainly know some examples.&lt;/p&gt;
&lt;p&gt;Meta-data is like the labels on a form. Here is an example
form without labels:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Jimmy&lt;br&gt;
Hartzell&lt;br&gt;
Male&lt;br&gt;
Pennsylvania&lt;br&gt;
United States of America&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you see this form, you can probably guess that it provides my given
name, surname, gender, state of residence, and country of citizenship.&lt;/p&gt;
&lt;p&gt;But some people are named Virginia, and some people live in the state
of Virginia, so there&amp;rsquo;s always room for confusion! And from Dune I&amp;rsquo;ve
learned that at least some fictional people have the word &amp;ldquo;Idaho&amp;rdquo; attached
to them, and it&amp;rsquo;s not a &lt;a href=&#34;https://en.wikipedia.org/wiki/Idaho&#34;&gt;state&lt;/a&gt;
but a &lt;a href=&#34;https://en.wikipedia.org/wiki/Idaho&#34;&gt;surname&lt;/a&gt;. For these and
other reasons, in practice, bureaucracies (which like computers have an
allergy for confusion and a need for objective, consistent processes that
they will follow against any and all opposing forces of common sense)
use labels on their forms:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Given Name:&lt;/strong&gt; Jimmy&lt;br&gt;
&lt;strong&gt;Surname:&lt;/strong&gt; Hartzell&lt;br&gt;
&lt;strong&gt;Gender:&lt;/strong&gt; Male&lt;br&gt;
&lt;strong&gt;State of Residence:&lt;/strong&gt; Pennsylvania&lt;br&gt;
&lt;strong&gt;Nationality:&lt;/strong&gt; United States of America&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Even so, these labels are only useful if you know how to read the
language. Even meta-data has to have some interpretative lens.
Additionally, oftentimes, a bureaucratic form becomes invalid
(and gets rejected by the authorities) if you start moving
fields around, or start adding your own form. If I renewed
my driver&amp;rsquo;s license, but decided to draw up my own form,
it would be rejected, even if my meta-data were abundantly clear
and it had all the data they wanted:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Favorite Color:&lt;/strong&gt; Blue&lt;br&gt;
&lt;strong&gt;Musical Instruments:&lt;/strong&gt; Piano, recorder, trombone, vocals&lt;br&gt;
&lt;strong&gt;Given name:&lt;/strong&gt; Jimmy&lt;br&gt;
&lt;strong&gt;Nationality:&lt;/strong&gt; United States of America&lt;br&gt;
&lt;strong&gt;Surname:&lt;/strong&gt; Hartzell&lt;br&gt;
&lt;strong&gt;State of Residence:&lt;/strong&gt; Pennsylvania&lt;br&gt;
&lt;strong&gt;State of Mind:&lt;/strong&gt; Happy&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Depending on what kind of computer system you&amp;rsquo;re dealing with,
the computer might or might not mind adding additional fields &amp;ndash;
also depending on how fields are defined and how the meta-data
is structured and what the format is for combining the meta-data
with the data. It&amp;rsquo;s all quite complicated.&lt;/p&gt;
&lt;p&gt;One common type of meta-data is file extensions. A file with a name ending
in &lt;code&gt;.docx&lt;/code&gt; is a Word Document, and when you (in this scenario perhaps
you are a Microsoft Windows™ user) double-click on it in Windows&amp;rsquo;s
file management program (is it still called Windows Explorer?), the
program Microsoft Word™ will load to open it. If you name any
old file to say &lt;code&gt;.docx&lt;/code&gt;, it will still try to open it in Word,
and then Word will yell at you that it can&amp;rsquo;t open it. (Oddly
enough, if you rename it to say &lt;code&gt;.zip&lt;/code&gt; instead, it will unzip
just fine &amp;ndash; Word documents are also zip files.)&lt;/p&gt;
&lt;p&gt;How&amp;rsquo;s Windows know to open Word? Why&amp;rsquo;s it do it even if it&amp;rsquo;s not a valid
Word document? It&amp;rsquo;s the extension. But not only the extension!  It has
configuration in the registry (at least it did at one time &amp;ndash; do they
still use a registry?) that associates the extension &lt;code&gt;.docx&lt;/code&gt; with Word.
Hopefully, that was the intention of the person who created the file,
but you would imagine it is, otherwise they wouldn&amp;rsquo;t have named it
that.&lt;/p&gt;
&lt;p&gt;But even this convention depends on the context of the registry, not
to mention the whole NTFS filesystem that Windows is probably using to
tell which parts of the hard drive correspond to which named files in
which folders.&lt;/p&gt;
&lt;p&gt;You could also imagine a system where there were no file extensions
and no file metadata. If you wanted to open a Word document, you
would have to open Word first, and with it select a file to open.
It would then try to open it as a Word document, and either you&amp;rsquo;d
get something sensical or not depending on whether you were
right about what program to use for that file. The onus would
then be on the user for what program to use to open what file.&lt;/p&gt;
&lt;p&gt;Perhaps the user could use their own metadata system, and have a Word
document that they remember is a Word document, in which they write
which program to use to open which file. Or perhaps the user can try
different programs until they find one that makes sense. Perhaps
the user can use specialized but ultimately fallible tools like
&lt;a href=&#34;https://en.wikipedia.org/wiki/File_%28command%29&#34;&gt;&lt;code&gt;file&lt;/code&gt;&lt;/a&gt; to see if there
are any (relatively rigorous and consistent) clues as to the file type.
Or the user may simply remember inside their own memory.&lt;/p&gt;
&lt;p&gt;All of this is complicated, but that&amp;rsquo;s the world we live in. Symbols
don&amp;rsquo;t have intrinsic meaning, and there is no inherent right language
or right way to speak any language. There is no one way to read
binary, and it is even more complicated than this essay implies,
or than you might ever have guessed.&lt;/p&gt;
&lt;p&gt;This extends into programming languages. In Python, variables
have no type. You can use the same variable &lt;code&gt;foo&lt;/code&gt; and put
a number like &lt;code&gt;33&lt;/code&gt; or text like &lt;code&gt;&amp;quot;GIFT&amp;quot;&lt;/code&gt; into it. If you try
to do an operation that doesn&amp;rsquo;t make sense, you get an error
when you reach that operation, but not beforehand.:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; random
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; random&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;randint(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;33&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(foo)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(foo &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Half the time, this prints 33 and then 34. The other half, it prints
&amp;ldquo;Hi&amp;rdquo; and then outputs an error message. Python is using meta-data to
keep track of whether &lt;code&gt;foo&lt;/code&gt; is a number or a string. That meta-data is
in a format that makes sense to the Python interpreter, and allows the
Python interpreter to inspect &lt;code&gt;foo&lt;/code&gt; to see what type it is. If &lt;code&gt;foo + 1&lt;/code&gt; makes sense given that type, it does it. If it doesn&amp;rsquo;t, it displays
an error on the spot.&lt;/p&gt;
&lt;p&gt;This prevents it from misinterpreting data. The text &amp;ldquo;GIFT&amp;rdquo;
will never be misinterpreted as the number 1413892423, because
it won&amp;rsquo;t have the right meta-data. Any Python code that works
on numbers will instead show an error message if the wrong
meta-data is present.&lt;/p&gt;
&lt;p&gt;What about a language like Rust? Rust also keeps track of types,
but it does so without using meta-data like this. Rust takes
your Rust program, and converts it into machine code that runs
directly on your computer, a process known as &lt;em&gt;compilation&lt;/em&gt;.
That machine code is a series of instructions that are guaranteed
to respect type safety (as long as you either don&amp;rsquo;t use unsafe
Rust features or else only use them according to the strict rules
Rust requires), so that if you write data interpreted as a number,
the data is also read as a number.&lt;/p&gt;
&lt;p&gt;Once the program is running, it doesn&amp;rsquo;t use meta-data to accomplish
this. Instead, it is more like the user who knows to open Microsoft Word
before opening a Word document. The instructions know to do operations
on the right values. If they load a memory address to do math on it,
it is because that memory address is known to the Rust compiler to
be the type of data that math can be used for.&lt;/p&gt;
&lt;p&gt;In this way, Rust is like a clever programmer who only writes correct
code. If they store an integer in address &lt;code&gt;0xffffd9718c6c&lt;/code&gt;, and they
load that value later, the programmer will remember in their brain that
they should expect it to be stored as an integer. The resulting program
works because the programmer wrote it in such a way that it would work,
even though this information isn&amp;rsquo;t written down anywhere, because
it uses addresses consistently.&lt;/p&gt;
&lt;p&gt;The same is true of programs compiled by the Rust compiler. Once
the compiler is done, it is not written down anywhere what type
a variable has. At a computer level, the program is just written
in such a way as to use data consistently.&lt;/p&gt;
&lt;p&gt;This is more efficient, as Rust programs don&amp;rsquo;t need to take up extra
memory for the meta-data. However, it does mean that the Python program
we wrote above won&amp;rsquo;t work in Rust. We can&amp;rsquo;t even compile a program
that tries to set a variable to two values of different types. There&amp;rsquo;s
nowhere to write down the type information.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try to write an equivalent Rust program and see what
happens.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; rand::Rng;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; rng &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; rand::thread_rng();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; test &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; rng.gen();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; foo;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; test {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;33&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{foo}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this case, you get an error:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;   Compiling TypePun v0.1.0 (/home/jim/hobby/TypePun)
error[E0308]: mismatched types
  --&amp;gt; src/main.rs:10:15
   |
6  |     let foo;
   |         --- expected due to the type of this binding
...
10 |         foo = &amp;#34;Hi&amp;#34;;
   |               ^^^^ expected integer, found `&amp;amp;str`
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That makes sense, because Rust is keeping track of what
type &lt;code&gt;foo&lt;/code&gt; is supposed to be, so it can use it consistently.
It can&amp;rsquo;t vary from run to run of the program, because that
information isn&amp;rsquo;t written down anywhere. The value of &lt;code&gt;foo&lt;/code&gt;
can vary, of course &amp;ndash; it wouldn&amp;rsquo;t be a good variable if
it couldn&amp;rsquo;t &amp;ndash; but the &lt;em&gt;type&lt;/em&gt;, the interpretation
of &lt;code&gt;foo&lt;/code&gt;&amp;rsquo;s bits, cannot.&lt;/p&gt;
&lt;p&gt;Of course, Rust can do everything Python can. In this case,
you could tell Rust yourself to use a new type that uses
meta-data to keep track of what type an inner value is.
You can even do the math on it if it&amp;rsquo;s a number.&lt;/p&gt;
&lt;p&gt;It gets complicated fast, since you have to define a
new type, here &lt;code&gt;StringOrInt&lt;/code&gt;, that indicates how to
not only interpret the data in the value, but also
the meta-data of what type of value it is. That outer
type, however, is not stored in the resulting program
as meta-meta-data.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; rand::Rng;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; rng &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; rand::thread_rng();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; test &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; rng.gen();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;StringOrInt&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        String(String),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Int(&lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; foo;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; test {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; StringOrInt::Int(&lt;span style=&#34;color:#ae81ff&#34;&gt;33&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; StringOrInt::String(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;match&lt;/span&gt; foo {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        StringOrInt::Int(foo) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{foo}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, foo &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        StringOrInt::String(foo) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{foo}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you were to write a Python interpreter in Rust, you would have to do
something like this for every variable, where you create a type that can
contain multiple inner types. This is only one example of a technique
that does this, where we created an &lt;code&gt;enum&lt;/code&gt; type, but there are others,
like &amp;ldquo;trait objects.&amp;rdquo; They all work according to similar principles:
Rust needs to know explicitly that you want meta-data to keep track of
additional information, and what style of meta-data you want.&lt;/p&gt;
&lt;p&gt;Note that, in Rust, it still knows at compile-time whether &lt;code&gt;+&lt;/code&gt; is
an appropriate operation.&lt;/p&gt;
&lt;p&gt;I mentioned something about safety earlier. You can get Rust to
violate its rules with &lt;code&gt;unsafe&lt;/code&gt;. This results in undefined behavior
in general, and so the results you get with &lt;code&gt;unsafe&lt;/code&gt; are not
guaranteed to be consistent. However, we can use this to demonstrate
what happens if Rust were to get its type information wrong.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GIFT&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; foo_ptr: &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;*&lt;/span&gt;foo;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Safety: This just is unsafe.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; foo_number &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;unsafe&lt;/span&gt; { &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;(foo_ptr &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;) };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{foo_number}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The key here is this line:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; foo_number &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;unsafe&lt;/span&gt; { &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;(foo_ptr &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;) };
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This means something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rust, I know you&amp;rsquo;re keeping track of what types go with
what memory addresses. I know &lt;code&gt;foo_ptr&lt;/code&gt; is a memory address
of text (&lt;code&gt;*const str&lt;/code&gt; means pointer to &lt;code&gt;str&lt;/code&gt;, and &lt;code&gt;str&lt;/code&gt; means
text). But I want you to pretend it&amp;rsquo;s a pointer to an
unsigned 32-bit integer (which is little endian on most
machines, including the author&amp;rsquo;s Mac Book M1 which has an
ARM64 processor), and read it according to that interpretation
instead, letting me do operations appropriate to that
interpretation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And it prints, of course, on my machine:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1413892423
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we&amp;rsquo;d done &lt;code&gt;println!(&amp;quot;{foo}&amp;quot;)&lt;/code&gt;, we would&amp;rsquo;ve gotten:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;GIFT
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The same data is passed to &lt;code&gt;println!&lt;/code&gt;, but what it actually does is based
on the type of the data. Again, this type is not tracked explicitly in
the outputted machine code. Rust just makes sure that the machine code
is appropriate for types that make sense.&lt;/p&gt;
&lt;p&gt;This mechanism that Rust uses is called &lt;em&gt;static typing&lt;/em&gt;, where instead of
using meta-data like Python does, Rust creates a program that does the
right thing, or else rejects a program that does something nonsensical
or incoherent (or else fails to reject it because you tell Rust you know
what you&amp;rsquo;re doing is unsafe).&lt;/p&gt;
&lt;p&gt;Static typing has many uses. It is primarily used to make sure that you
only do operations that make sense for the type you have. Some
operations do different things to different types &amp;ndash; &lt;code&gt;+&lt;/code&gt; means
one hardware operation for an integer like &lt;code&gt;u32&lt;/code&gt;, and something
else for a floating point like &lt;code&gt;f32&lt;/code&gt;, and static typing also
keeps track of that. You can create new operations like that &amp;ndash;
they are called &lt;em&gt;polymorphic&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Static typing is also used to reject programs where that is not possible,
where you write according to one binary format and read from another,
unless you use &lt;code&gt;unsafe&lt;/code&gt; to override these checks. The resulting programs
would otherwise be incoherent and nonsensical, which could lead to memory
corruption, especially if the optimizer is involved, which assumes you&amp;rsquo;re
following the rules when it modifies the program to make it faster.&lt;/p&gt;
&lt;p&gt;Static typing can also be used via creating custom types. These custom
types might mean specific things in a certain context, to distinguish
bits in more detailed ways than the built-in types do so. Are three
&lt;code&gt;f64&lt;/code&gt; values a color (red, green, and blue) or a coordinate in a
three-dimensional grid (X, Y, and Z)? Two types can be created
to distinguish them, beyond what the built-in type of &lt;code&gt;f64&lt;/code&gt; already
does:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ThreeDimensionalCoordinate&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    y: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    z: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Color&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    red: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    green: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    blue: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;draw&lt;/span&gt;(coord: &lt;span style=&#34;color:#a6e22e&#34;&gt;ThreeDimensionalCoordinate&lt;/span&gt;, color: &lt;span style=&#34;color:#a6e22e&#34;&gt;Color&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if there are 3 &lt;code&gt;f64&lt;/code&gt; values in a row, we can use Rust&amp;rsquo;s
static typing system not to just track that they&amp;rsquo;re all &lt;code&gt;f64&lt;/code&gt; values,
but whether they together represent a color or a coordinate. Otherwise,
a user might accidentally mix them up calling the &lt;code&gt;draw&lt;/code&gt; function,
and the program might do something illogical.&lt;/p&gt;
&lt;p&gt;So, static typing prevents incoherent code. It does it before you get
a chance to run it, making it easier to catch bugs. And it makes it so
you need less meta-data at run time (though some programming languages
leverage both static typing and run-time type meta-data).&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>What Bits Mean: Binary Integers and Two&#39;s Complement</title>
      <link href="https://www.thecodedmessage.com/posts/twos-complement/" />
      <id>https://www.thecodedmessage.com/posts/twos-complement/</id>
      <updated>2024-04-15T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I was explaining two&amp;rsquo;s complement recently&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; to a friend, and I thought
my explanation was decent, so I decided to write it up and share it
with you, my general blog audience, as well! If you already know about
two&amp;rsquo;s complement, this will pretty much just be a review. If not, you
may learn something, and you may not understand all of it. Try to get
what you can without getting too anxious, there will not be a test!&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I was explaining two&amp;rsquo;s complement recently&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; to a friend, and I thought
my explanation was decent, so I decided to write it up and share it
with you, my general blog audience, as well! If you already know about
two&amp;rsquo;s complement, this will pretty much just be a review. If not, you
may learn something, and you may not understand all of it. Try to get
what you can without getting too anxious, there will not be a test!&lt;/p&gt;
&lt;p&gt;In either case, feel free to ask questions in the comments
or nit-pick any mistakes you see!&lt;/p&gt;
&lt;h1 id=&#34;storing-numbers-in-binary&#34;&gt;Storing Numbers in Binary&lt;/h1&gt;
&lt;p&gt;So, without further ado, let&amp;rsquo;s talk about binary.&lt;/p&gt;
&lt;p&gt;Computers store all information in binary, in terms of combinations
of two values, conventionally called &amp;ldquo;zero&amp;rdquo; and &amp;ldquo;one.&amp;rdquo; It is easy to
distinguish two values in a physical representation: the presence or
absence of current on a wire, or of a radio signal; two areas magnetized
in the same direction or opposite direction; a capacitor that is charged
or not charged. Only having two possibilities for each storage location is
just easier for computing circuitry to work with, and so all information
in a computer is stored as patterns of two values.&lt;/p&gt;
&lt;p&gt;All information in a computer is stored in binary, whether it be text,
images, audio, video, scientific data, and even programs. Binary is
meaningless without a convention for interpreting it. Today, we will
talk about how numbers are stored in binary, specifically integers.&lt;/p&gt;
&lt;p&gt;So how do we encode integers in binary? Let&amp;rsquo;s start out by assuming all
the integers we might want to store are non-negative, and then we will
discuss later how to accommodate negative numbers.&lt;/p&gt;
&lt;p&gt;Computers encode integers similar to how humans do with a pen and paper,
by using a positional number system. When we read a number like 357,
we know that it contains 3 hundreds (&lt;code&gt;3*10^2&lt;/code&gt;), 5 tens (&lt;code&gt;3*10^1&lt;/code&gt;) and
7 ones (&lt;code&gt;7*10^0&lt;/code&gt;), where &lt;code&gt;^&lt;/code&gt; is used as the symbol for exponentiation.&lt;/p&gt;
&lt;p&gt;Computers use a similar system, but with 2 playing the role of 10.
Said another way, computers use base 2 instead of base 10. So, 1101
represents the number 13:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1101
1 * 2 ^ 3 + 1 * 2 ^ 2 + 0 * 2 ^ 1 + 1 * 2 ^ 0
1 * 8     + 1 * 4     + 0 * 2     + 1 * 1
8         + 4         + 0         + 1
13
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Instead of (from right to left) seeing a ones place, tens place, and
hundreds place, we have a ones place, a twos place, a fours place,
and an eights place. It continues with increasing powers of 2 (again,
right to left in the number): 1, 2, 4, 8, 16, 32, 64, 128, 256, 512,
1024, 2048, 4096, 8192, 16384, 32768, 65536&amp;hellip;&lt;/p&gt;
&lt;p&gt;When we write numbers in base 10, we write as many digits as it takes
to store the number, and no more. 357 is a 3-digit number, but 5364 is
a 4-digit number. But when computers store numbers in binary, they
generally have a fixed amount of memory to work with, memory that
is specifically designated to store this number. If the number
can&amp;rsquo;t be stored in that many binary digits &amp;ndash; that many &lt;em&gt;bits&lt;/em&gt; &amp;ndash;
then, well, it can&amp;rsquo;t be stored in that amount of memory. Programmers
in lower-level languages (like C++ or Rust) simply have to be careful
that this situation doesn&amp;rsquo;t arise, either by ensuring no larger numbers
will be stored, or else checking for situations where larger numbers would
be stored, and either signalling an error or arranging an alternative
storage arrangement.&lt;/p&gt;
&lt;p&gt;Usually, a programming language would support 8-bit, 16-bit, 32-bit,
or 64-bit numbers. For unsigned numbers, these correspond to the &lt;em&gt;types&lt;/em&gt;
&lt;code&gt;uint8_t&lt;/code&gt;, &lt;code&gt;uint16_t&lt;/code&gt;, &lt;code&gt;uint32_t&lt;/code&gt; and &lt;code&gt;uint64_t&lt;/code&gt; in C or C++, or &lt;code&gt;u8&lt;/code&gt;,
&lt;code&gt;u16&lt;/code&gt;, &lt;code&gt;u32&lt;/code&gt; and &lt;code&gt;u64&lt;/code&gt; in Rust. A &lt;em&gt;type&lt;/em&gt;, by the way, is a particular way
of looking at a collection of bits in binary as a &lt;em&gt;value&lt;/em&gt;, determining
both a mode of interpretation and a size of how many bits are included
in the value.&lt;/p&gt;
&lt;p&gt;All the bits in the allocated space must be set to 0 or 1. So, if we
want to store the number 13 in an 8-bit number, we have to use &lt;code&gt;0&lt;/code&gt;s for
all the higher-order bits: &lt;code&gt;00001101&lt;/code&gt; means the same as &lt;code&gt;1101&lt;/code&gt;, just as
&lt;code&gt;000357&lt;/code&gt; means the same thing as &lt;code&gt;357&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For the purposes of this document, however, let&amp;rsquo;s talk about 4-bit
integers. 4 bits is half a byte or a &lt;em&gt;nibble&lt;/em&gt;. Most processors do not
have the capacity for directly interfacing with 4-bit integers &amp;ndash; they
only deal with 8 bits, or one &lt;em&gt;byte&lt;/em&gt;, at a time. But you can still
program with 4-bit numbers, you just have to do some extra work.
And it makes it possible to show every possibility in this document.
The lessons learned from it generalize to wider numbers.&lt;/p&gt;
&lt;p&gt;Here are all the possible 4-bit integers and their decimal (base 10,
normal human) equivalents:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;0000 -&amp;gt; 0
0001 -&amp;gt; 1
0010 -&amp;gt; 2
0011 -&amp;gt; 3
0100 -&amp;gt; 4
0101 -&amp;gt; 5
0110 -&amp;gt; 6
0111 -&amp;gt; 7
1000 -&amp;gt; 8
1001 -&amp;gt; 9
1010 -&amp;gt; 10
1011 -&amp;gt; 11
1100 -&amp;gt; 12
1101 -&amp;gt; 13
1110 -&amp;gt; 14
1111 -&amp;gt; 15
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Note that the maximum is one less than &lt;code&gt;2^4&lt;/code&gt;, which is 16. There
are 16 possible combinations of bits, but the maximum value is 15,
as one of the possible combinations is used to encode 0. All
integer types support storing 0.&lt;/p&gt;
&lt;p&gt;So, how do we do addition? It&amp;rsquo;s through a very similar process to how
we do addition in base 10. We take the two numbers we want to add,
and line them up bit by bit. Let&amp;rsquo;s add 7 and 3, which we can see
from the table are &lt;code&gt;0111&lt;/code&gt; and &lt;code&gt;0011&lt;/code&gt;. Let&amp;rsquo;s line them up in classic
grade school fashion:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;0111
0011
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, we can start adding. We start from the right, just as we did when
doing arithmetic in grade school. &lt;code&gt;1&lt;/code&gt; + &lt;code&gt;1&lt;/code&gt; is 2, which in base 2 is
&lt;code&gt;10&lt;/code&gt;. So we write down the &lt;code&gt;0&lt;/code&gt;, and carry the &lt;code&gt;1&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  1
0111
0011
----
   0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OK, now &lt;code&gt;1&lt;/code&gt; + &lt;code&gt;1&lt;/code&gt;, + the &lt;code&gt;1&lt;/code&gt; we carried from the previous step, is 3,
which in base 2 is &lt;code&gt;11&lt;/code&gt;. We write down the (right) &lt;code&gt;1&lt;/code&gt; and carry the
(left) &lt;code&gt;1&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; 11 
0111
0011
----
  10
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, &lt;code&gt;1&lt;/code&gt; + &lt;code&gt;0&lt;/code&gt;, + the &lt;code&gt;1&lt;/code&gt; we carried from before, is 2, which is &lt;code&gt;10&lt;/code&gt;.
Keep the &lt;code&gt;0&lt;/code&gt;, carry the &lt;code&gt;1&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;111 
0111
0011
----
 010
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Final step, &lt;code&gt;0&lt;/code&gt; + &lt;code&gt;0&lt;/code&gt; + the &lt;code&gt;1&lt;/code&gt; we carried is &lt;code&gt;1&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;111
0111
0011
----
1010
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This has &lt;code&gt;1&lt;/code&gt; in the 8s place and &lt;code&gt;1&lt;/code&gt; in the 2s place, and 0 in the
other places. 8+2=10, which is good because we were adding 7 and 3,
so 10 is the right answer. If we look in the table above, we see
that &lt;code&gt;1010&lt;/code&gt; indeed corresponds to &lt;code&gt;10&lt;/code&gt;, so we know we&amp;rsquo;ve done
it right.&lt;/p&gt;
&lt;p&gt;So that is how we add binary numbers.&lt;/p&gt;
&lt;h1 id=&#34;adding-numbers-with-circuitry-or-program-logic&#34;&gt;Adding Numbers with Circuitry or Program Logic&lt;/h1&gt;
&lt;p&gt;The addition table, as we can see, is very simple, so it can be
represented in circuitry. For each bit, we have three inputs: one bit
each from the two numbers, and the carry from the previous bit. We have
two outputs, the bit we&amp;rsquo;re keeping, and the carry to pass on to the next
bit.&lt;/p&gt;
&lt;p&gt;We can create a complete table for this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;BIT A | BIT B | INPUT CARRY | OUTPUT CARRY | OUTPUT
    0 |     0 |           0 |            0 |      0
    0 |     0 |           1 |            0 |      1
    0 |     1 |           0 |            0 |      1
    0 |     1 |           1 |            1 |      0
    1 |     0 |           0 |            0 |      1
    1 |     0 |           1 |            1 |      0
    1 |     1 |           0 |            1 |      0
    1 |     1 |           1 |            1 |      1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Whenever we have a complete table of a limited number of inputs and
outputs, it can be converted to a circuit. If we did so, and then wire
a bunch of these circuits together, we could create a hardware adder. I
will not go into how to do this in detail, as that is out of the scope
of this post, but you can see how it would be simpler than encoding an
entire addition table for base 10 in logic gates, which would have 200
entries instead of 8 (addition table with and without carried 1s).&lt;/p&gt;
&lt;p&gt;I will, however, show you how simple it is conceptually by writing
a program to do it in Rust. In this program, the binary numbers are
represented as slices of &lt;code&gt;bool&lt;/code&gt;s, or &lt;code&gt;true&lt;/code&gt;/&lt;code&gt;false&lt;/code&gt; values.  (A slice
is a region of memory with multiple values of the same type.)  &lt;code&gt;true&lt;/code&gt;
corresponds to &lt;code&gt;1&lt;/code&gt;, and &lt;code&gt;0&lt;/code&gt; corresponds to &lt;code&gt;false&lt;/code&gt;.  In this program,
the slices start from the right (the least significant bit, the one&amp;rsquo;s
place), and go to the left (the most significant bit, the 2^N place) &amp;ndash;
backwards from what you may be used to, but better suited for implementing
math like addition.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn add(a: &amp;amp;[bool], b: &amp;amp;[bool]) -&amp;gt; Result&amp;lt;Vec&amp;lt;bool&amp;gt;, Error&amp;gt; {
    // Keep track of carry
    // &amp;#39;mut&amp;#39; means it can change
    let mut carry = false;

    // Place to store the result
    //
    // A `Vec` lets us store a varying number of values of the
    // same type. It&amp;#39;s like a slice, but it can grow over time.
    // `Vec::new()` gives us an empty `Vec`.
    let mut res = Vec::new();

    // Make sure we have the same number of bits in each input
    if a.len() != b.len() {
        // We don&amp;#39;t? That&amp;#39;s an error!
        return Err(Error::MismatchedInputSizes);
    }

    // Go through each position
    for i in 0..a.len() {
        // Examine the corresponding input bits from each input nibble
        // Also examine the carry from the previous step.
        // The result will be the output and the new carry value.
        // 
        // This corresponds to a &amp;#34;full adder&amp;#34; circuit, and in a hardware
        // adder, one of these is used per bit.
        let (output, new_carry) = match (a[i], b[i], carry) {
            // We have a table of what possibilities there are
            // for these input bits, and what two outputs to generate.
            // 
            // In a circuit, this would be expressed through logic gates.
            // All 8 possible combinations of 3 inputs are enumerated.
            // 8 = 2 ^ 3
            //
            // This is a Rust representation of the table shown above.
            (false, false, false) =&amp;gt; (false, false),
            (false, false, true) =&amp;gt; (true, false),
            (false, true, false) =&amp;gt; (true, false),
            (false, true, true) =&amp;gt; (false, true),
            (true, false, false) =&amp;gt; (true, false),
            (true, false, true) =&amp;gt; (false, true),
            (true, true, false) =&amp;gt; (false, true),
            (true, true, true) =&amp;gt; (true, true),
        };
        carry = new_carry;

        // This bit is added to our result
        res.push(output);
    }

    // What if the result doesn&amp;#39;t fit in the same number of bits?
    // Because the highest order bits have a carry
    // We&amp;#39;ll write some guess temporarily for now, and
    // discuss carries in more detail later.
    if carry {
        panic!(&amp;#34;error message&amp;#34;); // ??? or something?
    }

    // We have successfully obtained a result!
    Ok(res)
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A full, runnable program is available &lt;a href=&#34;https://github.com/jhartzell42/thecodedmessage-examples/blob/main/src/binary.rs&#34;&gt;on
GitHub&lt;/a&gt;,
as are the other examples from this post.&lt;/p&gt;
&lt;p&gt;This program uses booleans as a stand-in for bits, with &lt;code&gt;true&lt;/code&gt; standing
in for &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; for &lt;code&gt;0&lt;/code&gt;.  It contains the table we created above,
but in the form of a &lt;code&gt;match&lt;/code&gt; expression. It loops through the two values,
from least-significant bit (rightmost, 1&amp;rsquo;s place) to most-significant
bit (leftmost, 2^N place), bringing the carry output from each place
and using it as input in the next operation.&lt;/p&gt;
&lt;p&gt;Ironically, actually running this program will actually use many more
than 4 bits for each number. It is designed to correspond conceptually
with the details of adding a 4-bit number. In practice, we&amp;rsquo;d use the
built-in &lt;code&gt;u8&lt;/code&gt; type and let the computer&amp;rsquo;s built-in addition circuitry
do it for us.&lt;/p&gt;
&lt;h1 id=&#34;overflow&#34;&gt;Overflow&lt;/h1&gt;
&lt;p&gt;So, what happens if we have a carry on the last bit? If we&amp;rsquo;re
adding two 4-bit numbers, and we&amp;rsquo;re storing the result in a 4-bit
number, what happens if we add 10 and 10? The result won&amp;rsquo;t fit
in a 4-bit number! You might assume (as my friend Ilse Purrenhage
did) that there would be &amp;ldquo;an error message or something&amp;rdquo; (and
therefore that&amp;rsquo;s what the Rust sample code does)!&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see what happens in practice!&lt;/p&gt;
&lt;p&gt;Here is a &lt;a href=&#34;https://github.com/jhartzell42/thecodedmessage-examples/blob/main/src/overflow.rs&#34;&gt;Rust
program&lt;/a&gt;
that overflows an 8-bit unsigned integer.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn main() {
    let mut integer: u8 = 255;
    integer += 1;
    println!(&amp;#34;{integer}&amp;#34;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here is a &lt;a href=&#34;https://github.com/jhartzell42/thecodedmessage-examples/blob/main/src/overflow.c&#34;&gt;C
program&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

int main() {
    // The highest 8-bit unsigned integer possible is 255,
    // or 2^8 - 1, the highest number you can represent
    // before you need a 2^8 or 256 place in binary.
    uint8_t integer = 255;

    // OK, so what happens if we add 1 to it?
    integer += 1;

    // Let&amp;#39;s print it out and see!
    printf(&amp;#34;%u\n&amp;#34;, integer);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Let&amp;rsquo;s start with the Rust program, as this is a Rust-focused blog.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~/Writing/thecodedmessage-examples]$ cargo run --bin overflow
   Compiling thecodedmessage-examples v0.1.0 (/home/jim/Writing/thecodedmessage-examples)
    Finished dev [unoptimized + debuginfo] target(s) in 0.37s
     Running `target/debug/overflow`
thread &amp;#39;main&amp;#39; panicked at &amp;#39;attempt to add with overflow&amp;#39;, overflow.rs:3:5
stack backtrace:
   0: rust_begin_unwind
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:578:5
   1: core::panicking::panic_fmt
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:67:14
   2: core::panicking::panic
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:117:5
   3: overflow::main
   4: core::ops::function::FnOnce::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ah, looks like my friend Ilse was right, as this definitely qualifies
as &amp;ldquo;an error message or something.&amp;rdquo; It&amp;rsquo;s reasonable that Rust does
this! There&amp;rsquo;s no way to store 256 in a &lt;code&gt;u8&lt;/code&gt;, so attempting to should
lead to an error.&lt;/p&gt;
&lt;p&gt;But the experienced Rustaceans in the audience know there&amp;rsquo;s another
shoe that&amp;rsquo;s about to drop. We&amp;rsquo;ve finished developing &lt;code&gt;overflow&lt;/code&gt;, and
we want to do a production release, so we run it in release mode, giving
the compiler more time to work on making the program run fast, and &amp;ndash;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~/Writing/thecodedmessage-examples]$ cargo run --release --bin overflow
    Finished release [optimized] target(s) in 0.00s
     Running `target/release/overflow`
0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Yes, that is indeed a 0 that was printed. 255 + 1 no longer results in an
error message. No, we now see that &lt;em&gt;in debug mode&lt;/em&gt;, while we are still
developing the project, it results in an error. But once we switch to
release mode, we get a &lt;code&gt;0&lt;/code&gt;. And unfortunately, &lt;code&gt;0&lt;/code&gt; is (checks notes)
not the sum of &lt;code&gt;255 + 1&lt;/code&gt;.  This is really putting the &amp;ldquo;or something&amp;rdquo;
into &amp;ldquo;an error message or something!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;What is going on here? Alright, maybe this is one of the things they
are complaining about when they say Rust is hard to learn. Let&amp;rsquo;s move
on to C, the &amp;ldquo;easier&amp;rdquo; programming language &amp;ndash;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~/Writing/thecodedmessage-examples/src]$ cc -o overflow overflow.c
[jim@palatinate:~/Writing/thecodedmessage-examples/src]$ ./overflow
0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;ndash; in which it would also appear that, for 8-bit integers, 255 + 1 = 0.&lt;/p&gt;
&lt;p&gt;So what exactly is going on? Well, let&amp;rsquo;s do out 255 + 1 in binary,
using the good ol&amp;rsquo; elementary school addition algorithm. We add 1
and 1, and get 10 (2), so carry the 1 and write down 0, which
collides against the next 1, so carry the 1 and write down 0,
until:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;11111111  (carry bits)
 11111111 (255)
 00000001 (1)
---------
 00000000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After doing all 8 bits, we have 8 bits of 0 as output, and still a 1
being carried to the 9th bit (also known as bit 8), the 256s place. Of
course, there is no 9th bit in the output, which is why we get an error
message or something when we run this. See our original &lt;code&gt;binary.rs&lt;/code&gt;
program which does this algorithm out by hand using booleans:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~/Writing/thecodedmessage-examples]$ cargo run --bin binary 00000001 11111111
   Compiling thecodedmessage-examples v0.1.0 (/home/jim/Writing/thecodedmessage-examples)
    Finished dev [unoptimized + debuginfo] target(s) in 0.41s
     Running `target/debug/binary 00000001 11111111`
thread &amp;#39;main&amp;#39; panicked at &amp;#39;error message&amp;#39;, src/binary.rs:64:9
stack backtrace:
   0: rust_begin_unwind
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/panicking.rs:578:5
   1: core::panicking::panic_fmt
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/panicking.rs:67:14
   2: binary::add
             at ./src/binary.rs:64:9
   3: binary::main
             at ./src/binary.rs:78:18
   4: core::ops::function::FnOnce::call_once
             at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ops/function.rs:250:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This was, if you remember from our example above, triggered because
the &lt;code&gt;carry&lt;/code&gt; variable was still &lt;code&gt;true&lt;/code&gt; after the entire loop!&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// What if the result doesn&amp;#39;t fit in the same number of bits?
// Because the highest order bits have a carry
if carry {
    panic!(&amp;#34;error message&amp;#34;); // ??? or something?
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But what if we just remove that code?&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~/Writing/thecodedmessage-examples]$ cargo run --bin binary 00000001 11111111
   Compiling thecodedmessage-examples v0.1.0 (/home/jim/Writing/thecodedmessage-examples)
    Finished dev [unoptimized + debuginfo] target(s) in 0.39s
     Running `target/debug/binary 00000001 11111111`
00000000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we just ignore the last carry bit, instead of doing anything at all, we
see that 1 + 255 does indeed equal 0. It equals 0, carrying a 1 into the
256s place, but if we just ignore that that carry might happen, it just
equals 0. And that is what C does. And if we are asking Rust to optimize
for performance rather than debuggability, that is also what Rust does.&lt;/p&gt;
&lt;p&gt;In fact, this is exactly the behavior that the C standard explicitly
requires for unsigned values. Code can be written that relies on this
behavior.&lt;/p&gt;
&lt;p&gt;So what exactly is happening here? How can we understand 255 + 1 = 0?
Well, we are ignoring a carry, and ignoring places above the 128ths
place. This creates a special form of math, where instead of increasing,
at a certain point numbers wrap around, like an old-fashioned odometer
going from 999999 to 000000, or a 24-hour clock going from 23:59 to 00:00,
or the day of the month going from 31 to 1.&lt;/p&gt;
&lt;h1 id=&#34;modular-arithmetic&#34;&gt;Modular Arithmetic&lt;/h1&gt;
&lt;p&gt;This is known in mathematics as &lt;em&gt;modular arithmetic&lt;/em&gt;, which is an
important part of &lt;em&gt;number theory&lt;/em&gt;, or the study of whole numbers and
integers (as opposed to rationals and reals, where modular arithmetic
would make little sense).  In modular arithmetic, we treat numbers as
if they are equal &amp;ndash; some call it &lt;em&gt;congruent&lt;/em&gt; &amp;ndash; if they have the same
remainder when divided by a number. The number we divide by can vary &amp;ndash;
it can be, for example, 2, 10, 24&amp;hellip; or 256.&lt;/p&gt;
&lt;p&gt;For example, 24-hour time works &lt;em&gt;modulo 24&lt;/em&gt;. 23 (or 11PM) + 1 hour yields
0 (or midnight). 22 (or 10PM) + 4 hours yields 2 (or 2AM).&lt;/p&gt;
&lt;p&gt;We can also do modular arithmetic &lt;em&gt;modulo 10&lt;/em&gt; by considering decimal
numbers and only paying attention to the one&amp;rsquo;s place. &lt;code&gt;3 * 5 = 15&lt;/code&gt;,
but we are only paying attention to the one&amp;rsquo;s place, so we say that
&lt;code&gt;3 * 5 = 5&lt;/code&gt; &lt;em&gt;modulo 10&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;One property of modular arithmetic is that negation works weirdly.
When working modulo 10, 9 also serves as -1. They are equivalent modulo
10, because they are a multiple of 10 apart. It works functionally:
6+9=5 &lt;em&gt;modulo 10&lt;/em&gt;, or 1+9=0 &lt;em&gt;modulo 10&lt;/em&gt;. Adding 9 is the same as
subtracting 1, so we can say that 9 is congruent to -1.&lt;/p&gt;
&lt;p&gt;Well, in C, and in Rust with debugging turned off, arithmetic on a &lt;code&gt;u8&lt;/code&gt;,
or any unsigned integer type, wraps around modulo the maximum value
plus 1.  For 4-bit integers, this would be 1111 + 1 in binary (or 15 +
1 in decimal), or 16. For 8-bit integers, it&amp;rsquo;s 256.&lt;/p&gt;
&lt;p&gt;This is a natural consequence of ignoring the final output of the
carry bit. Just like ignoring digits above the 1s place yields
modulo-10 arithmetic, ignoring bits above the 8s place yields
modulo-16 arithmetic.&lt;/p&gt;
&lt;p&gt;It does mean that, when we want to subtract 1 from a &lt;code&gt;u8&lt;/code&gt;, we can instead
add 0 - 1, which is 256 - 1, which is 255.  When we want to subtract 2,
we can instead add 0 - 2, aka 256 - 2, aka 254.&lt;/p&gt;
&lt;h1 id=&#34;twos-complement&#34;&gt;Two&amp;rsquo;s Complement&lt;/h1&gt;
&lt;p&gt;In fact, this is how computers implement subtraction in circuitry &amp;ndash;
and not just how we implement subtraction, but also negative numbers. To
negate a number, instead of counting up from 0, we count down from 0,
but with wrap-around.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s return to our 4-bit example, as that&amp;rsquo;s easier to work with.
Each combination of bits can be interpreted as a negative number, or a
positive number.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Bit Pattern | As Positive | As Negative
0000        | 0           | -16
0001        | 1           | -15
0010        | 2           | -14
0011        | 3           | -13
0100        | 4           | -12
0101        | 5           | -11
0110        | 6           | -10
0111        | 7           | -9
1000        | 8           | -8
1001        | 9           | -7
1010        | 10          | -6
1011        | 11          | -5
1100        | 12          | -4
1101        | 13          | -3
1110        | 14          | -2
1111        | 15          | -1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And, of course, it just wraps around after: 1111 + 1 (15 + 1) = 0000
(with a carry beyond the highest order digit).&lt;/p&gt;
&lt;p&gt;For most operations, it doesn&amp;rsquo;t matter whether we interpret the number
as positive or negative. Addition, subtraction, multiplication, and
division will all wrap around. The computer just cares about the
pattern of bits, and applies the circuitry to it.&lt;/p&gt;
&lt;p&gt;Of course, if we want to display the number to the user, it
matters. We don&amp;rsquo;t want the user to enter -1 and the computer
to randomly display 15 later (or 255 for 8-bit, or 65535 for
16-bit, or 4294967295 for 32-bit). Somehow, we need some
mechanism of deciding when we want to interpret the number as
-1, and when we want to interpret it as 15.&lt;/p&gt;
&lt;p&gt;Similary, comparisons. -1 is less than 1. 15 is greater than 1.
Sign matters. Where does it wrap around? For what N is N + 1 &amp;lt; N?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s an arbitrary cut off. And there&amp;rsquo;s two conventions.&lt;/p&gt;
&lt;p&gt;For one of the conventions, &lt;strong&gt;unsigned&lt;/strong&gt; integers, well, it&amp;rsquo;s always
positive. The N for which N + 1 &amp;lt; N is 15 (for 4 bit arithmetic), as 15 +
1 wraps around to 0. 15 &amp;gt; 1. 0 &amp;lt; 1. Subtract 0 - 1 and display it? You
get 15.&lt;/p&gt;
&lt;p&gt;The following program displays 15:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;
#include &amp;lt;stdio.h&amp;gt;

int main() {
    struct {
        unsigned four_bits: 4;
    } bitfield;
    bitfield.four_bits = 0; // Starts out with 0000
    bitfield.four_bits -= 1; // Modify field by subtracting 1
    printf(&amp;#34;%u\n&amp;#34;, bitfield.four_bits); // Display on screen
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See the word &lt;code&gt;unsigned&lt;/code&gt; there in the declaration of &lt;code&gt;four_bits&lt;/code&gt;?
That&amp;rsquo;s the unsigned convention for arithmetic.&lt;/p&gt;
&lt;p&gt;Well, the opposite of that is &lt;strong&gt;signed&lt;/strong&gt; integers. For these,
the numbers that are interpreted as negative are the numbers
for which the highest-order bit is a 1. The cut-off N,
for which N + 1 &amp;lt; N, is 7. 7 + 1 = -8. 7 + 1 &amp;lt; 7.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s our original table with the standard signed interpretations
left in:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Bit Pattern | As Positive | As Negative
0000        | 0           |
0001        | 1           |
0010        | 2           |
0011        | 3           |
0100        | 4           |
0101        | 5           |
0110        | 6           |
0111        | 7           |
1000        |             | -8
1001        |             | -7
1010        |             | -6
1011        |             | -5
1100        |             | -4
1101        |             | -3
1110        |             | -2
1111        |             | -1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For another way of looking at it, remember we discussed
that these bits were coefficients to powers of two.
0101 is 5 because it&amp;rsquo;s &lt;code&gt;0 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 2^0&lt;/code&gt;.
It has 1s in the 4s place and the 1s place, so it has 1 4, and 1
1, and nothing else.&lt;/p&gt;
&lt;p&gt;Well, what if instead of that higher-order bit being the 8s place,
it were the -8s place? The other bits remain positive in value.
8 and -8 are equivalent modulo 16, so this doesn&amp;rsquo;t actually
change the meaning of the bit in the modular sense. But it does
change the meaning of the &lt;code&gt;&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;&lt;/code&gt; operations.&lt;/p&gt;
&lt;p&gt;0101 is still 5, but it&amp;rsquo;s &lt;code&gt;0 * (-8) + 1 * 4 + 0 * 2 + 1 * 1&lt;/code&gt; now.
And 1111 is -1, because it&amp;rsquo;s &lt;code&gt;1 * (-8) + 1 * 4 + 1 * 2 + 1 * 1&lt;/code&gt;,
or &lt;code&gt;-8 + 4 + 2 + 1&lt;/code&gt; or &lt;code&gt;-8 + 7 &lt;/code&gt; or &lt;code&gt;-1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not making this needlessly complicated! If it is needlessly
complicated, it&amp;rsquo;s not me who&amp;rsquo;s making it that way!  This is how computers
actually work, because it makes sense that way, from a circuitry design
perspective and from an engineering perspective.&lt;/p&gt;
&lt;p&gt;OK, now for some fun facts!&lt;/p&gt;
&lt;p&gt;This way of storing signed integers in computers is known as &lt;em&gt;two&amp;rsquo;s
complement&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Two&amp;rsquo;s complement negation can be computed by inverting all the bits
and adding 1. This is opposed to 1&amp;rsquo;s complement, where we negate by
inverting all the bits, and the circuitry is annoying and stupid. It
is also opposed to sign/magnitude, where the top bit indicates sign by
negating the whole rest of the number if it is 1, rather than subtracting
a value (e.g. 8 in 4-bit integers, or 128 in 8-bits).&lt;/p&gt;
&lt;p&gt;Almost all computers use two&amp;rsquo;s complement to store integers these
days, for all the reasons discussed above. For non-integers, all
bets are off, but sign-magnitude is popular for floating point
numbers overall.&lt;/p&gt;
&lt;p&gt;In two&amp;rsquo;s complement, -1 is always represented as all bits 1. Why? Well,
for the same reason 10,000 - 1 is 9,999, and 100,000 - 1 is 99,999.&lt;/p&gt;
&lt;p&gt;In fact, if we start by 1 followed by many zeros in any base, and
we subtract 1, then we get the maximum digit of that base repeated.
If we&amp;rsquo;re in base 8, &lt;code&gt;1000 - 1 = 777&lt;/code&gt;. If in base 16, then &lt;code&gt;100 - 1 = FF&lt;/code&gt;
(in base 16, it is conventional to use the letters A-F to represent the
digits for 10-15).&lt;/p&gt;
&lt;p&gt;Why is this? Well, doing the subtraction out, right to left, we start
with &lt;code&gt;10-1&lt;/code&gt;, with a borrowed &lt;code&gt;1&lt;/code&gt;. The value one less than the base is
the greatest digit of that base: 1 less than 10 is 9. Then, to get that
borrowed &lt;code&gt;1&lt;/code&gt;, we must go to the next digit to the left, and subtract that
&lt;code&gt;1&lt;/code&gt;. But that digit is also a &lt;code&gt;0&lt;/code&gt;, so we must borrow a &lt;code&gt;1&lt;/code&gt; even further
out, so we get &lt;code&gt;10-1&lt;/code&gt; again. This continues until we get an actual &lt;code&gt;1&lt;/code&gt;
and can no longer borrow.&lt;/p&gt;
&lt;p&gt;Of course, when subtracting from 0 in a computer context, you can
always borrow past the left-hand side. 0000 and 10000 are the same
bottom four bits; they are congruent modulo 16. Borrowing a 1 from
off the end is always an option.&lt;/p&gt;
&lt;p&gt;Or, considered another way, if you add binary 1 to 1111, you will
get 10000, for the same reason that if you add 1 to 9,999, you will
get 10,000. That last bit falls off the end, though, so 1111 is just
-1, because 1111 + 1 = 0.&lt;/p&gt;
&lt;p&gt;This also means that to negate a number N, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Invert all the bits. This gives you -1 - N.&lt;/li&gt;
&lt;li&gt;Add 1. This gives you -N.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s do this one step at a time.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Invert all the bits. This gives you -1 - N.&lt;/strong&gt; Let&amp;rsquo;s figure out how to
do -1 - N, and we&amp;rsquo;ll see it works out to inverting all the bits. So, -1
has all bits 1, so no bit will need to be borrowed. If you subtract a 1
(from the N) from the 1 (from -1), it becomes a 0. If you subtract a 0
(from the N) from the 1 (from the -1), it becomes a 1.&lt;/p&gt;
&lt;p&gt;Okay, perhaps it&amp;rsquo;s better to demonstrate visually. This is
-1-5, as a subtraction problem in binary:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;  1111    (-1 aka 15)
- 0101    ( 5)
  ----
  1010    (-6 aka 10)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;By subtracting &lt;code&gt;1111 - 0101&lt;/code&gt;, we got &lt;code&gt;1010&lt;/code&gt;, the bit-inversion of
&lt;code&gt;0101&lt;/code&gt;. Said another way, by inverting all the bits in &lt;code&gt;0101&lt;/code&gt;,
we got &lt;code&gt;1111 - 0101&lt;/code&gt;. Said another way, by inverting all the bits
in 5, we got -6.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add 1. This gives you -N.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And that is what computers do with signed integers when you
have an integer &lt;code&gt;n&lt;/code&gt; and write &lt;code&gt;let negate_n = -n;&lt;/code&gt; &amp;ndash; the computer
provides circuitry internally that lets you invert all the
bits and then add one.&lt;/p&gt;
&lt;p&gt;So, now we know how to represent numbers as signed and unsigned.
But we also treat them as equivalent. That&amp;rsquo;s confusing. So
what&amp;rsquo;s up with that?&lt;/p&gt;
&lt;p&gt;For some operations, this representation makes it so you don&amp;rsquo;t
need to care about signed and unsigned. These include &lt;strong&gt;addition&lt;/strong&gt;,
&lt;strong&gt;subtraction&lt;/strong&gt;, and &lt;strong&gt;multiplication&lt;/strong&gt;. As long as you assume that
wrapping-around doesn&amp;rsquo;t happen (which is the faster, more efficient
implementation in circuitry), these operations literally do the same
thing in signed and unsigned.  One person&amp;rsquo;s overflow is another person&amp;rsquo;s
subtraction, but as long as we&amp;rsquo;re OK with overflow, subtraction is
cool too.&lt;/p&gt;
&lt;p&gt;Ironically, negation goes in this category. It doesn&amp;rsquo;t need to care which
numbers you interpret as positive or negative to give you a number -N
that, when you add it, undoes the effect of adding N.&lt;/p&gt;
&lt;p&gt;However, if you want to do &lt;strong&gt;checked&lt;/strong&gt; versions of addition, subtraction,
and multiplication, where the program notices when adding two positive
numbers results in a number smaller than both, and causes a &lt;em&gt;trap&lt;/em&gt;, a
stop in the program&amp;rsquo;s normal behavior, &amp;ldquo;an error message or something,&amp;rdquo;
then how that check works differs in signed and unsigned.&lt;/p&gt;
&lt;p&gt;This check would involve a version of the addition operation that actually
used the carry output from the last bit. But there&amp;rsquo;s two interpretations
of that. Should -1 + 1 trigger?  In unsigned arithmetic, where it&amp;rsquo;s
actually 15 + 1 (or 255 + 1, or 65,535 + 1), it probably should, because
wrapping around to 0 is a trap. But in signed arithmetic, -1 + 1 is not
an overflow at all.&lt;/p&gt;
&lt;p&gt;So, in unsigned arithmetic, the normal carry output of the leftmost
(most significant) adder circuit can be used. Given the leftmost
input bit of the first argument, the leftmost input bit of the second
argument, and the carry from the next adder circuit to the right (the
second-most-significant bit, if you will), if 2 or more of those
bits are 1, well, then, signal an overflow.&lt;/p&gt;
&lt;p&gt;For signed arithmetic, it&amp;rsquo;s about how the sign bits line up in the
input and the output.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Fun aside:&lt;/strong&gt; The &lt;em&gt;sign bit&lt;/em&gt; is another name in two&amp;rsquo;s complement
for the most significant bit, as it is 1 if and only if the number
is negative. Some overzealous teachers will say it&amp;rsquo;s not a sign bit
because its significance can be ignored in many operations, but that&amp;rsquo;s
even more obnoxiously pedantic than saying that there&amp;rsquo;s no such thing as
&lt;a href=&#34;https://xkcd.com/123/&#34;&gt;centrifugal force&lt;/a&gt;, and more inaccurate.
Every processor designer (including Intel and ARM) refer to this
bit as the sign bit, which makes sense because it tells you what
sign the number is.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the two input sign bits are the same in an addition, and the result
bit is different, then you have a signed overflow. For example,
&lt;code&gt;1111+1111=1110&lt;/code&gt; is fine, as that&amp;rsquo;s &lt;code&gt;-1 + -1 = -2&lt;/code&gt;.  Similarly,
&lt;code&gt;1111+0010=0001&lt;/code&gt; is fine, as that&amp;rsquo;s &lt;code&gt;-1 + 2 = 1&lt;/code&gt;.  But &lt;code&gt;1000+1000=0000&lt;/code&gt;
is weird, as that&amp;rsquo;s &lt;code&gt;-8 + -8 = 0&lt;/code&gt;.  The two input sign bits are both 1
in an addition, and the output sign bit is 1 &amp;ndash; suspicious.&lt;/p&gt;
&lt;p&gt;So the situation where unsigned integers wrap around in defiance
of normal integer math is known as &amp;ldquo;carry&amp;rdquo; on Intel, and is indicated
by a &amp;ldquo;carry flag,&amp;rdquo; which can be checked to output an error
message or something. Similarly, the situation where signed
integers wrap around is known on Intel as &amp;ldquo;overflow,&amp;rdquo; which is
indicated by an overflow flag.&lt;/p&gt;
&lt;p&gt;The other flag is always meaningless. Which flags you check on Intel
is an indication of whether you are doing unsigned or signed (i.e.
two&amp;rsquo;s complement) arithmetic. And, since operations like less than
and greater than are also implemented on Intel by checking flags,
literally the only difference on Intel between signed and unsigned
arithmetic is what flags you check.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Fun fact:&lt;/strong&gt; Comparisons on Intel are done by the &lt;code&gt;cmp&lt;/code&gt;
instruction, which does a subtraction, throws away the result,
and sets the flags accordingly. The flags can then be inspected
to determine which input was greater or less, or less-or-equal
or greater-or-equal, with either signed or unsigned semantics.
All the same flags are set with a normal subtraction.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By the way, every time you add or subtract on Intel, both carry
and overflow flags are set accordingly. It&amp;rsquo;s easier in circuitry
to just do both, the operations are so similar.&lt;/p&gt;
&lt;p&gt;You can read more on Intel&amp;rsquo;s flags
&lt;a href=&#34;http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;Collections of bits can be used to store integers, using base 2.
Addition, subtraction, and multiplication are implemented in such a
way that wraps around, and any number can have a positive or negative
interpretation. This weird type of math is called &lt;em&gt;modular arithmetic&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If we interpret all the numbers as positive, then we are doing unsigned
arithmetic. Programming languages represent this by referring to unsigned
integers, but to the processor, they&amp;rsquo;re all just integers. The question is
just what kind of arithmetic we&amp;rsquo;ll do. With this interpretation, adding
two numbers and getting a smaller one is &lt;em&gt;overflow&lt;/em&gt;, and subtracting
from a number and making it bigger is called &lt;em&gt;underflow&lt;/em&gt;. This may or
may not be detected, but if it is, it is done on Intel by checking the
&lt;em&gt;carry flag&lt;/em&gt;. Besides that, it will happily do the arithmetic in a modular
way. Less than and greater than are also evaluated via the carry bit.&lt;/p&gt;
&lt;p&gt;If we interpret some of the numbers as negative, it&amp;rsquo;s based on the
top-most bit, the sign bit. This is known as signed arithmetic, and
programming languages will use this for signed integers. Numbers are
still interpreted based on their negative meaning in modular arithmetic.
In this interpretation, adding two negative numbers and getting a
positive, or adding two positive numbers and getting a negative,
is known as &lt;em&gt;overflow&lt;/em&gt;, and it shows up in the &lt;em&gt;overflow flag&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In either case, Intel processors perform addition, subtraction,
multiplication, and negation the exact same way for signed and unsigned
arithmetic. The only difference is the flag, and Intel will always do
the work to set or clear both flags appropriately. To distinguish
between signed and unsigned arithmetic, programming languages check
the specific flag they&amp;rsquo;re interested in for appropriate operations,
like less than and greater than operations.&lt;/p&gt;
&lt;p&gt;Two&amp;rsquo;s complement is not to be confused with &amp;ldquo;twos compliment&amp;rdquo; (drawing
by my friend Ilse Purrenhage):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/twos_compliment.png&#34; alt=&#34;Twos Compliment&#34;&gt;&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;This word is relative.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
      <title>Sorting Polymorphically in Many Languages</title>
      <link href="https://www.thecodedmessage.com/posts/polymorphism-many-languages/" />
      <id>https://www.thecodedmessage.com/posts/polymorphism-many-languages/</id>
      <updated>2024-02-05T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Polymorphism is a powerful programming language feature. In polymorphism,
we have generic functions that don&amp;rsquo;t know exactly what type of data
they will be operating on. Often, the data types won&amp;rsquo;t even all have been
designed yet when the generic function is written. The generic function
provides the general outline of the work, but the details of some parts of
the work, some specific operations, must be tailored to the specific
types being used. The generic code needs some way of accessing these
specific operations, and the users of the generic code need some way
of specifying them.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Polymorphism is a powerful programming language feature. In polymorphism,
we have generic functions that don&amp;rsquo;t know exactly what type of data
they will be operating on. Often, the data types won&amp;rsquo;t even all have been
designed yet when the generic function is written. The generic function
provides the general outline of the work, but the details of some parts of
the work, some specific operations, must be tailored to the specific
types being used. The generic code needs some way of accessing these
specific operations, and the users of the generic code need some way
of specifying them.&lt;/p&gt;
&lt;p&gt;There are many use cases for polymorphism. When sorting an array,
the algorithm will need to be adapted to the specific element type,
so it knows how to compare elements. When drawing virtual objects on
a screen, an algorithm might choose where to put each object and which
objects to draw, whereas each type of object might have its own specialized
implementation of how to draw it.&lt;/p&gt;
&lt;p&gt;These are just two examples among many. Most complicated projects
have many polymorphic functions. Even in languages that don&amp;rsquo;t support
polymorphism directly, there are usually ways of building it out of
existing primitives.&lt;/p&gt;
&lt;p&gt;The example I&amp;rsquo;ve chosen is sorting, specifically sorting an array
or vector. It&amp;rsquo;s just an example; a lot of what I say applies generally
to how polymorphism works in that programming language.&lt;/p&gt;
&lt;p&gt;This is a good example, as sorting is a function where it&amp;rsquo;s really
obvious where polymorphism is required to get a properly generalizable
algorithm. A lot of discussions of polymorphism invent contrived
situations where polymorphism seems overkill, and I think that&amp;rsquo;s
fundamentally confusing.&lt;/p&gt;
&lt;p&gt;On the other hand, it&amp;rsquo;s a bad example in some ways, because it only makes
sense in the context of a homogeneous array or list, where every element
is the same type. This is a bad example because heterogeneous containers,
where every element has a different type and the polymorphic function
has to look up as many function implementations as there are elements,
provides a very different set of problems to solve.&lt;/p&gt;
&lt;p&gt;This is especially important as Rust and C++ both provide two types of
polymorphism, compile-time and run-time, also known as static and dynamic.
The question of which to use is complicated, but for sorting, compile-time
or static polymorphism is clearly the appropriate choice, with run-time
or dynamic polymorphism feeling very awkward and forced. Heterogeneous
containers generally must use some form of dynamic polymorphism (whether
through virtual functions in C++ or through type erasure).&lt;/p&gt;
&lt;p&gt;So, while I think this example will be illustrative, it won&amp;rsquo;t allow us
to explore run-time, dynamic polymorphism on its home turf, if you will.
Hopefully, I can make up this deficit in future blog posts.&lt;/p&gt;
&lt;h1 id=&#34;sorting-a-polymorphic-function&#34;&gt;Sorting: A Polymorphic Function&lt;/h1&gt;
&lt;p&gt;Sorting algorithms are a true use case for polymorphism: rather than
distinguishing between a small set of options, many types support
the operations necessary for sorting. The algorithm is agnostic to the
implementation of those operations. Quick sort, insertion sort, and merge
sort apply equally well to sorting integers, floating point values,
or alphabetizing strings &amp;ndash; any algorithm can be combined freely with
any type, or at least any type for which a concept of &amp;ldquo;ordering&amp;rdquo; exists.&lt;/p&gt;
&lt;p&gt;Here are the operations or properties (or dare I say, &lt;em&gt;traits&lt;/em&gt;) that a
type needs to be sortable, and that a generic sorting algorithm might
need to find out about. The first one is obvious to OOP programmers, but
the other two more subtle, and implied in many OOP programming languages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ordering&lt;/strong&gt; or &lt;strong&gt;comparison&lt;/strong&gt;: Given two values &lt;em&gt;a&lt;/em&gt; and &lt;em&gt;b&lt;/em&gt;,
this operation answers which is greater, or determines that they
are equal. Some types have the additional possibility that they are
incomparable &amp;ndash; arrays of those types cannot be sorted by most algorithms.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Swapping&lt;/strong&gt; or &lt;strong&gt;moving&lt;/strong&gt;: The data has to be able to be moved around
to turn the unsorted array into a sorted one. This is automatic in many
OOP languages for object types due to ubiquitous use of indirection. It
is also automatic in Rust, where every type can be moved by just
copying all the bytes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Striding the array&lt;/strong&gt; or &lt;strong&gt;size&lt;/strong&gt;: Given a pointer to one element,
how do you get to the next one? By how many bytes must you increment the
pointer? Most sorting algorithms require this to be constant. If you
use indirection for the values, this is also trivial. If you do not,
it is key information.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These operations &amp;ndash; or more generally, &lt;em&gt;traits&lt;/em&gt; of a type &amp;ndash; can then be
combined with a sorting algorithm to create a concrete procedure to
sort an array for a given concrete type.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s see how various programming languages handle this.&lt;/p&gt;
&lt;h1 id=&#34;programming-language-0-sorting-in-c&#34;&gt;Programming Language #0: Sorting in C&lt;/h1&gt;
&lt;p&gt;I will start our tour of programming languages with C. C &amp;ndash; the non-OOP,
non-C++ programming language; the classic &amp;ldquo;portable assembly language&amp;rdquo;
from 1972 &amp;ndash; doesn&amp;rsquo;t have many polymorphic algorithms, algorithms that
accept any type, because you have to implement polymorphism by hand. But
sorting is an important enough one that standard C does have a generic
sorting function: &lt;code&gt;qsort&lt;/code&gt; for quicksort (and on many systems, &lt;code&gt;heapsort&lt;/code&gt;
and mergesort` are also avaialble). Because polymorphism is implemented
by hand, we can look at this function to see how one might specifically
tailor polymorphism to the problem of sorting.&lt;/p&gt;
&lt;p&gt;Here is the function signature for &lt;code&gt;qsort&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;qsort&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;base, &lt;span style=&#34;color:#66d9ef&#34;&gt;size_t&lt;/span&gt; nmemb, &lt;span style=&#34;color:#66d9ef&#34;&gt;size_t&lt;/span&gt; size,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;compar)(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It can be used to sort blocks of memory containing a sequence of integers,
foating point values, or (pointers to) strings &amp;ndash; any comparable and
(trivially) movable fixed-size type.&lt;/p&gt;
&lt;p&gt;C function signatures can be hard to read, so I&amp;rsquo;ll break it down
argument by argument:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;void *base&lt;/code&gt;: This is an untyped pointer (&lt;code&gt;void *&lt;/code&gt;) to the beginning
of the block of memory to be sorted.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;size_t nmemb&lt;/code&gt;: This is a bound, how much memory is contained in
the block of memory. C often represents aggregates by two values,
base and a count of the members.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;size_t size&lt;/code&gt;: How big is each member? On a typical 64-bit system, an
&lt;code&gt;int&lt;/code&gt; is 4 bytes, a &lt;code&gt;double&lt;/code&gt; is 8, and &lt;code&gt;char *&lt;/code&gt; for strings are 8 bytes.
Custom types might be any size. &lt;code&gt;qsort&lt;/code&gt; should work for all of these
types, without indirection.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int (*compar)(const void *, const void *)&lt;/code&gt;: This is the interesting
part. This is a function pointer for the comparison operation as
discussed above. You write a function that takes two pointers to
two elements, and returns a value that encodes their relationship.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Swapping is assumed to be byte-by-byte, and so &lt;code&gt;size&lt;/code&gt; covers the
last two attributes of the type listed above. The key one here
is &lt;code&gt;compar&lt;/code&gt;, a bit of code that &lt;code&gt;qsort&lt;/code&gt; has to call to do an
operation specific to your type, a small policy injection that
adapts a generic algorithm to your particular type.&lt;/p&gt;
&lt;p&gt;The return value of &lt;code&gt;compar&lt;/code&gt; is an &lt;code&gt;int&lt;/code&gt;, but it is interpreted according
to a C convention, shared with (for example) the string comparison
function &lt;code&gt;strcmp&lt;/code&gt;. For &lt;code&gt;a ? b&lt;/code&gt;, a return value &lt;code&gt;r&lt;/code&gt; is interpreted thus:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if &lt;code&gt;r &amp;lt; 0&lt;/code&gt;, &lt;code&gt;a &amp;lt; b&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;r &amp;gt; 0&lt;/code&gt;, &lt;code&gt;a &amp;gt; b&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if &lt;code&gt;r == 0&lt;/code&gt;, &lt;code&gt;a == b&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, here&amp;rsquo;s a complete C program that sorts its command line arguments &amp;ndash;
including the program name:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;compare_strings&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;a, &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// `a` and `b` are pointers to the element type, which in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// this case is `char *`. Thus they are `char **`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Nothing is stopping you from getting this wrong and putting
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// `char *` instead -- it will just silently not work. The
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// compiler can and will make you write `const` in the right
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// place, though.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; a_str_ptr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; a;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; b_str_ptr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// `strcmp` uses the same convention as `qsort` for comparison.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;strcmp&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;a_str_ptr, &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;b_str_ptr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; argc, &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;argv) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;qsort&lt;/span&gt;(argv, argc, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;), &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;compare_strings);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; argc; i&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%s&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, argv[i]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But the same &lt;code&gt;qsort&lt;/code&gt; function can also be used to sort integers, if given
different parameters and a different comparison function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;compare_ints&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;a_vp, &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;b_vp) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;a_ip &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; a_vp;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;b_ip &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; b_vp;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;a_ip;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; b &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;b_ip;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (a &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (a &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#75715e&#34;&gt;// a &amp;gt; b
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; argc, &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;**&lt;/span&gt;argv) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; intary[&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; { &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;9&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;qsort&lt;/span&gt;(intary, &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;), &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;compare_ints);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;; i&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%d&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, intary[i]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;qsort&lt;/code&gt; implements a form of manual run-time polymorphism, in a
programming language with no built-in support for polymorphism.
It behaves differently based on the element type, as passed to it via a
variety of arguments. One of the traits &amp;ndash; the comparison operator &amp;ndash;
differs between types in a way that requires custom code, and this is
passed in via pointer. &lt;code&gt;qsort&lt;/code&gt; then invokes the operation via indirect
function call, the same mechanism that is used for polymorphism
in OOP. But unlike OOP-style runtime polymorphism, there is just one
function pointer for all the items, rather than each item coming with
its own &amp;ldquo;vtable.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Note that the optimizer is not able to eliminate this indirect call,
especially in the &lt;code&gt;qsort&lt;/code&gt; example, where the sorting function is in the
standard library, whereas the function calling it and the comparison
function are both in application code. This comes at a performance cost,
which means that if you&amp;rsquo;re programming C and the performance of this
particular sort is essential to your program, it might easily make sense
to write custom sorting code that is not polymorphic.&lt;/p&gt;
&lt;h1 id=&#34;programming-language-1-sorting-in-java&#34;&gt;Programming Language #1: Sorting in Java&lt;/h1&gt;
&lt;p&gt;Java is about as far from C as you can get in this matter.  C provides no
abstraction or language features specifically for polymorphism, and in
&lt;code&gt;qsort&lt;/code&gt; we use a low-level tool it does provide &amp;ndash; function pointers &amp;ndash;
to build it ourselves.  In Java, however, the programming language is
explicitly object-oriented, and so the whole programming language is
designed to encourage you to leverage polymorphism, as that is one of
the pillars of object-oriented programming.&lt;/p&gt;
&lt;p&gt;The version of polymorphism available in Java is dynamic, run-time,
&amp;ldquo;late binding&amp;rdquo; polymorphism, the type of polymorphism that OOP favors.
It is based off of the idea of overriding methods, either from base
classes, or interfaces that a custom type (a &amp;ldquo;class&amp;rdquo;) can implement.&lt;/p&gt;
&lt;p&gt;As I mentioned before, this is not the best match for the problem of
sorting, at least not the type of sorting we&amp;rsquo;re talking about. Run-time
polymorphism means that every individual element could potentially have
a different comparison procedure, which is unlikely. The possibility
of such a thing happen increases the cognitive load.&lt;/p&gt;
&lt;p&gt;Nevertheless, Java does support polymorphic sorting, and it&amp;rsquo;s useful
to discuss specifically because it does show how OOP-style polymorphism
works when applied to such a problem.&lt;/p&gt;
&lt;p&gt;There are many methods that do sorting in Java. &lt;a href=&#34;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Arrays.html#sort%28java.lang.Object%5B%5D,java.util.Comparator%29&#34;&gt;Some of
them&lt;/a&gt;
take an explicit argument to convey how to do comparisons, just like the
&lt;code&gt;qsort&lt;/code&gt; example.  But more commonly, we sort according to what Java refers
to as the &amp;ldquo;natural order&amp;rdquo; of the elements, as (for example) in
&lt;a href=&#34;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Collections.html#sort%28java.util.List%29&#34;&gt;this overload&lt;/a&gt;
of &lt;code&gt;Collections.sort&lt;/code&gt;, with the following signature:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; Comparable&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;super&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; list)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This sorts a list of elements of type &lt;code&gt;T&lt;/code&gt;, where &amp;ldquo;list&amp;rdquo; in Java can refer
to any of a number of collections that store data in order, such as in
a single allocated array (&lt;code&gt;ArrayList&lt;/code&gt;) or a linked list (&lt;code&gt;LinkedList&lt;/code&gt;).
Therefore, it is not only polymorphic in how to compare the elements,
but also in how to navigate through the list.&lt;/p&gt;
&lt;p&gt;It needs to know about the same traits of type &lt;code&gt;T&lt;/code&gt; that &lt;code&gt;qsort&lt;/code&gt; does.
Some are not polymorphic: for this method to make sense, we know that
&lt;code&gt;T&lt;/code&gt; must be a reference type, that it must be boxed (that is, it must
use indirection), and that therefore the size of an element is always
the natural pointer size of the platform, and swapping the element only
involves swapping the pointers.&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s no getting around the polymorphism of comparisons, and so
we see this strange annotation on the function signature: &lt;code&gt;&amp;lt;T extends Comparable&amp;lt;? super T&amp;gt;&amp;gt;&lt;/code&gt;. This indicates that &lt;code&gt;T&lt;/code&gt; must implement
the interface &lt;code&gt;Comparable&lt;/code&gt; &amp;ndash; implement in this context is called
&lt;code&gt;extends&lt;/code&gt;. Specifically, it must implement that interface in such a way
that it can be applied to other elements of type &lt;code&gt;T&lt;/code&gt; (which means that
it uses &lt;code&gt;T&lt;/code&gt; or some &amp;ldquo;supertype&amp;rdquo; of &lt;code&gt;T&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The notation is complicated, because the semantics are complicated.
Technically, &lt;code&gt;T&lt;/code&gt; could be comparable to a parent type of &lt;code&gt;T&lt;/code&gt;, and that
would still work. In fact, &lt;code&gt;T&lt;/code&gt; could refer to an entire class hierarchy
of types derived from some base class, all of them comparable in different
ways to objects elsewhere in the hierarchy and to objects derived from
a yet further base class. Objects of type &lt;code&gt;T&lt;/code&gt; could even be comparable
to any arbitrary object &amp;ndash; and all of this is covered in
&lt;code&gt;&amp;lt;T extends Comparable&amp;lt;? superT&amp;gt;&amp;gt;&lt;/code&gt;, trying to express at compile-time
what will cause the type &lt;code&gt;T&lt;/code&gt; to be a reasonable type to use for sorting.&lt;/p&gt;
&lt;p&gt;But this is all just an extra check that the compiler can do at
compile-time to prevent run-time errors, because all of the information
on how to do the comparisons is available at run-time.  In fact, &lt;a href=&#34;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Arrays.html#sort%28java.lang.Object%5B%5D%29&#34;&gt;other
methods&lt;/a&gt;
don&amp;rsquo;t use such formal prerequisites at all, preferring
to query at run-time for appropriate interfaces, throwing
an exception if they are not present.&lt;/p&gt;
&lt;p&gt;In all of these cases, the comparison is the &amp;ldquo;natural
ordering,&amp;rdquo; which is defined to mean that comparison is
done through a Java interface. Specifically, these methods use the
&lt;a href=&#34;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Comparable.html&#34;&gt;&lt;code&gt;Comparable&lt;/code&gt;&lt;/a&gt;
interface, which specifies a method, &lt;code&gt;compareTo&lt;/code&gt;, which must take an
implicit &lt;code&gt;this&lt;/code&gt; parameter and an explicit parameter of the type being
compared to, and, like the comparison functions in &lt;code&gt;qsort&lt;/code&gt;, must then
return an integer whose sign indicates whether the first value was
greater or the second (with zero indicating equality).&lt;/p&gt;
&lt;p&gt;This natural ordering is defined on a per-type basis. Each type can
only implement &lt;code&gt;Comparable&lt;/code&gt; once. Fortunately, the regular built-in
types, all the ones we are likely to use, all come with good natural
orderings. For example, this code all works:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; java.util.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Sort&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(String&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; argList &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Arrays.&lt;span style=&#34;color:#a6e22e&#34;&gt;asList&lt;/span&gt;(args);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Collections.&lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(argList);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (String arg : argList) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            System.&lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;println&lt;/span&gt;(arg);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Integer&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; list &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ArrayList&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Integer&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(3);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(2);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(4);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Collections.&lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(list);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i : list) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            System.&lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;println&lt;/span&gt;(i);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See it in use:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ java Sort b c a
a
b
c
1
2
3
4
$
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It gets a little less coherent when we mix different types of object
in the same list, which Java lets us represent in the type system
by using &lt;code&gt;Object&lt;/code&gt;, which is a type that can store a reference to any
non-primitive (including boxed primitives):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; java.util.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Sort&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(String&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Object&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; list &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ArrayList&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Object&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Collections.&lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(list);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (Object i : list) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            System.&lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;println&lt;/span&gt;(i);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While the Java runtime allows us to create such a collection, the
type system does not allow us to use &lt;code&gt;Collections.sort&lt;/code&gt; to sort it,
as &lt;code&gt;Object&lt;/code&gt; does not provide us enough information to make sure these
elements properly can be compared to each other (which in fact, they
cannot, as comparing strings to integers is not defined in Java&amp;rsquo;s
&amp;ldquo;natural ordering&amp;rdquo;):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ javac Sort.java
Sort.java:9: error: no suitable method found for sort(List&amp;lt;Object&amp;gt;)
        Collections.sort(list);
                   ^
    method Collections.&amp;lt;T#1&amp;gt;sort(List&amp;lt;T#1&amp;gt;) is not applicable
      (inference variable T#1 has incompatible bounds
        equality constraints: Object
        lower bounds: Comparable&amp;lt;? super T#1&amp;gt;)
    method Collections.&amp;lt;T#2&amp;gt;sort(List&amp;lt;T#2&amp;gt;,Comparator&amp;lt;? super T#2&amp;gt;) is not applicable
      (cannot infer type-variable(s) T#2
        (actual and formal argument lists differ in length))
  where T#1,T#2 are type-variables:
    T#1 extends Comparable&amp;lt;? super T#1&amp;gt; declared in method &amp;lt;T#1&amp;gt;sort(List&amp;lt;T#1&amp;gt;)
    T#2 extends Object declared in method &amp;lt;T#2&amp;gt;sort(List&amp;lt;T#2&amp;gt;,Comparator&amp;lt;? super T#2&amp;gt;)
1 error
$
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So how does this work? What is a Java interface? What are its advantages
or disadvantages?&lt;/p&gt;
&lt;p&gt;Well, Java has two types of values: primitives on the one hand, and
object references on the other. In order to use interfaces, or polymorphism
at all, we must be dealing with objects. For primitives, there are separate
methods for sorting various types of arrays in the &lt;code&gt;Arrays&lt;/code&gt; class. As
primitives cannot be stored directly in collections, &lt;code&gt;Collections&lt;/code&gt;
doesn&amp;rsquo;t have to deal with them.&lt;/p&gt;
&lt;p&gt;So, to use this polymorphism through interfaces, we must be dealing with
objects. Objects in Java are a rich, standardized data structure, which
is why it&amp;rsquo;s possible to query at run-time which interfaces an object
supports. Objects contain not just the fields that the Java programmer
specifies, but additional metadata that includes implementations of
any supported interfaces, including &lt;code&gt;Comparable&lt;/code&gt;. That metadata can be
used to find the right version of the &lt;code&gt;compareTo&lt;/code&gt; method to use to sort
objects of type &lt;code&gt;T&lt;/code&gt;. Once we have a &lt;code&gt;T&lt;/code&gt;, we can query it at run-time
to find the &lt;code&gt;compareTo&lt;/code&gt; method. Theoretically, Java might query every
object separately as it sorts, with a separate query for each comparison,
although I trust that modern Java will in many cases realize that the
method will be the same for each object, and figure out a way to optimize
it out.&lt;/p&gt;
&lt;p&gt;As a programmer of a type, we simply declare at the top of the class that
our type &lt;code&gt;Foo&lt;/code&gt;, for example, &lt;code&gt;implements Comparable&amp;lt;Foo&amp;gt;&lt;/code&gt;, and then lower
down include our implementation of &lt;code&gt;compareTo&lt;/code&gt; among our methods with the
&lt;code&gt;override&lt;/code&gt; keyword. Based on that, &lt;code&gt;Foo&lt;/code&gt; objects will be created with
the correct metadata such that Java will know to use that method for
comparison when sorting, whether the type is known at compile-time
or at run-time. We can implement our own version of &lt;code&gt;compareTo&lt;/code&gt;
that has a different type than the typical &amp;ldquo;natural ordering&amp;rdquo; one
would expect from the state that is contained in a &lt;code&gt;Foo&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; java.util.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Sort&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; Comparable&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Foo&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; inner;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; inner) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;inner&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; inner;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;@Override&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;compareTo&lt;/span&gt;(Foo foo) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// Less and greater are swapped by this compared to int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// comparison&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (foo.&lt;span style=&#34;color:#a6e22e&#34;&gt;inner&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;inner&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (foo.&lt;span style=&#34;color:#a6e22e&#34;&gt;inner&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;inner&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; String &lt;span style=&#34;color:#a6e22e&#34;&gt;toString&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; inner;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(String&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Foo&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; list &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ArrayList&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Foo&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Foo(3));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Foo(4));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Foo(1));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        list.&lt;span style=&#34;color:#a6e22e&#34;&gt;add&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Foo(2));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Collections.&lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(list);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (Object i : list) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            System.&lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;println&lt;/span&gt;(i);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here is the output:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ java Sort
4
3
2
1
$
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Built-in types such as &lt;code&gt;String&lt;/code&gt; and &lt;code&gt;Integer&lt;/code&gt; already provide
their own &lt;code&gt;compareTo&lt;/code&gt; override methods, corresponding to more
typical implementations of comparisons. Only the author of each
type can provide information on how the types are to be compared
in this way. To get around this, you can use a wrapper type for
each element (like &lt;code&gt;Foo&lt;/code&gt;), or you have to fall back on passing in
the comparison function the old-fashioned way, like in &lt;code&gt;qsort&lt;/code&gt; &amp;ndash;
though in Java passing in a function is accomplished here through
yet another interface, &lt;code&gt;Comparator&lt;/code&gt;, as in &lt;a href=&#34;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Collections.html#sort%28java.util.List,java.util.Comparator%29&#34;&gt;this alternative
function&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; list,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                            Comparator&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;super&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; c)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here, &lt;code&gt;Comparator&lt;/code&gt; is effectively a function pointer with context, but
it&amp;rsquo;s expressed as an interface so that you can write a concrete class
that implements the desired function. Fundamentally, Rust and C++
do something similar.&lt;/p&gt;
&lt;p&gt;So, how are we to evaluate this system? It&amp;rsquo;s not particularly designed
for situations like sorting. The run-time system is built for the
heterogeneous containers, where each individual element of a collection
might have a different opinion on how to compare itself to the others.
The amount of run-time flexibility is overkill to the situation.&lt;/p&gt;
&lt;p&gt;Rather than providing one sorting function pointer, as in the C example,
each object comes with its own infrastructure for finding out how to
not only sort, but do every other thing that Java might want to do
polymorphically with that object, such as convert it to a string, or
hash.  While the infrastructure is well-optimized and performant for the
assumption of heavy use of OOP-style polymorphism, it clearly doesn&amp;rsquo;t hold
to the C++ or Rust performance ideals of not paying for what you don&amp;rsquo;t
use, instead opting to pay an up-front cost under the assumption that
any and all objects will regularly be used polymorphically, in OOP style.&lt;/p&gt;
&lt;p&gt;The type system in Java is conceptualized as a way of preventing
errors, a layer of safety on top of a more Smalltalk-like natural
OOP state.  In Smalltalk any method can be invoked on any object,
and it&amp;rsquo;s simply a run-time error if that method isn&amp;rsquo;t available. In
Java, the types form a more rigorous layer to check to make
sure our method calls have correct semantics, allowing errors
to be caught earlier, at compile-time (although Java type errors
are also sometimes caught at run-time). The power of the more ideologically
pure form of OOP is still available in Java, as evidenced by the
signature on the &lt;code&gt;Arrays.sort&lt;/code&gt; method alluded to above (and &lt;a href=&#34;https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Arrays.html#sort%28java.lang.Object%5B%5D%29&#34;&gt;documented
here&lt;/a&gt;.
It is deprecated, but still possible:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(Object&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; a)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here is a use case that succeeds:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; java.util.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Sort&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(String&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Arrays.&lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(args);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (String arg : args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            System.&lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;println&lt;/span&gt;(arg);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here is the output:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ java Sort a c b
a
b
c
$
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here is a use that fails:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; java.util.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Sort&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;(String&lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Object &lt;span style=&#34;color:#f92672&#34;&gt;[]&lt;/span&gt; array &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Object&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;2&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        array&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;0&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Integer(0);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        array&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;1&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Arrays.&lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(array);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (Object obj : array) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            System.&lt;span style=&#34;color:#a6e22e&#34;&gt;out&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;println&lt;/span&gt;(obj);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It outputs:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Exception in thread &amp;#34;main&amp;#34; java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String (java.lang.Integer and java.lang.String are in module java.base of loader &amp;#39;bootstrap&amp;#39;)
	at java.base/java.lang.String.compareTo(String.java:125)
	at java.base/java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320)
	at java.base/java.util.ComparableTimSort.sort(ComparableTimSort.java:188)
	at java.base/java.util.Arrays.sort(Arrays.java:1249)
	at Sort.main(Sort.java:8)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The cost of this is acceptable in Java but not in Rust or C++, or C for
that matter. Every object must contain individual metadata if it is to
be sortable through a polymorphic function, and it must be boxed. In C++
or Rust, we must be able to sort arbitrary unboxed data, without extra
metadata included directly within it. But in Java, all types except for
primitives are boxed, only boxed types support polymorphism, and they do
so at the cost of additional data in each heap allocation to do so. And
it works, for Java&amp;rsquo;s goals, of being a garbage-collected OOP language
with a layer of types to expose errors at compile-time.&lt;/p&gt;
&lt;p&gt;As the C example shows, this cost isn&amp;rsquo;t intrinsic to run-time polymorphism
in general, but it is intrinsic to OOP-style polymorphism. OOP uses
run-time polymorphism at an individual object level as one of its
core features, even when the function does not need to be conveyed on
a per-element basis, but only once.&lt;/p&gt;
&lt;h1 id=&#34;programming-language-2-sorting-in-c&#34;&gt;Programming Language #2: Sorting in C++&lt;/h1&gt;
&lt;p&gt;C++, of course, supports this type of run-time polymorphism. We could,
if we wanted, build a system like Java&amp;rsquo;s, where we had an abstract class
&lt;code&gt;Comparable&lt;/code&gt; that we could use to add run-time data to show every object
of a type how to be compared with every other object. We could require
that collections to be sorted contain classes that inherit from &amp;ndash; in C++,
inheritance and interface implementation are the same &amp;ndash; &lt;code&gt;Comparable&lt;/code&gt;.
C++&amp;rsquo;s run-time polymorphism could be used to implement sorting in the
exact same way as Java.&lt;/p&gt;
&lt;p&gt;But that&amp;rsquo;s not how sorting is implemented in C++. Sorting, in C++,
uses a completely unrelated mechanism of templates. Templates are C++&amp;rsquo;s
mechanism for static, compile-time polymorphism, just as virtual functions
and inheritance are C++&amp;rsquo;s mechanism for dynamic, run-time polymorphism
(of a classical OOP variety that closely resembles Java). In spite of
them both being forms of polymorphism, and having many overlapping use
cases, templates and virtual functions are completely unrelated features.&lt;/p&gt;
&lt;p&gt;I have seen people argue that templates and virtual functions are
justified in being completely unrelated, because every situation clearly
calls for one or the other. But if it&amp;rsquo;s possible to do sorting with
run-time polymorphism, as we see from Java, then clearly the distinction
is not clear-cut as all that. What&amp;rsquo;s to stop a former Java programmer
from using C++&amp;rsquo;s run-time polymorphism to implement their own sorting
function a la Java, even though that&amp;rsquo;s not idiomatic C++? There&amp;rsquo;s clearly
some level of overlap in use cases, even if not in semantics!&lt;/p&gt;
&lt;p&gt;So, how do templates actually work?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Caveat for modern C++ fans&lt;/strong&gt;: I&amp;rsquo;m going to save concepts for the end. They
don&amp;rsquo;t actually substantially affect my point (as I will explain).
I think it&amp;rsquo;s simpler to talk about pre-concepts C++ at first, and then
discuss how concepts impact (or rather, don&amp;rsquo;t really impact) the equation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Templates are a form of macro system. A template (class template, function
template, type alias template, etc.) is given parameters at compile-time.
Once the template is given parameters, it is &lt;em&gt;instantiated&lt;/em&gt; and stamps out
a concrete component of the program (a class, function, type alias, etc.).&lt;/p&gt;
&lt;p&gt;So, that&amp;rsquo;s quite abstract. This is a situation where an example can
help a lot. In line with our theme, we&amp;rsquo;re going to write a template
that involves comparisons: given two values of any type that you can
compare (and we&amp;rsquo;ll have to decide what that means), which is bigger?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;template&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typename&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;T max_value(T a, T b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (a &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; a;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When we actually invoke it, we provide a type for &lt;code&gt;T&lt;/code&gt;, giving us
a specialized function where &lt;code&gt;T&lt;/code&gt; is replaced by that type.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; max_value&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; max_value&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hi&amp;#34;&lt;/span&gt;s, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;s) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The mere mention of &lt;code&gt;max_value&amp;lt;int&amp;gt;&lt;/code&gt; creates a function &lt;code&gt;max_value&amp;lt;int&amp;gt;&lt;/code&gt;,
and likewise for &lt;code&gt;max_value&amp;lt;std::string&amp;gt;&lt;/code&gt;. This function is the template,
with the template parameter in brackets standing in for &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Of course, for function templates, specifying the &lt;code&gt;T&lt;/code&gt; is optional,
as C++ can infer it, so this code works equally well:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; max_value(&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; max_value(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hi&amp;#34;&lt;/span&gt;s, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;s) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, what are the resulting functions? It&amp;rsquo;s very similar to as if
we had written:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;max_value&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; a, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (a &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; a;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string max_value(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string a, std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (a &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; a;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These are separate functions. The compiler will simply generate as many
separate versions of &lt;code&gt;max_value&lt;/code&gt; as it needs to. It outputs separate
assembly language for each of them, and treats them as function overloads,
meaning that it uses the static (compile-time) type of the parameters
to figure out which function to call.&lt;/p&gt;
&lt;p&gt;So, from the perspective of someone reading the code, we call
&lt;code&gt;max_value&lt;/code&gt; twice, and it figures out how to do its thing on an &lt;code&gt;int&lt;/code&gt;
or a &lt;code&gt;std::string&lt;/code&gt;.  It&amp;rsquo;s polymorphic, as it does the same algorithm
(finding max) with an operation that changes based on type (&lt;code&gt;&amp;lt;&lt;/code&gt;). But
from the perspective of someone reading the outputted assembly, it&amp;rsquo;s
not polymorphic &amp;ndash; we&amp;rsquo;ve simply got two different functions that do
&lt;code&gt;max_value&lt;/code&gt; in two different ways.&lt;/p&gt;
&lt;p&gt;In other words, we&amp;rsquo;ve gone from polymorphic code (compile time) to
monomorphic code (run time). This is why Rust calls its equivalent to
template instantiation &amp;ldquo;monomorphization.&amp;rdquo; This is also why it&amp;rsquo;s called
&amp;ldquo;compile time polymorphism&amp;rdquo; &amp;ndash; it is no longer polymorphic at run-time.&lt;/p&gt;
&lt;p&gt;The advantage: This is a zero-overhead abstraction. We&amp;rsquo;re having the
compiler write, on our behalf, specialized code for each type. We
do not need each element to have virtual function metadata to
indicate how to do comparisons, nor do we even need a function
pointer like with &lt;code&gt;qsort&lt;/code&gt;. It&amp;rsquo;s as optimal as specialized hand-written
code, but we didn&amp;rsquo;t have to do the specialization.&lt;/p&gt;
&lt;p&gt;The disadvantage: We have to know the type at compile-time. This
prevents heterogeneous containers from being possible with this
style of polymorphism. This type of polymorphism can only be based
off of the compile-time type, not based off of changing run-time types.
It is the exact opposite of &amp;ldquo;late binding&amp;rdquo; &amp;ndash; the binding is done at
compile-time. So, this could not be used for polymorphism over different
types of widgets in a list of widgets.&lt;/p&gt;
&lt;p&gt;The other disadvantage: Compile times take longer and the resultant
binary is larger. (Eh, shrug.)&lt;/p&gt;
&lt;p&gt;So what operations are needed to support this template? What definition
are we using for &amp;ldquo;comparable type&amp;rdquo; for &lt;code&gt;T&lt;/code&gt;? We&amp;rsquo;re not explicitly using
any at all, but note that if the type &lt;code&gt;T&lt;/code&gt; doesn&amp;rsquo;t support the &lt;code&gt;&amp;lt;&lt;/code&gt; operator,
this code will simply fail to compile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;max_value(Foo{}, Foo{});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Giving the error:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;test.cpp: In instantiation of ‘T max_value(T, T) [with T = main()::Foo]’:
test.cpp:22:14:   required from here
test.cpp:8:11: error: no match for ‘operator&amp;lt;’ (operand types are ‘main()::Foo’ and ‘main()::Foo’)
    8 |     if (a &amp;lt; b) {
      |         ~~^~~
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This goes away if we give it the &lt;code&gt;&amp;lt;&lt;/code&gt; operator.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; Foo &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;other) &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; false; &lt;span style=&#34;color:#75715e&#34;&gt;// All Foos are created equal!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;max_value(Foo{}, Foo{}); &lt;span style=&#34;color:#75715e&#34;&gt;// Now compiles
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we&amp;rsquo;d written &lt;code&gt;max_value&lt;/code&gt; differently, however, using &lt;code&gt;&amp;gt;&lt;/code&gt; instead,
this might not have made the error message go away. It turns out that &lt;code&gt;&amp;lt;&lt;/code&gt;
is the conventional operator to use for comparisons, however, the C++
equivalent to Java&amp;rsquo;s &lt;code&gt;Comparable&lt;/code&gt;, the defining function for &amp;ldquo;natural
order&amp;rdquo; by convention.&lt;/p&gt;
&lt;p&gt;Is that all that&amp;rsquo;s required to make &lt;code&gt;max_value&lt;/code&gt; work? It turns out no,
as many an astute C++ programmer has probably already noticed. There is
another operation besides &lt;code&gt;operator&amp;lt;&lt;/code&gt; required to make &lt;code&gt;max_value&lt;/code&gt; work,
and this is because I intentionally made a mistake (so I could reveal
it later to show how subtle templates can be).&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at the instantiation for &lt;code&gt;std::string&lt;/code&gt; again,
just the signature:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string max_value(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string a, std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string b);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Is that how we&amp;rsquo;d write &lt;code&gt;max_value&lt;/code&gt; by hand for &lt;code&gt;std::string&lt;/code&gt;? No, we
wouldn&amp;rsquo;t. We&amp;rsquo;d write &lt;code&gt;const std::string &amp;amp;a&lt;/code&gt;, and take it by reference,
so that no new objects are initialized in the comparison and return.
If you&amp;rsquo;re not a C++ programmer, this might seem shocking, but &lt;code&gt;max_value&lt;/code&gt;
as we wrote it requires the type to be passable by value, which is a
capability that a type might not have:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Foo() &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Foo(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; Foo&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;delete&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; Foo&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; other) &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; false; &lt;span style=&#34;color:#75715e&#34;&gt;// All Foos are created equal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;max_value(Foo{}, Foo{}); &lt;span style=&#34;color:#75715e&#34;&gt;// Error! Error!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, we missed the mark, quite by accident! We had an
extra requirement besides comparison, and we can fix that
by taking the value by (&lt;code&gt;const&lt;/code&gt;) reference (which is what
&lt;a href=&#34;https://en.cppreference.com/w/cpp/algorithm/max&#34;&gt;&lt;code&gt;std::max&lt;/code&gt;&lt;/a&gt; does
anyway), which also implies returning by reference:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;template&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typename&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;max_value(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;a, &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; T &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (a &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; b) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; a;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So what was required from &lt;code&gt;T&lt;/code&gt; for us to call &lt;code&gt;max_value&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;In one sense, nothing besides that it should be a type! We could pass any
type in for &lt;code&gt;T&lt;/code&gt;, and the compiler will plug in the type and chug away,
running into errors only once it has attempted to do so! This might
actually happen several template instantiations deep, and the resulting
error shows up in the template where the operation is attempted, not
in where you use the template with an inappropriate type, which can
be confusing.&lt;/p&gt;
&lt;p&gt;In another sense, what is required is that we pass types that make
&lt;code&gt;max_value&lt;/code&gt; compile, so in this case, ones that support &lt;code&gt;operator &amp;lt;&lt;/code&gt;.
However, there is no guarantee or check that the type is making the
semantic promises that correspond to that type. Sorting, for example,
requires that that operator work in such a way as to define a strict
equivalence class. If that operator doesn&amp;rsquo;t in fact do that, &lt;code&gt;std::sort&lt;/code&gt;
will compile but won&amp;rsquo;t work properly.&lt;/p&gt;
&lt;p&gt;It seems reasonable in this case to expect people to use &lt;code&gt;operator &amp;lt;&lt;/code&gt;
for less-than as it&amp;rsquo;s such a well-established and fundamental operator.
But templates can also invoke named methods. What if somebody writes
a template that calls &lt;code&gt;some_t.foo()&lt;/code&gt; expecting it to do one thing,
and someone calls that template with an unrelated class that has a
type-compatible &lt;code&gt;foo&lt;/code&gt; method, but with different semantics? There is no
indication to the compiler, when you write the class, that you intend
for &lt;code&gt;foo&lt;/code&gt; to be appropriate for use in the template. We didn&amp;rsquo;t have to
say, when we wrote &lt;code&gt;Foo&lt;/code&gt; here, that our &lt;code&gt;operator &amp;lt;&lt;/code&gt; was valid for
&lt;code&gt;std::sort&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Concepts do help with that. You can statically assert that a class
supports a concept&amp;rsquo;s requirements, and that documents your intention
to support it semantically as well. Concepts can also cover stricter
requirements than a template incidentally imposes, and help document
the semantics of templates.&lt;/p&gt;
&lt;p&gt;But everything about concepts is opt-in; you can always write a template
that will sometimes fail on instantiation. And that makes them much less
useful in my book. Don&amp;rsquo;t get me wrong: I&amp;rsquo;m glad they exist. I think C++
with concepts is better than C++ without concepts. But it only goes so
far, especially when compared with Rust traits, which are mandatory for
Rust&amp;rsquo;s form of compile-time polymorphism.&lt;/p&gt;
&lt;p&gt;More relevant than all of this, to me, is that templates and OOP work
so differently than each other. Run-time polymorphism and compile-time
polymorphism are just completely different beasts. Students are taught
the OOP style run-time polymorphism, and that doesn&amp;rsquo;t really help them
understand templates, or even get started doing so. Again, I feel C++
is too big.&lt;/p&gt;
&lt;p&gt;But, at least it has this zero-overhead abstraction, without requiring
a method look-up and an indirection for every item to be sorted.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;std::sort&lt;/code&gt;, by the way, takes iterators. These iterators must be
value swappable legacy random access iterators, and that&amp;rsquo;s just a
subset of the requirements, as seen in &lt;code&gt;std::sort&lt;/code&gt;&amp;rsquo;s &lt;a href=&#34;https://en.cppreference.com/w/cpp/algorithm/sort&#34;&gt;CPPReference
page&lt;/a&gt;. The way to
get from one element to another (and therefore implicitly the size),
the way to swap elements, and the way to compare them are all implicitly
derived from &lt;code&gt;RandomIt&lt;/code&gt;, the type parameter specifying the type of the
iterator (at least in the overloads of &lt;code&gt;std::sort&lt;/code&gt; that do not take an
explicit comparator).&lt;/p&gt;
&lt;h1 id=&#34;programming-language-3-sorting-in-haskell&#34;&gt;Programming Language #3: Sorting in Haskell&lt;/h1&gt;
&lt;p&gt;Now for Haskell!&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;re mostly talking about Haskell to move on to talking about Rust,
as this is a Rust-focused blog. There&amp;rsquo;s a lot going on with Haskell
typeclasses that I won&amp;rsquo;t have time to get into here.&lt;/p&gt;
&lt;p&gt;Haskell is where Rust got traits from, although Haskell
calls them typeclasses. Incidentally, Haskell uses run-time polymorphism
where Rust uses compile-time polymorphism, but the semantics are more
similar than you might expect from that statement.&lt;/p&gt;
&lt;p&gt;In Haskell, like Java, all types that &lt;code&gt;sort&lt;/code&gt; accepts are boxed, covering
size and swapping among the traits that might need to be customized.
Unlike Java, the operations we need to perform on values of this type
are passed to &lt;code&gt;sort&lt;/code&gt; once, rather than looked up on a per-element basis.&lt;/p&gt;
&lt;p&gt;Here is the type for &lt;a href=&#34;https://hackage.haskell.org/package/base-4.19.0.0/docs/Data-List.html#v:sort&#34;&gt;&lt;code&gt;sort&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-haskell&#34; data-lang=&#34;haskell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Ord&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; [a] &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; [a]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;a&lt;/code&gt; here is like &lt;code&gt;T&lt;/code&gt; in C++: a type variable that can be replaced
with any type. As in Java, this is subject to type erasure: &lt;code&gt;sort&lt;/code&gt;
just operates on generic boxed values. Any comparison-specific operations
it needs come from the &lt;code&gt;Ord a =&amp;gt;&lt;/code&gt;, which constrains &lt;code&gt;a&lt;/code&gt; to types that
have instances of the &lt;code&gt;Ord&lt;/code&gt; typeclass.&lt;/p&gt;
&lt;p&gt;Here is the definition of &lt;code&gt;Ord&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-haskell&#34; data-lang=&#34;haskell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt;  (&lt;span style=&#34;color:#66d9ef&#34;&gt;Eq&lt;/span&gt; a) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Ord&lt;/span&gt; a  &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    compare              &lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Ordering&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;), (&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt;), (&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;), (&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Bool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    max, min             &lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    compare x y &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; x &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; y &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;EQ&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#75715e&#34;&gt;-- NB: must be &amp;#39;&amp;lt;=&amp;#39; not &amp;#39;&amp;lt;&amp;#39; to validate the&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#75715e&#34;&gt;-- above claim about the minimal things that&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#75715e&#34;&gt;-- can be defined for an instance of Ord:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; x &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; y &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;LT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;GT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;  y &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; compare x y &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;LT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;;  &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; y &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; compare x y &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;GT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;  y &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; compare x y &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;GT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;;  &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; y &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; compare x y &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;LT&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;; &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;-- These two default methods use &amp;#39;&amp;lt;=&amp;#39; rather than &amp;#39;compare&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;-- because the latter is often more expensive&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    max x y &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; x &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; y &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt; y &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; x
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    min x y &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; x &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; y &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt; x &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; y
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It defines many methods that an instance of &lt;code&gt;Ord&lt;/code&gt; can support.
These methods are functions defined in terms of each other; you
must specifically implement at least one of them for your type to prevent
infinite regress. Minimally, either &lt;code&gt;compare&lt;/code&gt; or &lt;code&gt;&amp;lt;=&lt;/code&gt; is sufficient,
with &lt;code&gt;compare&lt;/code&gt; &lt;a href=&#34;https://hackage.haskell.org/package/base-4.1.0.0/docs/src/GHC-Classes.html#Ord&#34;&gt;recommended&lt;/a&gt; for more complex types.&lt;/p&gt;
&lt;p&gt;Unlike in C++, when you define these methods, it is not enough to simply
define a function called &lt;code&gt;&amp;lt;=&lt;/code&gt; or &lt;code&gt;compare&lt;/code&gt;. Haskell won&amp;rsquo;t even let you
define functions with the same fully qualified name as the methods,
which exist in the same namespace as any other functions. Unlike
C++, Haskell does not have function overloading, and any time the
same fully qualified name has different semantics for different types,
it is through this mechanism of &lt;code&gt;typeclass&lt;/code&gt;es. Like in Java,
you have to explicitly declare your intention to implement the methods
as found in &lt;code&gt;Ord&lt;/code&gt;, by writing an &lt;code&gt;instance&lt;/code&gt; explicitly, like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Haskell&#34; data-lang=&#34;Haskell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; Data.Ord
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; Data.List
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;data&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Integer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;deriving&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Show&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;instance&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Eq&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; a) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; b) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; b
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;instance&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Ord&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; a) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; b) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; b &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; list &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;Foo&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print &lt;span style=&#34;color:#f92672&#34;&gt;$&lt;/span&gt; sort list                   &lt;span style=&#34;color:#75715e&#34;&gt;-- outputs [Foo 4,Foo 3,Foo 2]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that the &lt;code&gt;instance&lt;/code&gt; declarations are separate from the definition
of the type! The module where the type is declared can define them, but
so can the module where the &lt;code&gt;typeclass&lt;/code&gt; is declared. Other modules
are not allowed to by default to make sure there is only one canonical
definition of an instance for a given type and typeclass.&lt;/p&gt;
&lt;p&gt;How does this actually work then? Well, &lt;code&gt;Ord a&lt;/code&gt; is a secret parameter
to &lt;code&gt;sort&lt;/code&gt;. Haskell will create a bundle of function pointers for us
that represent the specific &lt;code&gt;Ord&lt;/code&gt; instance for whatever type we pass to
&lt;code&gt;sort&lt;/code&gt;, either from knowing the type statically at that point, or passing
along a bundle passed into whatever called &lt;code&gt;sort&lt;/code&gt;. So this compiles to
something quite similar to the C &lt;code&gt;qsort&lt;/code&gt; (at least as far as polymorphism
is concerned), taking in a comparison function. The big difference is,
Haskell will choose the comparison function for us &amp;ndash; but it is one
comparison function, not one comparison function per item as in Java.&lt;/p&gt;
&lt;h1 id=&#34;programming-language-4-sorting-in-rust&#34;&gt;Programming Language #4: Sorting in Rust&lt;/h1&gt;
&lt;p&gt;So, how does Rust do all of this?&lt;/p&gt;
&lt;p&gt;As I said, a Rust &lt;code&gt;trait&lt;/code&gt; is very much
like a Haskell typeclass.  Rust&amp;rsquo;s main &lt;a href=&#34;https://doc.rust-lang.org/std/vec/struct.Vec.html#method.sort&#34;&gt;&lt;code&gt;sort&lt;/code&gt;
method&lt;/a&gt;,
like Haskell, requires the &lt;a href=&#34;https://doc.rust-lang.org/std/cmp/trait.Ord.html&#34;&gt;&lt;code&gt;Ord&lt;/code&gt; &lt;del&gt;typeclass&lt;/del&gt;
trait&lt;/a&gt;.  Like Haskell,
it even has provided (but overrideable) methods as well as required
methods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Rust&#34; data-lang=&#34;Rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;trait&lt;/span&gt; Ord: Eq &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; PartialOrd {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Required method
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cmp&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self, other: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Ordering&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Provided methods
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;max&lt;/span&gt;(self, other: &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; Self: Sized { &lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;. }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;min&lt;/span&gt;(self, other: &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; Self: Sized { &lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;. }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;clamp&lt;/span&gt;(self, min: &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;, max: &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; Self: Sized &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; PartialOrd { &lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;. }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Like typeclasses, to indicate that a type has a trait requires
a specific block that says what trait we&amp;rsquo;re trying to implement,
and lists the implementation of the required methods. Like in Haskell,
that block may reside in the crate where the trait is defined, or the
trait where the type is defined. Like in Haskell, this allows us to
add polymorphism to previously unpolymorphic operations without having
to create wrapper types.&lt;/p&gt;
&lt;p&gt;Here is an example of implementing this trait (unfortunately, we
have to implement both &lt;code&gt;Ord&lt;/code&gt; and &lt;code&gt;PartialOrd&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Rust&#34; data-lang=&#34;Rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;use&lt;/span&gt; std::cmp::Ordering;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[derive(PartialEq, Eq, Clone, Copy, Debug)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; PartialOrd &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; Foo {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;partial_cmp&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self, other: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;) -&amp;gt; Option&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Ordering&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        other.&lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;partial_cmp(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self.&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; Ord &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; Foo {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cmp&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self, other: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Ordering&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        other.&lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;cmp(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self.&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; foos &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;vec!&lt;/span&gt;[Foo(&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;), Foo(&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;), Foo(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;), Foo(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    foos.sort();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{:?}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, foos); &lt;span style=&#34;color:#75715e&#34;&gt;// Displays [Foo(4), Foo(3), Foo(2), Foo(1)]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s very similar to Haskell, but with &amp;ldquo;C-like&amp;rdquo; syntax and aesthetic.
The syntax for the functions using the trait looks like C++ templates:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-Rust&#34; data-lang=&#34;Rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;max&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T: Ord&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;(a: &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;, b: &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; b &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; a { b } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { a }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What&amp;rsquo;s different from Haskell is how it&amp;rsquo;s implemented. The semantics
are quite similar, and the Rust implementation can be thought of
as an optimization of the Haskell semantics. Instead of passing in
to &lt;code&gt;sort()&lt;/code&gt; a secret run-time parameter with &lt;code&gt;Foo&lt;/code&gt;&amp;rsquo;s implementation
of &lt;code&gt;Ord&lt;/code&gt;, the function is &lt;em&gt;monomorphized&lt;/em&gt;. We can think of it as
inlining just that one parameter at compile-time, and generating
a specialized function.&lt;/p&gt;
&lt;p&gt;Yes, this implementation is fundamentally very similar to C++&amp;rsquo;s
implementation of templates. It&amp;rsquo;s basically the same in terms of machine
code and resulting optimizations. But the semantics are more
Haskell-like. Polymorphic functions are type-checked once.
They may only use functionality incorporated in the traits at hand.
We don&amp;rsquo;t postpone the type-checking for the template instantiation.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s more, the same mechanism is also used for Rust&amp;rsquo;s run-time
polymorphism, where we can have a type like &lt;code&gt;dyn MyTrait&lt;/code&gt; for
some specific traits that are &lt;em&gt;object-safe&lt;/em&gt;. These &lt;em&gt;trait object&lt;/em&gt;
types are like OOP polymorphic types, in that each value has its
own copy of the table of polymorphic functions with it, but the
copy is outside the original object. It is a property of the
pointer, not of the object, and implemented with fat pointers.&lt;/p&gt;
&lt;p&gt;Like with any other trait, the trait implementation is separate from
the type definition or the trait definition (though it must live in
the same crate as one of them). Unlike C++, there is one system for
polymorphism that can be used in both run-time and compile-time ways,
with overlap where possible.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I hope this shows, if nothing else, that polymorphism itself can take
many forms in many programming languages beyond the OOP variety of it.
The OOP variety is in some senses self-propagating &amp;ndash; if you optimize
your language for it as in Java, then it makes sense to use for everything,
even if it&amp;rsquo;s not what you would choose in a language that has other options.&lt;/p&gt;
&lt;p&gt;For many forms of polymorphism, in C++ (for templates), Haskell, and
Rust, no inheritance is necessary. It is simply not built according to
the OOP frame of mind. I personally think Haskell and Rust are doing it
right here, as is perhaps obvious from how I&amp;rsquo;ve written about it.&lt;/p&gt;
&lt;p&gt;I hope to write more about run-time polymorphism in Rust, and how it
differs from the C++ variety, and how you can manually implement other
types of run-time polymorphism if you want. This would be a future
post. But, this is a hobby blog, so no promises on timeline!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Minor News: Some Repos on GitHub</title>
      <link href="https://www.thecodedmessage.com/posts/minor-news/" />
      <id>https://www.thecodedmessage.com/posts/minor-news/</id>
      <updated>2024-01-21T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;So, there are now two additional repos of my code on GitHub that recently
got published, both under the MIT license. Neither is any show-stopping
major project, but I figured I&amp;rsquo;d let everyone know nevertheless, and
write up a few notes about it. Both have been added to my
&lt;a href=&#34;https://www.thecodedmessage.com/programming-portfolio/&#34;&gt;programming portfolio&lt;/a&gt; &lt;a href=&#34;https://www.thecodedmessage.com/gardens/&#34;&gt;garden&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;repo-1-crate-version-of-prefix-ranges&#34;&gt;Repo #1: Crate Version of Prefix Ranges&lt;/h1&gt;
&lt;p&gt;Arvid Norlander (&lt;a href=&#34;https://vorpal.se/&#34;&gt;blog&lt;/a&gt;,
&lt;a href=&#34;https://github.com/VorpalBlade&#34;&gt;GitHub&lt;/a&gt;) reached out to me to ask if
I wanted to publish my little &lt;a href=&#34;https://www.thecodedmessage.com/range.rs&#34;&gt;Rust module&lt;/a&gt; from my post on
&lt;a href=&#34;https://www.thecodedmessage.com/posts/prefix-ranges/&#34;&gt;prefix ranges&lt;/a&gt; as a crate, or, failing that,
if I could license it as open source so he could publish it. I had
thought of most of my code on this blog up until this point as example
code not worth licensing, but his prompting changed my mind. If it&amp;rsquo;s
just trivial example code, it&amp;rsquo;s not worth &lt;strong&gt;not&lt;/strong&gt; open sourcing, so
I might as well release the website&amp;rsquo;s example code under an &lt;a href=&#34;https://www.thecodedmessage.com/license/&#34;&gt;MIT
license&lt;/a&gt;.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;So, there are now two additional repos of my code on GitHub that recently
got published, both under the MIT license. Neither is any show-stopping
major project, but I figured I&amp;rsquo;d let everyone know nevertheless, and
write up a few notes about it. Both have been added to my
&lt;a href=&#34;https://www.thecodedmessage.com/programming-portfolio/&#34;&gt;programming portfolio&lt;/a&gt; &lt;a href=&#34;https://www.thecodedmessage.com/gardens/&#34;&gt;garden&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;repo-1-crate-version-of-prefix-ranges&#34;&gt;Repo #1: Crate Version of Prefix Ranges&lt;/h1&gt;
&lt;p&gt;Arvid Norlander (&lt;a href=&#34;https://vorpal.se/&#34;&gt;blog&lt;/a&gt;,
&lt;a href=&#34;https://github.com/VorpalBlade&#34;&gt;GitHub&lt;/a&gt;) reached out to me to ask if
I wanted to publish my little &lt;a href=&#34;https://www.thecodedmessage.com/range.rs&#34;&gt;Rust module&lt;/a&gt; from my post on
&lt;a href=&#34;https://www.thecodedmessage.com/posts/prefix-ranges/&#34;&gt;prefix ranges&lt;/a&gt; as a crate, or, failing that,
if I could license it as open source so he could publish it. I had
thought of most of my code on this blog up until this point as example
code not worth licensing, but his prompting changed my mind. If it&amp;rsquo;s
just trivial example code, it&amp;rsquo;s not worth &lt;strong&gt;not&lt;/strong&gt; open sourcing, so
I might as well release the website&amp;rsquo;s example code under an &lt;a href=&#34;https://www.thecodedmessage.com/license/&#34;&gt;MIT
license&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This particular piece of code seems like the wrong end solution to
the problem at hand &amp;ndash; though it is the solution I ended up using
when faced with the problem in a larger project. Ideally, I would
like to write a follow-up piece to the &lt;a href=&#34;https://www.thecodedmessage.com/posts/prefix-ranges/&#34;&gt;prefix range&lt;/a&gt;
article, discussing how to fix &lt;code&gt;BTreeMap&lt;/code&gt; to generalize not just
to splitting on various keys based on their ordering properties, but
based on any appropriate function that acts as a range (i.e. that
monotonically transitions from &lt;code&gt;false&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; when looping over items in
sorted order by the &lt;code&gt;Ord&lt;/code&gt; trait), as a generalization of
&lt;a href=&#34;https://doc.rust-lang.org/nightly/std/ops/enum.Bound.html&#34;&gt;&lt;code&gt;Bound&lt;/code&gt;&lt;/a&gt;.
Then, prefixes could be represented in terms of such a function, and
we could leverage the full efficiency of a &lt;code&gt;BTreeMap&lt;/code&gt; without having
to do any extra UTF-8-mongering.&lt;/p&gt;
&lt;p&gt;But fully implementing such a thing would mean patching the standard library,
and fully writing that blog post would mean a lot of benchmarking
work.  I still plan on doing it someday, but as I point out many
times, this is a hobby blog (although I do now support &lt;a href=&#34;https://www.buymeacoffee.com/thecodedmessage&#34;&gt;buying me a
coffee&lt;/a&gt;, that is meant in
the true spirit of buying me an extra beverage as a token of thanks. At
the time of this writing no one has clicked it, and I certainly expect
no more than occasional literal coffees to come of any money from it),
and so follow-up posts will happen when they happen (although nagging
me about it, nicely, over e-mail is allowed).&lt;/p&gt;
&lt;h1 id=&#34;repo-2-texas-hold-em-libraryquiz-app&#34;&gt;Repo #2: Texas Hold-Em Library/Quiz App&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve been writing some code to do with the most popular
modern poker variant, Texas Hold-Em. It lives in a &lt;a href=&#34;https://github.com/jhartzell42/holdem_rs&#34;&gt;repo on
GitHub&lt;/a&gt;. Ideally, it&amp;rsquo;ll turn
into an app to help me and some buddies practice reading flops, counting
outs, seeing who&amp;rsquo;s ahead, and doing other hold-em mental calculations. I
might also extract a library or even a framework for writing AIs, or
playing against them. Maybe even a front-end app could be added,
either in Rust or in &lt;a href=&#34;https://reflex-frp.org/&#34;&gt;Reflex&lt;/a&gt; in Haskell.&lt;/p&gt;
&lt;p&gt;But no promises! See the hobby blog note above! If you really want a
feature, I&amp;rsquo;ll happily accept PRs!&lt;/p&gt;
&lt;p&gt;Of course, this wouldn&amp;rsquo;t be the first such codebase, or even the first
in Rust. I&amp;rsquo;m just having run. I enjoyed writing the code so far, and I
figured I&amp;rsquo;d put it on GitHub in the meantime, even if it never becomes
particularly useful.&lt;/p&gt;
&lt;p&gt;Writing it with all its combinatoric randomness made me really learn to
appreciate &lt;a href=&#34;https://crates.io/crates/itertools&#34;&gt;&lt;code&gt;itertools&lt;/code&gt;&lt;/a&gt;, a collection
of iterator methods that for various reasons haven&amp;rsquo;t been accepted or
stabilized in the standard library. It&amp;rsquo;s been good exercise writing in
functional programming, iterator and iterator-transformer style, which
is a little harder in Rust than in Haskell.&lt;/p&gt;
&lt;p&gt;Also, while I understand why Rust doesn&amp;rsquo;t have generators (there is
an excellent &lt;a href=&#34;https://without.boats/tags/generators/&#34;&gt;blog series&lt;/a&gt;
about the topic on &lt;a href=&#34;https://without.boats/&#34;&gt;&amp;ldquo;Without Boats&amp;rdquo;&lt;/a&gt;), many of
the reasons are historical and, well, I just really wish it did.&lt;/p&gt;
&lt;p&gt;Additional future exploration might include zany optimizations, perhaps
inspired by (but not directly following in the feet of) &lt;a href=&#34;http://suffe.cool/poker/evaluator.html&#34;&gt;this zany hand
evaluation algorithm&lt;/a&gt;
implemented in Rust many places including
&lt;a href=&#34;https://github.com/b-inary/holdem-hand-evaluator/blob/main/src/hand.rs#L112&#34;&gt;here&lt;/a&gt;
by &lt;a href=&#34;https://github.com/b-inary/&#34;&gt;Wataru Inariba&lt;/a&gt; &amp;ndash; although regular
optimizations probably come first.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Rust Is Beyond Object-Oriented, Part 3: Inheritance</title>
      <link href="https://www.thecodedmessage.com/posts/oop-3-inheritance/" />
      <id>https://www.thecodedmessage.com/posts/oop-3-inheritance/</id>
      <updated>2023-12-07T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;In this next&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; post of my series explaining how Rust is better
off &lt;a href=&#34;https://www.thecodedmessage.com/tags/beyond-oop/&#34;&gt;without Object-Oriented Programming&lt;/a&gt;, I discuss
the last and (in my opinion) the weirdest of OOP&amp;rsquo;s 3 traditional pillars.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation/&#34;&gt;encapsulation&lt;/a&gt;, a great idea which
exists in some form in every modern programming language, just OOP does
it oddly. It&amp;rsquo;s not &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-2-polymorphism/&#34;&gt;polymorphism&lt;/a&gt;, also a
great idea that OOP puts too many restrictions on, and that Rust
borrows a better design for from Haskell (with syntax from C++).&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;In this next&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; post of my series explaining how Rust is better
off &lt;a href=&#34;https://www.thecodedmessage.com/tags/beyond-oop/&#34;&gt;without Object-Oriented Programming&lt;/a&gt;, I discuss
the last and (in my opinion) the weirdest of OOP&amp;rsquo;s 3 traditional pillars.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation/&#34;&gt;encapsulation&lt;/a&gt;, a great idea which
exists in some form in every modern programming language, just OOP does
it oddly. It&amp;rsquo;s not &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-2-polymorphism/&#34;&gt;polymorphism&lt;/a&gt;, also a
great idea that OOP puts too many restrictions on, and that Rust
borrows a better design for from Haskell (with syntax from C++).&lt;/p&gt;
&lt;p&gt;No, it&amp;rsquo;s that third pillar, inheritance, that I am discussing today, that
concept that only shows up in OOP circles, causing no end of problems
for your code. Unlike encapsulation and polymorphism, Rust does not
have any direct analogue.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; In this series in general, but especially in this post,
I am primarily discussing static OOP languages, like C++ and Java,
where interfaces have to be explicit and where classes correspond to
different static types. Much of what I write would have to be adapted
to apply to more dynamic &amp;ldquo;duck-typing&amp;rdquo; styles of OOP like
in Python or JavaScript (or Smalltalk), and won&amp;rsquo;t apply as directly.
This series is about why Rust isn&amp;rsquo;t OOP, and Rust is closer to C++ or
Java than to a dynamic language, so this bias makes sense in context.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;why-do-people-like-inheritance&#34;&gt;Why do people like inheritance?&lt;/h1&gt;
&lt;p&gt;I can see why inheritance is so compelling. The entire system
of education encourages us to categorize things into neat little
hierarchies. Rectangles are a type of shape, and squares are a type of
rectangle. Humans are a type of animal, and men and women are types of
humans. Inheritance allows us to take this &amp;ldquo;X is a Y&amp;rdquo; and express it to
a computer.&lt;/p&gt;
&lt;p&gt;This &amp;ldquo;is a&amp;rdquo; relationship is seen as intuitive. As the entire point of OOP
is to make programming more intuitive, more like reasoning about the
real world, inheritance is a perfect match for it. Just like we reason
about the real world with categories and subcategories, we can reason
about the world of our program in a similar way.&lt;/p&gt;
&lt;p&gt;And this allows us to feel smart when we read introductions to inheritance
in various books on OOP programming. We see the &lt;code&gt;Tiger&lt;/code&gt; class inherit
from the &lt;code&gt;Animal&lt;/code&gt; class, or the &lt;code&gt;Rectangle&lt;/code&gt; class inherit from the
&lt;code&gt;Shape&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;We get so excited by the abstract principle of &amp;ldquo;is a&amp;rdquo; that we don&amp;rsquo;t even
notice that the examples have nothing to do with programming. We don&amp;rsquo;t
write code about shapes or animals. And even a drawing program or a zoo
inventory app wouldn&amp;rsquo;t use inheritance like this! If inheritance was so
useful as to be a pillar of OOP, why are there so few beginner examples
that involve things programs actually do?&lt;/p&gt;
&lt;h1 id=&#34;what-do-i-mean-by-inheritance&#34;&gt;What do I mean by inheritance?&lt;/h1&gt;
&lt;p&gt;First, let me clarify what I mean by inheritance, or rather what I don&amp;rsquo;t
mean.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t mean every subtype-supertype relationship, where all values
of one type are also included in another, broader type. Subtyping
shows up in Rust all the time, particularly when it comes to
&lt;a href=&#34;https://doc.rust-lang.org/nomicon/subtyping.html&#34;&gt;lifetimes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I also don&amp;rsquo;t mean the version of inheritance that only involves
implementing an interface. In C++, you implement dynamic interfaces
through inheritance as a mechanism, even if the &amp;ldquo;superclass&amp;rdquo; is just
a list of methods. In Java, inheritance and interface implementation
are separate mechanisms. I am not talking about interface implementation
as inheritance, even though it is technically considered the same
feature in C++:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// This class has no fields, only virtual methods.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// In Java, we would call this an interface. In Rust, we would
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// call this a trait.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Shape&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;virtual&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; draw(Surface &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;surface) &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// This is considered inheritance in C++. The Java equivalent
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// would use `implements` instead of `extends`. And you could still
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// do this in Rust with a trait.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Square&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Shape {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; size;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; x;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; y;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; draw(Surface &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;surface) &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;override&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I am only opposed to the type of inheritance that is still called
inheritance in Java. Having a type implement an interface (a &lt;em&gt;trait&lt;/em&gt;
in Rust) is perfectly legitimate and still allowed in Rust, as is
casting a reference to a value to a generic, &amp;ldquo;dynamic&amp;rdquo; value based on
that trait or interface:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;trait&lt;/span&gt; Shape {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;draw&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self, surface: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;mut&lt;/span&gt; Surface);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Square&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    size: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    y: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; Shape &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; Square {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;draw&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self, surface: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;mut&lt;/span&gt; Surface) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Assume square is Square, surface is Surface
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; shape: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;dyn&lt;/span&gt; Shape &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;square;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;shape.draw(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; surface);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Shape&lt;/code&gt;, in this context, is a pure interface. It is only a structured
form of polymorphism, not inheritance per se. Very importantly, &lt;code&gt;Shape&lt;/code&gt; has
no fields. It is defined based solely on what you can do with it. And
accordingly, the &amp;ldquo;is a&amp;rdquo; language makes sense for interface implementation:
&lt;code&gt;Square&lt;/code&gt; is a &lt;code&gt;Shape&lt;/code&gt;. A &lt;code&gt;Shape&lt;/code&gt; has no state, though, just methods, just
behaviors.&lt;/p&gt;
&lt;p&gt;But some parent classes have fields. And that&amp;rsquo;s when inheritance really
starts to have problems: when the &amp;ldquo;parent&amp;rdquo; class has fields. It is at
this point that inheritance starts to seem really weird.&lt;/p&gt;
&lt;h1 id=&#34;what-does-inheritance-actually-do&#34;&gt;What does inheritance actually do?&lt;/h1&gt;
&lt;p&gt;In my article on &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation&#34;&gt;encapsulation&lt;/a&gt;, I discussed
how a class is secretly two things with the same name, entangled and
conflated:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;record type&lt;/strong&gt; (or what Rust would call a &lt;code&gt;struct&lt;/code&gt;), that is, a type
whose values consist of a number of fields with fixed names and types&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;module&lt;/strong&gt; (a collection of code with enforced encapsulation boundaries),
containing that record type and a collection of functions (called &amp;ldquo;methods&amp;rdquo;)
for interacting with it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Inheritance does something different with each of these concepts.
To start out, let&amp;rsquo;s discuss what it does to the record type.
We&amp;rsquo;ll continue using shapes, a classic example for discussing
object-oriented features. A circle is a shape, so we can use inheritance
here:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Shape&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Color color;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Point&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; x;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; y;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Circle&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Shape {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Point center;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; radius;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, what does this mean for &lt;code&gt;Circle&lt;/code&gt;? Well, it means that all the fields
of &lt;code&gt;Shape&lt;/code&gt; (namely, &lt;code&gt;color&lt;/code&gt;) are also fields of &lt;code&gt;Circle&lt;/code&gt;. Therefore,
references to &lt;code&gt;Circle&lt;/code&gt; can be made into references to &lt;code&gt;Shape&lt;/code&gt;, as everything
you can do with a shape, you can do with a circle, like set the color,
or get the color:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Circle circle;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Shape &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;shape &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; circle;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;shape.color &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Color&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;Blue;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;assert(circle.color &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; Color&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;Blue);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The thing is, we already have a mechanism of taking all the fields of
struct A and putting it in struct B: by putting a field of type A into
struct B! Instead of inheritance&amp;rsquo;s &amp;ldquo;is a,&amp;rdquo; we can accomplish the same
thing with having a field, or &amp;ldquo;has a.&amp;rdquo;  In our example, we can do the
exact same thing with &lt;code&gt;Point&lt;/code&gt; that we did with &lt;code&gt;Shape&lt;/code&gt; &amp;ndash; it just
involves being a little more explicit about what&amp;rsquo;s going on:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Circle circle;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Point &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;point &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; circle.center;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;point.x &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;assert(circle.center.x &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, what does inheritance do to the classes from the &lt;strong&gt;record type&lt;/strong&gt;
perspective? It makes the parent class a field of the child class,
just a field with no name. By writing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Circle&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Shape {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip; from a record type perspective, we were writing syntactic sugar for:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Circle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Shape shape;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And when we wrote:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Shape &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;shape &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; circle;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That was translated into something like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Shape &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;shape &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; circle.shape;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;ldquo;Is a,&amp;rdquo; from a record type point of view, is just syntactic sugar for
&amp;ldquo;has a.&amp;rdquo; If you want to do something similar in Rust, just make a has-a
relationship, rather than creating an implicit field with no name.
Rust doesn&amp;rsquo;t like implicit nameless things anyway.&lt;/p&gt;
&lt;p&gt;This will also save on arguing about whether two types have an &amp;ldquo;is a&amp;rdquo;
or a &amp;ldquo;has a&amp;rdquo; relationship. I regret all the time I&amp;rsquo;ve spent splitting hairs
about that distinction, when really, it&amp;rsquo;s just a matter of whether we want
a field to be implicit or not.&lt;/p&gt;
&lt;p&gt;OK, so that covers what inheritance does to the record types, but
what about the rest of the class, the module? What happens to
the methods?&lt;/p&gt;
&lt;p&gt;Well, for non-virtual methods, it&amp;rsquo;s also straight-forward. Instead of
doing inheritance, you can still just use has-a instead, and do a field
access. Instead of calling, say, &lt;code&gt;circle.get_color()&lt;/code&gt;, we could always
call &lt;code&gt;circle.shape.get_color()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So far, with the fields and non-virtual methods, inheritance just
seems a bit weird and overrated. Like, we don&amp;rsquo;t see any reason yet
why a programming language would want to support it, when just having
a field of a superclass type does everything. But on the other hand,
some people like implicit fields and convenient short-hands, so there&amp;rsquo;s
not much of a downside either.&lt;/p&gt;
&lt;p&gt;Inheritance without virtual methods may seem harmless, but it doesn&amp;rsquo;t
have much to do with the concept of &amp;ldquo;is a.&amp;rdquo; Technically, you can use a
field access as an implicit conversion, and think of it as a subtyping
relationship, but it doesn&amp;rsquo;t actually correspond to how the world
works. Even in the world of shapes, it doesn&amp;rsquo;t make sense: if a square
is a rectangle, how come it has less state than a rectangle, with only
one field for side length instead of two for width and height?&lt;/p&gt;
&lt;p&gt;But we&amp;rsquo;ve not yet talked about virtual methods. When we do, you will
see why I think inheritance is not just an unnecessary feature, but an
ill-conceived anti-feature.&lt;/p&gt;
&lt;h1 id=&#34;but-what-about-the-virtual-methods&#34;&gt;But what about the virtual methods?&lt;/h1&gt;
&lt;p&gt;So, earlier we discussed a class as being two things, a record type (with
fields) and a module (with methods and visibility restrictions). But
once we consider virtual methods, a class is actually three things with
the same name:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;record type&lt;/strong&gt;: each object has the fields&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;module&lt;/strong&gt;: the type, trait, and other methods, are all in an encapsulated
module&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;trait&lt;/strong&gt; or &lt;strong&gt;interface&lt;/strong&gt;: the virtual methods form an interface&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; some programming languages consider all methods to be
virtual for some reason. For these programming languages, everything I
say still applies, but all methods are in the trait as they&amp;rsquo;re all virtual.&lt;/p&gt;
&lt;p&gt;Given that most methods aren&amp;rsquo;t self-consciously written with the intent
to be virtual, making methods implicitly virtual seems like a good way
to set the programmer up for surprise &amp;ndash; that is, a horrible idea. But
nevertheless having all virtual methods was for a long time considered
the more ideological, more purely OOP way to do things, and so languages
which strove to be purely OOP (like the original Java) did it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Up until now, we have ignored this additional conflation,
this additional role that a class plays. In discussing
&lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation/&#34;&gt;encapsulation&lt;/a&gt;, we were discussing simply
how classes conflate the two distinct concepts of record types and
modules. In discussing &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-2-polymorphism/&#34;&gt;polymorphism&lt;/a&gt;, we
were assuming interfaces, and discussing how OOP&amp;rsquo;s version of interfaces
were constrained by insisting on a specific dynamic implementation. Only
now, now that we discuss inheritance, do we see that OOP not only
conflates record types and modules, but it also conflates record types
and interfaces.&lt;/p&gt;
&lt;p&gt;When a class has virtual functions, that constitutes an interface,
implemented by dynamic polymorphism. But the only way you are allowed
to implement the interface is by inheriting from the class &amp;ndash; that is,
by also having a (secret, unnamed, implicit) field of the record type.&lt;/p&gt;
&lt;p&gt;See, as discussed above, inheriting from a class without virtual methods,
a class with just fields and regular methods, is no biggie. It&amp;rsquo;s just
a weird way of writing a has-a relationship that comes with some syntactic
sugar and automatic conversions &amp;ndash; things I&amp;rsquo;m not a fan of and wouldn&amp;rsquo;t
put in my programming language, but not that bad.&lt;/p&gt;
&lt;p&gt;Similarly, inheriting from a class without fields, a class with just
virtual methods (and perhaps regular methods, it turns out they barely
matter) is also no biggie. It has all the downsides of OOP-style
&lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-2-polymorphism/&#34;&gt;polymorphism&lt;/a&gt;, but is fundamentally just a
way to indicate that you&amp;rsquo;re implementing an interface. In languages like
C++, inheritance is the mechanism by which you implement interfaces,
and in languages like Java, a methods-only class should probably be an
interface.&lt;/p&gt;
&lt;p&gt;(To round out all the possibilities, I will mention that a class with
neither virtual methods nor fields is just a traditional module.)&lt;/p&gt;
&lt;p&gt;But if you have both fields and virtual methods, then you have true
OOP-style inheritance, with all of its problems. You have an interface
that you can only implement if you inherit from the class. If you did
not intend this, perhaps because you are writing in a language like
Java where allowing inheritance is the default for classes and virtual
is the default for methods, you are setting yourself up for surprises
when someone inherits from your class and starts overriding methods.&lt;/p&gt;
&lt;p&gt;If you did intend this, however, why? Why make implementing an interface
contingent on having certain state, on having a special unnamed field?
Why conflate these two fundamentally different concepts of containing
another record type&amp;rsquo;s state and having the new record implement an
interface?&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a number of problems with this conflation. Why would we assume
that in order to implement the methods, you need that state?  What if that
state is represented differently, like on a disk, or over a network, or as
mathematical consequences by a formula?  This conflation of implementation
and interface means that there is no sane way to implement proxy objects.&lt;/p&gt;
&lt;p&gt;But more importantly than that, I&amp;rsquo;m not entirely sure what the upside
of this conflation is. It seems to make programming simpler in one
particular scenario, a scenario that I rarely see come up in real life,
a scenario that frankly seems like a code smell.&lt;/p&gt;
&lt;h1 id=&#34;so-what-can-we-do-instead&#34;&gt;So what can we do instead?&lt;/h1&gt;
&lt;p&gt;There is no inheritance in Rust. There are no fields in traits. There is
simply no way of saying that in order to implement a trait, your type
must have certain fields. Rather than conflate the concepts of record
types, modules, and traits in this God-concept of &amp;ldquo;class,&amp;rdquo; Rust keeps
these three concepts quite separate.&lt;/p&gt;
&lt;p&gt;So if we have a design that requires inheritance (either because we think
in OOP or because we&amp;rsquo;re translating from an OOP programming language),
how would we represent that in Rust?&lt;/p&gt;
&lt;p&gt;Well, the most straight-forward way would be to separate out the
different parts of the base class. Such a refactor would allow us to
express our design in Rust, as literally as possible. This is just meant
as a starting point, a proof of concept that our design can survive
in a language without inheritance. Alternative, often better ways of
replacing inheritance will follow subseqeuntly.&lt;/p&gt;
&lt;p&gt;But here&amp;rsquo;s the straight-forward method: If the base class has just fields,
or just virtual methods, that&amp;rsquo;s easy: it becomes a &lt;code&gt;struct&lt;/code&gt; or a &lt;code&gt;trait&lt;/code&gt;,
respectively. Instead of inheriting from the class, a type would have that
&lt;code&gt;struct&lt;/code&gt; as a field, or implement that &lt;code&gt;trait&lt;/code&gt;. Actually, in this case,
the straight-forward method might just be perfect &amp;ndash; you weren&amp;rsquo;t actually
using inheritance per se, just an odd syntax for a field or for implementing
an interface.&lt;/p&gt;
&lt;p&gt;If it has both, we&amp;rsquo;d have to extract both a &lt;code&gt;struct&lt;/code&gt; and a &lt;code&gt;trait&lt;/code&gt;.
The fields would become a &lt;code&gt;struct&lt;/code&gt;, of its own type. The interface of the
virtual methods would become a trait.  The implementation of the virtual
methods would become the implementation of that trait for that &lt;code&gt;struct&lt;/code&gt;,
or provided methods on the trait, depending on what makes more sense. Any
non-virtual methods would then become methods of the &lt;code&gt;struct&lt;/code&gt; or provided
methods on the trait, again depending on what makes more sense in context.&lt;/p&gt;
&lt;p&gt;At this point, it might make sense to consider some of the alternatives
that Rust provides to run-time polymorphism, as discussed in the
&lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-2-polymorphism/&#34;&gt;polymorphism&lt;/a&gt; post. Is a trait, especially
an OOP-style, object-safe trait, really what we want here? We&amp;rsquo;ve opened
up alternative designs now, and perhaps one of the alternatives makes
more sense.&lt;/p&gt;
&lt;p&gt;Assuming we do want a trait, we can then go to all the &amp;ldquo;child&amp;rdquo; classes
and make them implement the trait. They also get a new field, perhaps
named &lt;code&gt;super&lt;/code&gt;, to contain the parent. Their trait implementations would
then do a mix of implementing new methods, calling the same method on
&lt;code&gt;super&lt;/code&gt;, and defaulting to the provided method.&lt;/p&gt;
&lt;p&gt;And again, at this point it would be appropriate to consider whether we
even need the &lt;code&gt;super&lt;/code&gt; field, or if perhaps we can get away with not
having it.&lt;/p&gt;
&lt;p&gt;After this transformation, we have valid Rust code out of our
inheritance-based OOP-style design pattern. But there&amp;rsquo;s nothing requiring
us to use Rust to do it: you could do the same refactor of inheritance
structures in an OOP language.&lt;/p&gt;
&lt;p&gt;If we were to do this transformation, we&amp;rsquo;ve paid a small cost of having
to potentially write &lt;code&gt;.super&lt;/code&gt; (or whatever name we&amp;rsquo;ve given the parent
field) every once in a while, as well as writing trait implementations
that forward some method calls to the &lt;code&gt;super&lt;/code&gt; field. In return, we&amp;rsquo;ve
deconflated the two very different concepts of interface and fields,
and opened ourselves up to more possibilities.&lt;/p&gt;
&lt;h1 id=&#34;what-should-i-actually-do-in-rust-instead-of-inheritance&#34;&gt;What should I actually do in Rust instead of inheritance?&lt;/h1&gt;
&lt;p&gt;But notice that in discussing this transformation, I encouraged you to
consider alternatives at two points. Rarely does this transformation make
sense literally, which is to say, rarely does a literal translation of
inheritance into Rust make sense. I find this quite telling, as it implies
to me that inheritance itself only rarely makes sense &amp;ndash; and indeed, I
only tend to use inheritance in OOP languages where a framework requires
me to, or as an &lt;em&gt;ersatz&lt;/em&gt;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; replacement of sum types (i.e. Rust &lt;code&gt;enum&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Here are some other patterns that replace inheritance hierarchies, that
you might find yourself considering instead:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A regular &lt;code&gt;enum&lt;/code&gt;. This actually covers most situations for me. Methods that
would be overriden just do a &lt;code&gt;match&lt;/code&gt; on the &lt;code&gt;enum&lt;/code&gt; contents, and methods
that would not, do not.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;struct&lt;/code&gt; types that contain a field with an &lt;code&gt;enum&lt;/code&gt; types.  The &lt;code&gt;enum&lt;/code&gt;
type represents all the different options, but the &lt;code&gt;struct&lt;/code&gt; type contains
the fields that are always the same.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MessageHeader&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    source: &lt;span style=&#34;color:#a6e22e&#34;&gt;Address&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    destination: &lt;span style=&#34;color:#a6e22e&#34;&gt;Address&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    seqnum: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MessageBody&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ping(PingMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Pong(PongMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Request(RequestMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Response(ResponseMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Message&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    header: &lt;span style=&#34;color:#a6e22e&#34;&gt;MessageHeader&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    body: &lt;span style=&#34;color:#a6e22e&#34;&gt;MessageBody&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Isn&amp;rsquo;t this so much nicer than putting &lt;code&gt;source&lt;/code&gt;, &lt;code&gt;destination&lt;/code&gt;, and
&lt;code&gt;seqnum&lt;/code&gt; in the base class?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;enum&lt;/code&gt; variants that themselves contain &lt;code&gt;enum&lt;/code&gt; types.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Message&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Client(ClientMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Server(ServerMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ClientMessage&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ping(PingMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Request(RequestMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ServerMessage&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Pong(PongMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Response(ResponseMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Error(ErrorMessage),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if you want any message, your type is &lt;code&gt;Message&lt;/code&gt;. If you know
for sure you have a client message, you can say &lt;code&gt;ClientMessage&lt;/code&gt;.
Or if you know for sure it&amp;rsquo;s specifically a ping, you can say
&lt;code&gt;PingMessage&lt;/code&gt;. It&amp;rsquo;s like a class hierarchy!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;struct&lt;/code&gt; with a template-parameterized member to set a policy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is perhaps the most sophisticated replacement. Imagine you
have a class &lt;code&gt;SocketHandler&lt;/code&gt; that handles reading from a socket.
Imagine it looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SocketHandler&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CircularBuffer socket_data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; data_available(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; fd);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;protected&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;virtual&lt;/span&gt; size_t message_size(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data, size_t size) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;virtual&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;process_message&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data, size_t size) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;How this is going to work is, &lt;code&gt;data_available&lt;/code&gt; is going to grab more and
more data from the socket &lt;code&gt;fd&lt;/code&gt; until &lt;code&gt;message_size&lt;/code&gt; returns a non-zero
value. Then, it&amp;rsquo;ll call &lt;code&gt;process_message&lt;/code&gt; with that data.  During this
time, it&amp;rsquo;ll store the data in &lt;code&gt;socket_data&lt;/code&gt;. All of that work is being
done by &lt;code&gt;data_available&lt;/code&gt;, in the parent class, and you can imagine
that the socket dispatching library has a collection of these
socket handlers, something like &lt;code&gt;std::vector&amp;lt;std::unique_ptr&amp;lt;SocketHandler&amp;gt;&amp;gt;&lt;/code&gt;
(or perhaps a map indexed by file descriptor).&lt;/p&gt;
&lt;p&gt;The child class is responsible for overriding &lt;code&gt;message_size&lt;/code&gt; and
&lt;code&gt;process_message&lt;/code&gt; to actually interpret incoming data for a specific
protocol. You&amp;rsquo;d have a child class for each &lt;code&gt;SocketHandler&lt;/code&gt; protocol,
and it would include internal state like sequence numbers, etc.&lt;/p&gt;
&lt;p&gt;But rather than have these methods overriden by a child class, the
right way to do it is to have just those methods in a trait that a
&lt;code&gt;SocketHandler&lt;/code&gt; has. You can see this when you extract the implicit
trait for &lt;code&gt;SocketHandler&lt;/code&gt; for the Rust version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;trait&lt;/span&gt; SocketProtocol {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;message_size&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self, data: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;[&lt;span style=&#34;color:#66d9ef&#34;&gt;u8&lt;/span&gt;]) -&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;usize&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;process_message&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self, data: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;[&lt;span style=&#34;color:#66d9ef&#34;&gt;u8&lt;/span&gt;]) -&amp;gt; Result&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SocketHandler&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;P: &lt;span style=&#34;color:#a6e22e&#34;&gt;SocketProtocol&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    buffer: &lt;span style=&#34;color:#a6e22e&#34;&gt;CircularBuffer&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    protocol: &lt;span style=&#34;color:#a6e22e&#34;&gt;P&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;trait&lt;/span&gt; SocketHandlerTrait {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;data_available&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self, fd: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;) -&amp;gt; Result&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;P: &lt;span style=&#34;color:#a6e22e&#34;&gt;SocketProtocol&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; SocketHandlerTrait &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; SocketHandler&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;P&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;data_available&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self, fd: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;) -&amp;gt; Result&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// Call `self.protocol.message_size/process_message`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, rather than each socket protocol inheriting from socket handler,
with its common state, the socket handler &lt;em&gt;has a&lt;/em&gt; socket protocol, as
a policy. The &lt;code&gt;SocketProtocol&lt;/code&gt; trait here can then be a compile-time,
static trait and &lt;code&gt;SocketHandlerTrait&lt;/code&gt; can be the object-safe, dynamic
one, and the &lt;code&gt;std::vector&amp;lt;std::unique_ptr&amp;lt;SocketHandler&amp;gt;&amp;gt;&lt;/code&gt; can
be replaced with &lt;code&gt;Vec&amp;lt;Box&amp;lt;dyn SocketHandlerTrait&amp;gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This last refactor can be generalized. Instead of inheriting from
a base class to implement specific functionality, inject that
functionality using policies&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;, and parameterize the &lt;code&gt;struct&lt;/code&gt; with members that implement policy traits.
Then, if need be (and need might not be) write a separate dynamic trait
for the overall &lt;code&gt;struct&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I know my &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-2-polymorphism&#34;&gt;last post&lt;/a&gt; hasn&amp;rsquo;t been
since February. I&amp;rsquo;ve been procrastinating this one for a long time,
mostly because my life has been so gosh-darn busy, and also mostly
because I don&amp;rsquo;t really instinctively remember what I (or anyone else)
really liked about inheritance to begin with.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Isn&amp;rsquo;t it weird that &lt;em&gt;ersatz&lt;/em&gt; means replacement in German, but
means mediocre as a replacement in English, so that &amp;ldquo;ersatz replacement&amp;rdquo;
doesn&amp;rsquo;t mean &amp;ldquo;replacement replacement&amp;rdquo; but &amp;ldquo;mediocre replacement&amp;rdquo;?
Or am I using the English word wrong?&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Policies are known in Gang of Four terminology as
&lt;a href=&#34;https://en.wikipedia.org/wiki/Strategy_pattern&#34;&gt;strategies&lt;/a&gt;. I&amp;rsquo;ve touched
on the policy pattern in some &lt;a href=&#34;https://www.thecodedmessage.com/posts/endian_polymorphism/&#34;&gt;previous&lt;/a&gt;
&lt;a href=&#34;https://www.thecodedmessage.com/posts/multiparadigm/&#34;&gt;posts&lt;/a&gt;, and at some point should write a full
post about it, as policies are my favorite thing.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
      <title>Endianness, and why I don&#39;t like htons(3) and friends</title>
      <link href="https://www.thecodedmessage.com/posts/endianness/" />
      <id>https://www.thecodedmessage.com/posts/endianness/</id>
      <updated>2023-10-19T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Endianness is a long-standing headache for many a computer science
student, and a thorn in the side of practitioners. I have already
&lt;a href=&#34;https://www.thecodedmessage.com/posts/endian_polymorphism/&#34;&gt;written some about it&lt;/a&gt; in a different
context. Today, I&amp;rsquo;d like to talk more about how to deal with endianness
in programming languages and APIs, especially how to deal with it
in a principled, type-safe way.&lt;/p&gt;
&lt;p&gt;Before we get to that, I want to make some preliminary clarifications
about endianness, which will help inform our API design.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Endianness is a long-standing headache for many a computer science
student, and a thorn in the side of practitioners. I have already
&lt;a href=&#34;https://www.thecodedmessage.com/posts/endian_polymorphism/&#34;&gt;written some about it&lt;/a&gt; in a different
context. Today, I&amp;rsquo;d like to talk more about how to deal with endianness
in programming languages and APIs, especially how to deal with it
in a principled, type-safe way.&lt;/p&gt;
&lt;p&gt;Before we get to that, I want to make some preliminary clarifications
about endianness, which will help inform our API design.&lt;/p&gt;
&lt;h1 id=&#34;why-little-endian-bugs-us&#34;&gt;Why Little Endian Bugs Us&lt;/h1&gt;
&lt;p&gt;New students often are more confused by little endian (where the
least-significant component of an integer is stored first), and until
they are told about it, they tend to assume computers are big endian
(where the most-significant component is stored first) even if they don&amp;rsquo;t
know that word. This is due primarily to the fact that big endian is what
they&amp;rsquo;re used to: We write numbers with the most significant digit on the
left, and in languages that write from left to write (including English,
the &lt;em&gt;lingua franca&lt;/em&gt; of programming among other things), this means that
we live our day to day lives in big endian. But that doesn&amp;rsquo;t mean that
big endian is more logical in any way, just that it is more conventional.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t helped by the fact that many learners are first exposed to
little endian by it being confusing, and making them do more cognitive
work, by reading little endian numbers from a hex dump. Take, for example,
this code, which displays a 32-bit number in hexadecimal, and then displays
the individual bytes of the same number as a hex dump:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; number &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0x12345678&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%08X&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, number);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;memcpy&lt;/span&gt;(bytes, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;number, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%02X %02X %02X %02X&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;], bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;], bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;], bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This results in this befudding output:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;12345678
78 56 34 12
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When read as a number, we can just read the number normally.
However, when read as a series of bytes, we find ourselves having
to read the number from right to left to read the number as big
endian, as we are accustomed to doing. We can&amp;rsquo;t even just read
backwards, however, as each byte is still printed internally
according to our big endian convention: the higher-order hex digit
is still printed first, followed by the lower-order hex digit.&lt;/p&gt;
&lt;p&gt;The problem here isn&amp;rsquo;t little endian. The problem is that the printing
functionality accommodates our big endian preference in printing, but
only at the level of printing an individual number, either as a byte
or as a 32-bit word. The word printed as a whole is printed big
endian, to accommodate us. The individual bytes are also printed
big endian, to accommodate us. However, the hex dump as a whole
is printed with the lower values on the left, and the higher values
on the right, to similarly accommodate our values that lower-indexed
memory, memory that comes earlier, should be on the left. On a little
endian system, this desire to print each number with the most
significant digit on the left, but to print a sequence of numbers
from left to right, leads to the contradiction. The resulting
last line, &lt;code&gt;78 56 34 12&lt;/code&gt;, isn&amp;rsquo;t, properly speaking, little endian.
The print-out is an odd type of mixed endian, due to our awkward
conventions.&lt;/p&gt;
&lt;p&gt;There is actually a relatively easy fix: if we insist on reading
numbers with the most significant digit on the right (which we do),
and the computer insists on storing less significant components
first (which it does), these two desires can be reconciled by printing
the hex dump from right to left:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; number &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0x12345678&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%08X&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, number);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;memcpy&lt;/span&gt;(bytes, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;number, &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;%02X %02X %02X %02X&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;], bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;], bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;], bytes[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This results in a much cleaner print-out:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;12345678
12 34 56 78
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This should make clear that the weirdness of little endian is
entirely due to our preference for big endian, and our preference for
listing the lower-indexed values to the left, and how these preferences
interact. It is because of human conventions, not because of any intrinsic
problem with little endian. I would argue that, on little endian systems,
all hex dumps should be right to left, and that would help, but there is
little I can do to change the conventions of this.&lt;/p&gt;
&lt;p&gt;Now, almost all modern systems are little endian, either because they are
typically configured that way for processors that support either endianness,
or because they only support little endian, like Intel processors. The
few programmers who have to write code for big endian systems find themselves
in the minority, and find themselves doing extra work to deal with other
code that no longer accommodates big endianness.&lt;/p&gt;
&lt;p&gt;There is one big exception to this: the Internet. All of the Internet
protocols are designed to use big endian ordering, known in this context
as &amp;ldquo;network byte ordering.&amp;rdquo; This is because when the Internet protocols
were developed, big endian was a viable rival to little endian, and
both byte orders were common.&lt;/p&gt;
&lt;p&gt;This does make some sense, as well, because hex dumps of packets are very
common, and big endian does make those hex dumps easier to read and reckon
with for us big endian humans.&lt;/p&gt;
&lt;h1 id=&#34;when-endianness-comes-in&#34;&gt;When Endianness Comes In&lt;/h1&gt;
&lt;p&gt;I would also like to clarify something about how endianness works.
A 32-bit word in a register in the processor is neither big endian
nor little endian. The processor needs to be designed knowing which
bits are more significant, and which are less, but there is no
intrinsic way in which the less significant bits come &amp;ldquo;first.&amp;rdquo;
In a word-based memory system, where only entire words were stored
in memory (like the PDP-7 was with its 16-bit words), and where
it was impossible to address memory in terms of individual bytes,
this would be the end of it.&lt;/p&gt;
&lt;p&gt;As an example of this, see the documentation for
&lt;a href=&#34;https://en.cppreference.com/w/cpp/types/endian&#34;&gt;&lt;code&gt;std::endian&lt;/code&gt;&lt;/a&gt;
on &lt;a href=&#34;https://en.cppreference.com/&#34;&gt;CppReference.com&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If all scalar types have &lt;code&gt;sizeof&lt;/code&gt; equal to 1, endianness does not matter
and all three values, &lt;code&gt;std::endian::little&lt;/code&gt;, &lt;code&gt;std::endian::big&lt;/code&gt;, and
&lt;code&gt;std::endian::native&lt;/code&gt; are the same.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;However, once we come up with the idea that memory is made up of bytes,
the endianness question arises: How do we split this 32-bit number into
bytes? Which end of it should be byte 0, and which end byte 3? Similarly,
if we read a series of bytes into memory, where should the first byte
(by memory address) go in the register, the most significant (big)
end, or the least significant (little) end?&lt;/p&gt;
&lt;p&gt;As a result, types like &lt;code&gt;uint32_t&lt;/code&gt; (and &lt;code&gt;uint16_t&lt;/code&gt; and &lt;code&gt;uint64_t&lt;/code&gt;) have no
intrinsic endianness, so long as they are stored in registers.  Only if
they are written to memory, or read from memory, does their endianness
matter. And then, it only matters if the actual byte representation is
important &amp;ndash; if we, as in the code above, use &lt;code&gt;memcpy&lt;/code&gt; to copy their
representation, byte by byte, into an array of bytes.&lt;/p&gt;
&lt;p&gt;In general, if the byte representation does matter, I would argue that
&lt;code&gt;uint32_t&lt;/code&gt; should be treated as an abstract 32-bit value, devoid of
endianness. Only when it is transcribed as a series of bytes should
endianness be taken into account &amp;ndash; and then the description should
instead have the type of &lt;code&gt;uint8_t[4]&lt;/code&gt; in C (or &lt;code&gt;std::array&amp;lt;uint8_t, 4&amp;gt;&lt;/code&gt;
in C++ or &lt;code&gt;[u8; 4]&lt;/code&gt; in Rust).&lt;/p&gt;
&lt;h1 id=&#34;the-main-argument-why-i-dislike-htons-and-friends&#34;&gt;The Main Argument: Why I dislike &lt;code&gt;htons&lt;/code&gt; and friends&lt;/h1&gt;
&lt;p&gt;In C, however, we do not in fact do this. We instead have functions
like &lt;code&gt;htons&lt;/code&gt;, with this signature:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;htons&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; hostshort);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; http_port &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;htons&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;80&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function purports to convert a 16-bit number from host endianness
(typically little) to network endianness (always big). Assuming a little
endian computer, it does a byteswap: It swaps the less significant 8
bits with the more significant 8 bits in the register used to return
the &lt;code&gt;uint16_t&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So what are the properties of the returned &lt;code&gt;uint16_t&lt;/code&gt;? If we passed in,
for example, 80 (the port of HTTP), &lt;code&gt;http_port&lt;/code&gt;, the new &lt;code&gt;uint16_t&lt;/code&gt; is
20480 &amp;ndash; because 80 is &lt;code&gt;0x0050&lt;/code&gt; in hex, and we&amp;rsquo;ve swapped the two bytes,
so we now have &lt;code&gt;0x5000&lt;/code&gt;. What is this number?&lt;/p&gt;
&lt;p&gt;It is not, to be clear, a &lt;code&gt;uint16_t&lt;/code&gt; value 80 that is now in &amp;ldquo;big endian,&amp;rdquo;
though we might say that as a manner of speaking. It is almost certainly
in a register, and as mentioned before, registers don&amp;rsquo;t have intrinsic
endianness. It is something far more awkward: It is a value that, if
we were to store it in little endian (the only option), results in a
different number being stored in big endian.&lt;/p&gt;
&lt;p&gt;To expand on this: 20480 is not a particularly meaningful number. It is
not actually the port number we want to use. And it has nothing to do
with the actual number 20480. It is simply a number that, if we store
it in memory as bytes, will result in &lt;code&gt;0x00&lt;/code&gt; being stored, followed by
&lt;code&gt;0x50&lt;/code&gt; &amp;ndash; the big endian representation of 80. It is a &lt;code&gt;uint16_t&lt;/code&gt; with
a value chosen not for what number we want to store, but what bytes we
will get if we store &lt;code&gt;http_port&lt;/code&gt; as bytes.&lt;/p&gt;
&lt;p&gt;Since &lt;code&gt;uint16_t&lt;/code&gt; is designed to store numbers, not collections of bytes,
I would argue that this type is not being used in a semantically honest
way &amp;ndash; it is a lie. What we are really storing is an array of 2 bytes,
2 &lt;code&gt;uint8_t&lt;/code&gt;s. We are storing it in a 16-bit register, and implementation-wise
that might be a good decision &amp;ndash; but I would argue, if we want that to
be possible, we should create an ABI where &lt;code&gt;uint8_t[2]&lt;/code&gt; should be storable
in a single register. The C programming languages, by not making arrays
first-class types, is getting in our way here, which explains
the situation.&lt;/p&gt;
&lt;p&gt;Am I exaggerating when I say the type is a lie? Well, we expect to be
able to do arithmetic on a &lt;code&gt;uint16_t&lt;/code&gt;, to be able to test, for example,
whether it is less than 1024, as listening on a port less than 1024 is
a privileged operation. But in order to do that, we have to convert
it back to a normal &lt;code&gt;uint16_t&lt;/code&gt; &amp;ndash; all &lt;code&gt;uint16_t&lt;/code&gt;&amp;rsquo;s usual arithmetic
operators are inappropriate for data that&amp;rsquo;s stored with its bytes
swapped around.&lt;/p&gt;
&lt;p&gt;So what should be done? Well, if we really intend to express a value
in network byte order, e.g. big endian, we are changing the semantics
of the information from &amp;ldquo;this is a 16-bit integer&amp;rdquo; to &amp;ldquo;this is a specific
sequence of two bytes, chosen for a reason.&amp;rdquo; Therefore, the return
value of htons should be an aggregate of two bytes.&lt;/p&gt;
&lt;p&gt;Again, because of pointer decay this is impossible to express
straight-forwardly in C, although a wrapper struct could be used.
C++ takes care of this by having a built-in wrapper struct for
arrays, namely &lt;code&gt;std::array&lt;/code&gt;. The equivalent of &lt;code&gt;htons&lt;/code&gt; would
not emphasize that the &lt;code&gt;uint16_t&lt;/code&gt; is in the host order (which I
think is the wrong way of thinking about it), but would simply
indicate that we&amp;rsquo;re just storing this short in a big-endian
fashion (as opposed to the hardware-supported default storage
we can access with a &lt;code&gt;memcpy&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;array&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; store_short_as_big_endian(&lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt; value);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rust already provides this as an alternative:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u16&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;to_be_bytes&lt;/span&gt;(self) -&amp;gt; [&lt;span style=&#34;color:#66d9ef&#34;&gt;u8&lt;/span&gt;; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unfortunately for semantics, Rust still has the problematic
signature for &lt;code&gt;to_be&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u16&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;to_be&lt;/span&gt;(self) -&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u16&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Perhaps this is due to efficiency reasons, or felt efficiency.
Programmers know that this byteswapped value should, for performance,
be stored in a single register. Programmers can feel more confident
that this is actually done if it remains a &lt;code&gt;u16&lt;/code&gt; (or &lt;code&gt;uint16_t&lt;/code&gt;) than
if it is transformed into an array of bytes, however semantically
inappropriate the &lt;code&gt;u16&lt;/code&gt; is.&lt;/p&gt;
&lt;p&gt;However, if we are using a &lt;code&gt;u16&lt;/code&gt; or &lt;code&gt;uint16_t&lt;/code&gt; as an implementation layer
for what is in fact a way of storing two bytes in the opposite order
than the one that makes sense for our processor, if we are using it as
an implementation trick to do something semantically different from what
a &lt;code&gt;uint16_t&lt;/code&gt; normally does, then we should at least make the type distinct
to give the maintenance programmer and compiler some ability to avoid
letting us do non-sensical things (like comparing the value using
&lt;code&gt;uint16_t&lt;/code&gt;&amp;rsquo;s comparison operator).&lt;/p&gt;
&lt;p&gt;Luckily, there is a design pattern for using the implementation of a
type, but applying different semantics to it: the newtype pattern. We
typically think of it as a Haskell or Rust thing, but we can use it in
C++ as well. I would argue that if we&amp;rsquo;re going to abuse &lt;code&gt;uint16_t&lt;/code&gt;s
and friends in such a way, we should at least abstract it using the
newtype pattern. In C++, this would look something like this, assuming
a little endian computer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;template&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typename&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;big_endian&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    T value;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    big_endian() &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    big_endian&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;operator&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; big_endian&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    big_endian(T in) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; in;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    big_endian&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;operator&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;(T in) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        value &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;byteswap(in);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;byteswap(value);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Adding appropriate &lt;code&gt;if constexpr&lt;/code&gt; expressions to also support
big endian machines, and defining &lt;code&gt;std::byteswap&lt;/code&gt; if you don&amp;rsquo;t
have it yet on your system is left as an exercise to the reader.&lt;/p&gt;
&lt;p&gt;But it works on my (little endian) system:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int main() {
    big_endian&amp;lt;uint16_t&amp;gt; be = 80;
    std::array&amp;lt;uint8_t, 2&amp;gt; be_bytes;
    memcpy(be_bytes.data(), &amp;amp;be, 2);
    printf(&amp;#34;%04X\n&amp;#34;, uint16_t(be));
    printf(&amp;#34;%02X %02X\n&amp;#34;, be_bytes[0], be_bytes[1]);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I would much rather use this to represent &amp;ldquo;we want to store a value
in a register byte-swapped on some platforms&amp;rdquo; than a &lt;code&gt;uint16_t&lt;/code&gt; with
no additional type information. You cannot accidentally run invalid
&lt;code&gt;uint16_t&lt;/code&gt; operators on it, but you can convert it to a normal &lt;code&gt;uint16_t&lt;/code&gt;
first and then use those operators. However, it does have a big endian
representation when stored, as indicated by the &lt;code&gt;memcpy&lt;/code&gt;, and it can still
be stored in a single register.&lt;/p&gt;
&lt;p&gt;Even so, I would still not prioritize that ability to store it in a
single register in most situations. Using a &lt;code&gt;uint16_t&lt;/code&gt; to store the
bytes swapped is still not remotely &amp;ldquo;storing a big endian value in a
&lt;code&gt;uint16_t&lt;/code&gt;,&amp;rdquo; it is &amp;ldquo;storing a big endian representation in a &lt;code&gt;uint16_t&lt;/code&gt;
so that when the processor writes that &lt;code&gt;uint16_t&lt;/code&gt; little endian, we get
a big endian representation of the number we actually want.&amp;rdquo; It&amp;rsquo;s still
fundamentally a hack for performance, and while I&amp;rsquo;m comfortable with
it contained within the encapsulation of this &lt;code&gt;little_endian&lt;/code&gt; class,
I would still rather actually write &lt;code&gt;std::array&amp;lt;uint8_t, sizeof(T)&amp;gt;&lt;/code&gt; as
the underlying storage type, unless the optimization is actually needed.
I actually would use a &lt;code&gt;big_endian&lt;/code&gt; class that would look more like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;template &amp;lt;typename T&amp;gt;
class big_endian {
    std::array&amp;lt;uint8_t, sizeof(T)&amp;gt; be_representation;

    static void swap_array(std::array&amp;lt;uint8_t, sizeof(T)&amp;gt; &amp;amp;arr) {
        for (auto it = arr.begin(), jt = arr.end() - 1;
             it &amp;lt; jt;
             ++it, --jt) {
            std::swap(*it, *jt);
        }
    }
public:
    big_endian() = default;
    big_endian&amp;amp; operator=(const big_endian&amp;amp;) = default;

    big_endian(T in) {
        *this = in;
    }

    big_endian&amp;amp; operator=(T in) {
        memcpy(be_representation.data(), &amp;amp;in, sizeof(T));
        swap_array(be_representation);
        return *this;
    }

    operator T() {
        auto bytes_copy = be_representation;
        swap_array(bytes_copy);
        T out;
        memcpy(&amp;amp;out, bytes_copy.data(), sizeof(T));
        return out;
    }
};
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This now feels like I&amp;rsquo;m actually representing accurately what a big
endian representation is: a way of storing a number as a sequence
of bytes, rather than however the processor feels like storing it,
and certainly rather than as a value that the processor will store
as little endian, but which will store the value we actually want
to store as big endian. I won&amp;rsquo;t lie and say the optimizer will
make it equally performant, and if I needed to actually optimize
I would use the other version, but I feel like this version is hack-free.
(Again, it still only works on little endian platforms &amp;ndash; fixing this
is again left as an exercise.)&lt;/p&gt;
&lt;p&gt;This version has the added benefit of having an alignment of 1, which I
will argue later is more appropriate than using the underlying alignment
of &lt;code&gt;uint16_t&lt;/code&gt;, &lt;code&gt;uint32_t&lt;/code&gt;, etc.&lt;/p&gt;
&lt;h1 id=&#34;using-these-big-endian-types&#34;&gt;Using These &amp;ldquo;Big Endian&amp;rdquo; Types&lt;/h1&gt;
&lt;p&gt;This leads to a further question, however: When do we need to support
network byte order? Really, the only time is when generating messages
in wire format to send over the network. In C and C++, we generally
represent messages to be sent over the network as &lt;code&gt;struct&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;For example, one can imagine a packet format with a 32-bit sequence
number. We would want to write &lt;code&gt;uint32_t&lt;/code&gt; for this sequence number:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__attribute__((packed))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;packet_wire_format&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; from_device;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; to_device;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; sequence_number;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, of course, if it is in big endian byte ordering (as many
protocols are), we then have to call &lt;code&gt;htonl&lt;/code&gt; when loading this value
in:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;packet_wire_format packet;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; seq_num &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; current_seqnum&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;packet.sequence_number &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; htonl(seq_num);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As I said before, I don&amp;rsquo;t like &lt;code&gt;htonl&lt;/code&gt;. I certainly don&amp;rsquo;t like
using &lt;code&gt;uint32_t&lt;/code&gt; as the type for &lt;code&gt;sequence_number&lt;/code&gt;. So, we can do one of
two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can use a Rust-style function to convert to byte representation,
and use &lt;code&gt;std::array&amp;lt;uint8_t, 4&amp;gt;&lt;/code&gt; as the type of &lt;code&gt;sequence_number&lt;/code&gt;.
This strikes me as equally awkward. We now know that we need to do
soemthing other than just assign the value, but we don&amp;rsquo;t know what
that thing is, necessarly.&lt;/li&gt;
&lt;li&gt;We can make the type more semantic, and use our &lt;code&gt;big_endian&lt;/code&gt;
wrapper. This is the purpose why I wrote it, and the use case where
it makes sense it has an alignment of 1 &amp;ndash; wire format structures
are often packed.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;__attribute__((packed))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// ^^ You may need to add this to `little_endian` as well,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// or you may not need it at all now
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;packet_wire_format&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; from_device;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; to_device;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    big_endian&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; sequence_number;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, when we actually send it over the wire, we will cast or copy
this &lt;code&gt;packet_wire_format&lt;/code&gt; to get the byte-by-byte representation,
and &lt;code&gt;sequence_number&lt;/code&gt; will be in big endian, by the invariants
of our &lt;code&gt;big_endian&lt;/code&gt; class. We will not need to remember to call
any function at all, as the class&amp;rsquo;s interface provides us with
only appropriate options:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;packet_wire_format packet;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; seq_num &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; current_seqnum&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;packet.sequence_number &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; seq_num; &lt;span style=&#34;color:#75715e&#34;&gt;// Performs conversion
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The fewer mistakes you can make by accident, the better.
And of course, this has the additional advantage that the
type of the wire format is more self-documenting.&lt;/p&gt;
&lt;p&gt;Similarly, if you read or write from the wire format using
read and write methods on a buffer type, those methods should
either be parameterized to take endian information along with
the values, or you can pass objects of type &lt;code&gt;big_endian&lt;/code&gt;
as the value to be copied in: &lt;code&gt;big_endian&amp;lt;uint32_t&amp;gt;&lt;/code&gt; is just
as trivially-copyable as &lt;code&gt;uint32_t&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;conclusions-and-loose-ends&#34;&gt;Conclusions and Loose Ends&lt;/h1&gt;
&lt;p&gt;It is a little more awkward to write &lt;code&gt;big_endian&lt;/code&gt; for Rust.
I would want to use the existing &lt;code&gt;to_be_bytes&lt;/code&gt; method in the
implementation, and unfortunately that method is not in any
trait, as I&amp;rsquo;ve &lt;a href=&#34;https://www.thecodedmessage.com/posts/endian_polymorphism/&#34;&gt;complained about before&lt;/a&gt;.
This can easily be remedied by writing our own trait, however,
or using external crates that already do so.&lt;/p&gt;
&lt;p&gt;However, I wonder if maybe all of these languages should define types
that correspond to &lt;code&gt;uint16_t&lt;/code&gt;, &lt;code&gt;uint32_t&lt;/code&gt; etc, and just are defined to
store themselves in network byte order (and perhaps another one that
guarantees little endian order). After all, most processors support
byteswap instructions, that make writing a value as a byteswap an easy
operation. They could be optimized as normal values unless actually
written to memory &amp;ndash; and only the optimizer knows when they&amp;rsquo;re actually
written to memory. They could even be written to memory in native
endianness unless there&amp;rsquo;s some defined way to get a byte-by-byte pointer
to them &amp;ndash; and really only the optimizer knows that.&lt;/p&gt;
&lt;p&gt;Endianness seems more a configuration on the natural types of the
programming language than it does something to be implemented on
top of these natural tools. These loops I&amp;rsquo;m using to do byteswaps
are surely not the most efficient way to do it (which is why the
non-array based implementation of &lt;code&gt;big_endian&lt;/code&gt; is surely more
performant even if it is hackish), because processors have some
support for non-native endianness baked in. If a C++ vendor
provided types like &lt;code&gt;big_endian&lt;/code&gt; (and perhaps some do, I&amp;rsquo;m sure I&amp;rsquo;ll
find out in the comments) it would surely be more performant.&lt;/p&gt;
&lt;p&gt;But again, perhaps they should be primitive types. There&amp;rsquo;s some built-in
processor support for them, and only the optimizer knows when the
non-native endianness actually should be used.&lt;/p&gt;
&lt;p&gt;I am too busy a person to do the research for such a proposal. I don&amp;rsquo;t
know if such a proposal exists. My interest here is simply in using the
tools I have to be a good programmer. For that, &lt;code&gt;to_be_bytes&lt;/code&gt; and
my implementation of &lt;code&gt;big_endian&lt;/code&gt; will simply have to suffice.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Operating Systems: What is the command line?</title>
      <link href="https://www.thecodedmessage.com/posts/command-line/" />
      <id>https://www.thecodedmessage.com/posts/command-line/</id>
      <updated>2023-10-08T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;This is my newest post in my series about &lt;a href=&#34;https://www.thecodedmessage.com/tags/operating-systems/&#34;&gt;operating
systems&lt;/a&gt;. Yes, it was last updated in 2019 &amp;ndash;
I&amp;rsquo;m a hobbyist blogger. This is a post about the command line, a computer
topic, but it is for educating a non-technical (but tech-curious)
audience. Most of the programmers in my audience will already know
everything I have to say, and may be bored by some explanation of things
they already know, though I intend to discuss some technical details of
how computers work.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;This is my newest post in my series about &lt;a href=&#34;https://www.thecodedmessage.com/tags/operating-systems/&#34;&gt;operating
systems&lt;/a&gt;. Yes, it was last updated in 2019 &amp;ndash;
I&amp;rsquo;m a hobbyist blogger. This is a post about the command line, a computer
topic, but it is for educating a non-technical (but tech-curious)
audience. Most of the programmers in my audience will already know
everything I have to say, and may be bored by some explanation of things
they already know, though I intend to discuss some technical details of
how computers work.&lt;/p&gt;
&lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; a tutorial on how to use the command line on any
particular operating system. Rather, it is a discussion of the role that
a command line plays in a modern operating system and why some people
(including me) still use that kind of interface.&lt;/p&gt;
&lt;p&gt;As I&amp;rsquo;ve &lt;a href=&#34;https://www.thecodedmessage.com/posts/org4-desktop/&#34;&gt;explained before&lt;/a&gt;, I often use my computer
through the command line. It is a major part of but not the entirety of how
I interact with it. I do this so much that people looking at my computer
will assume I&amp;rsquo;m programming even when I&amp;rsquo;m not &amp;ndash; even when I&amp;rsquo;m working on
my blog, or another writing project, or even just organizing my pictures.&lt;/p&gt;
&lt;p&gt;Here is a screenshot of a command line session:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/cli.png&#34; alt=&#34;Command Line Screenshot&#34;&gt;&lt;/p&gt;
&lt;h1 id=&#34;graphical-user-interfaces&#34;&gt;Graphical User Interfaces&lt;/h1&gt;
&lt;p&gt;This is (as you likely know since you&amp;rsquo;re reading this on a website) no
longer the normal way to interact with computers.  Nowadays, we usually
interact with computers through &lt;em&gt;graphical user interfaces (GUIs)&lt;/em&gt;, and
many people take them for granted. We access applications&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; through
each having their own window &amp;ndash; or, for web applications, we can combine
them into one window via browser tabs.&lt;/p&gt;
&lt;p&gt;We navigate these applications through the mouse, or touchpad. Scrolling
and clicking to find our way through the document, right-clicking or
navigating menus to find further options, and occasionally interacting
with a &amp;ldquo;dialog box&amp;rdquo; to specify details. All features are expected to
be &lt;em&gt;discoverable&lt;/em&gt;, that is to say, we expect to be able to find them
in a menu, a toolbar, a right-click menu, or by navigating the dialog
boxes we reveal through these other things. If we cannot discover
a feature by these mechanisms, we can reasonably assume the application
does not have this feature.&lt;/p&gt;
&lt;p&gt;Here is LibreOffice Calc, a (somewhat old-fashioned) GUI program:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/lo-calc.png&#34; alt=&#34;LibreOffice Calc Screenshot&#34;&gt;&lt;/p&gt;
&lt;p&gt;Nowadays, applications often run inside web browsers. This principle
of discoverability is still considered important. Here is Google Docs,
an application running inside a web browser:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/google-docs.png&#34; alt=&#34;Google Docs Screenshot&#34;&gt;&lt;/p&gt;
&lt;p&gt;These are both mouse-navigated programs with discoverable features. For
both of these applications, there are many visible ways to interact
with them. If you want to find a feature, looking through what&amp;rsquo;s right
in front of you is the way to go.&lt;/p&gt;
&lt;h1 id=&#34;the-command-line-in-brief&#34;&gt;The Command Line in Brief&lt;/h1&gt;
&lt;p&gt;The command line works differently.&lt;/p&gt;
&lt;p&gt;Nowadays, the command line is usually accessed via a window within
the context of a graphical &lt;em&gt;desktop environment&lt;/em&gt;&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;, but in the olden
days, people interacted with computers via dumb terminals that couldn&amp;rsquo;t
display images, just text&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/dumb-terminal.png&#34; alt=&#34;Dumb Terminal&#34;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;It was a dummy terminal, and I was a dummy user.&amp;rdquo;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A member of the Baby Boomer generation describing what it was like to
be a person in a non-IT role using Unix in the 80s.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Instead of being able to find various features via menus visible
on the screen, you are instead given a &lt;em&gt;prompt&lt;/em&gt;, an indication
of the current state of your session that is, well, prompting you
to tell the computer what to do, to give it a command:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/prompt.png&#34; alt=&#34;Prompt&#34;&gt;&lt;/p&gt;
&lt;p&gt;You can then type your command, maybe a few more.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/cli.png&#34; alt=&#34;Command Line Screenshot&#34;&gt;&lt;/p&gt;
&lt;p&gt;As you type commands, the output of the commands displays on the
subsequent lines. When you hit the bottom of the screen, the screen
scrolls up. Most terminal emulators let you scroll the window to see
earlier parts of the transcript. A command might also prompt for additional
input, or take full control of the terminal emulator and provide a different
type of (still text-based) interface entirely.&lt;/p&gt;
&lt;p&gt;If you type a bad command, it is not very helpful:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/bad-command.png&#34; alt=&#34;Bad commands&#34;&gt;&lt;/p&gt;
&lt;p&gt;There is no discoverability. There are no hints as to what commands might
be accepted. You can use the command line to find out more information
about what commands are accepted, but you have to know the commands to do
that. In practice, you have to learn a minimal set of commands from a book
(or nowadays, a website) before you can actually do anything productive.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not intentionally user-unfriendly. For example, on Linux, there
are commands like &lt;code&gt;man&lt;/code&gt; (for &amp;ldquo;manual&amp;rdquo;) that explain what commands do,
and commands like &lt;code&gt;apropos&lt;/code&gt; to search for useful commands. Here is the
manual page for the &lt;code&gt;man&lt;/code&gt; command itself:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/man.png&#34; alt=&#34;Man Manual&#34;&gt;&lt;/p&gt;
&lt;p&gt;Additionally, once you know the name of a command or utility, you
can generally find out more about how to use it by passing &lt;code&gt;-?&lt;/code&gt; or
&lt;code&gt;--help&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/apt-help.png&#34; alt=&#34;Apt Help&#34;&gt;&lt;/p&gt;
&lt;p&gt;Command lines are available on all modern operating systems for personal
computing: Windows, macOS, Linux, and certainly any other Unix you might
have running. They tend not to be available on mobile OSes.&lt;/p&gt;
&lt;h1 id=&#34;what-is-the-command-line-not&#34;&gt;What is the command line not?&lt;/h1&gt;
&lt;p&gt;Before we talk about what this is for, and why modern operating systems
still support this decidedly old-fashioned way of interacting with them,
I want to dispel some myths and misconceptions about the command line,
specifically two opposite misconceptions that seem to still be common
amongst the computer laity.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Misconception One:&lt;/strong&gt; The command line is literally DOS, the
Microsoft operating system from the 80&amp;rsquo;s and early 90&amp;rsquo;s.
It is there to support old programs from the 80&amp;rsquo;s and early 90&amp;rsquo;s,
and exists solely for the support of obsolete and obsolescent software.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This misconception is common among Windows users, because it used to be
true. Until Windows XP, Windows still came bundled and intertwined with
a version of Microsoft&amp;rsquo;s older, fully command-line operating system,
DOS. Old DOS programs were still in common use, and people needed a way
to run them, so they could run a copy of DOS inside a window.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not true anymore, however. Windows is no longer a chimera of DOS
and more modern components. Since Windows XP, both the consumer and
business versions of the Windows brand have been versions of &lt;a href=&#34;https://en.wikipedia.org/wiki/Windows_NT&#34;&gt;&lt;em&gt;Windows
NT&lt;/em&gt;&lt;/a&gt;, a different operating
system from earlier consumer versions of Windows, one originally targeted
at business users, with no DOS code in it at all.&lt;/p&gt;
&lt;p&gt;On a modern Windows computer, the command line is not primarily for
DOS programs. The ability to run DOS programs isn&amp;rsquo;t even shipped with
Windows by default anymore, but the command line still is. The confusion
is understandable, because the command line still &lt;em&gt;looks like&lt;/em&gt; the DOS
command line. The prompt is still a form of DOS&amp;rsquo;s famous &lt;code&gt;C:\&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;What is the command line for, then? It is for running modern Windows
programs that happen to be designed to be used from the command
line. Windows comes with a bunch of such programs, for things like systems
and network administration.&lt;/p&gt;
&lt;p&gt;There are a bunch more that you can download install, usually tools
written by computer professionals for other computer professionals. Many
of these command line programs were written primarily for Linux and
other Unix OSes, but also have Windows versions.&lt;/p&gt;
&lt;p&gt;We will go into specific examples of command line programs in a later
section, but the important thing to know is that a command line program
has access to all the same system libraries and capabilities that any
Windows (or Linux, or macOS) program can access. It can play audio,
connect to the Internet, and do pretty much anything &amp;ndash; anything except
draw a new window on the screen, not because it can&amp;rsquo;t, but because that
would make it not a command line program anymore.&lt;/p&gt;
&lt;p&gt;But I don&amp;rsquo;t want to go too over-the-top rebutting this first misconception,
because then I might lead you to believe the second misconception.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Misconception Two:&lt;/strong&gt; Not only can you do anything from the command
line that you can do from a graphical user interface, but the command
line is fundamentally closer to the operating system. When graphical
programs run, they are using the command line under the hood.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is not true.&lt;/p&gt;
&lt;p&gt;It should be obvious that there is at least one thing you can do
from a graphical user interface that you can&amp;rsquo;t do from the command
line, which is to display graphics. The command line is an interface
based fundamentally on displaying a grid of text. Thanks to &lt;a href=&#34;https://xkcd.com/1953/&#34;&gt;modern
Unicode&lt;/a&gt;, &amp;ldquo;text&amp;rdquo; now includes &amp;ldquo;emojis,&amp;rdquo; but it
does not include images or high-quality charts and graphs.&lt;/p&gt;
&lt;p&gt;But even with that overly-obvious caveat aside, yes, it is true that
anything a graphical program can do besides show graphics could be done
by a command line program as well. There are command line programs that
manipulate images, they just don&amp;rsquo;t show the images as they manipulate
them. There are command line programs that pretend to be web browsers
and scrape data off of the websites when they load. All the operating
system features and computer resources that graphical programs have at
their disposal, command line programs will generally have too, besides
(by definition) actually doing graphical displays and interactions.&lt;/p&gt;
&lt;p&gt;However &amp;ndash; and this is a big however &amp;ndash; just because a command line
program could exist to do everything a graphical program does,
doesn&amp;rsquo;t mean that you have that program installed on your system,
or that someone&amp;rsquo;s even ever written that program. The capabilities
of your computer depend on what software you have installed, and what
software you can install depends on what software people have written.
If someone creates a file format, but only writes a GUI program
to edit it, well, then, until someone reverse-engineers it, that file
format will only be editable via GUI. Similarly if they only create
command line tools &amp;ndash; that file format will then only be accessible
by command line.&lt;/p&gt;
&lt;p&gt;For example, someone with &lt;a href=&#34;https://imagemagick.org/index.php&#34;&gt;ImageMagick&lt;/a&gt;
installed on their computer but not Photoshop may only be able to do image
manipulation from the command line. Someone with Photoshop installed but
not ImageMagick may only be able to do image manipulation from the GUI.
There is nothing intrinsically more powerful about either interface.&lt;/p&gt;
&lt;p&gt;Specifically, GUI programs are decidedly not wrappers around command
line utilities. You could write a GUI program that way (and there
are a couple that are), but the vast majority do not in fact do this.
Just as command line programs have access to all the same computer resources
and operating system functionality that GUI programs do, it also works
the other way around. GUI programs and command line programs both are
written in programming languages that allow the program to invoke
operating system functionality through system libraries and system calls.
These calls are not at all the same as command line commands, and
the GUI doesn&amp;rsquo;t need to use the command line as an intermediate layer.&lt;/p&gt;
&lt;p&gt;If there is a GUI version and a command line version of the same
functionality, maybe this is implemented as the GUI version launching the
command line version under the hood &amp;ndash; that is certainly something GUI
programs &lt;em&gt;can&lt;/em&gt; do, and it might make sense if the command line version is
the interface most people use and that most maintainers are interested
in. But it is just as likely if not more likely to be implemented by
the GUI program and the command line both using the same common library.&lt;/p&gt;
&lt;p&gt;And certainly, GUI-only programs like web browsers, e-mail clients,
and office suites do not by any means implement their functionality by
wrapping command line programs. There is no command line version of
or interface to Photoshop, nor of Microsoft Word&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;And just like it&amp;rsquo;s possible to have an operating system with
a command line and no graphical user interface, it is possible
to have an operating system with a graphical user interface and no
command line, not even internal analogues of it.&lt;/p&gt;
&lt;h1 id=&#34;history-of-the-command-line&#34;&gt;History of the command line&lt;/h1&gt;
&lt;p&gt;As I said before, computers used to be frequently accessed
via dumb terminals. Before this, they were accessed by
&lt;a href=&#34;https://en.wikipedia.org/wiki/Teleprinter&#34;&gt;teletypewriters&lt;/a&gt;. This was
literally a typewriter, where the keys you entered went to the computer,
and the computers responses were typed on the paper.&lt;/p&gt;
&lt;p&gt;Modern command lines mostly follow that pattern &amp;ndash; new input goes in
at the bottom of the window, and the window scrolls like a piece of paper
receding from the typewriter. But on a modern command line, the program
can also take over the entire terminal emulator window, as long as what
it wants to draw can be expressed as text. They even support multiple
colors.&lt;/p&gt;
&lt;p&gt;Most command line systems used today, like most operating systems used
today, descend from the Unix tradition, written in 1970. The exception
is Windows &amp;ndash; even though the Windows command line is not DOS, it takes
many of its aesthetic principles from DOS, not only the famous prompt
&lt;code&gt;C:\&amp;gt;&lt;/code&gt;, but also its habit of taking options with &lt;code&gt;/&lt;/code&gt;, where Unix and
friends use &lt;code&gt;-&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;what-are-some-modern-command-line-programs&#34;&gt;What are some modern command line programs?&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://git-scm.com/&#34;&gt;&lt;code&gt;git&lt;/code&gt;&lt;/a&gt; keeps track of different versions of
a large folder (called a &lt;em&gt;repository&lt;/em&gt;) full of code or other forms of
(mostly) text, and allows changes to be merged and reconciled between
different authors. While there are GUI and web wrappers around it,
the flagship program is a command line utility.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.openssh.com/&#34;&gt;&lt;code&gt;ssh&lt;/code&gt;&lt;/a&gt; lets you log into a command line
interface of another computer, usually a server. This is often the only
way to log into and administrate the server, as Linux servers generally
don&amp;rsquo;t have any GUI capabilities or GUI programs installed.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://imagemagick.org/index.php&#34;&gt;ImageMagick&lt;/a&gt; lets you manipulate
images.&lt;/li&gt;
&lt;li&gt;Last but not least, there are many small programs that let you do
basic file management, searching, and editing. Two of my favorite
new ones are &lt;a href=&#34;https://github.com/BurntSushi/ripgrep&#34;&gt;RipGrep&lt;/a&gt;
by &lt;a href=&#34;https://blog.burntsushi.net/&#34;&gt;Andrew Gallant&lt;/a&gt; (which lets you
search for strings or patterns in text files)
and &lt;a href=&#34;https://github.com/sharkdp/fd&#34;&gt;fd&lt;/a&gt; by &lt;a href=&#34;https://david-peter.de/&#34;&gt;David
Peter&lt;/a&gt; (which let you search for files by
name or other properties).&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;why-use-the-command-line&#34;&gt;Why use the command line?&lt;/h1&gt;
&lt;p&gt;If you are new to a tool, discoverability is an important
feature. If you are experienced with a tool, all the hints of
where to find things are more distractions than they are useful.&lt;/p&gt;
&lt;p&gt;As someone who needs all the focus that I can get&lt;sup id=&#34;fnref:5&#34;&gt;&lt;a href=&#34;#fn:5&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;5&lt;/a&gt;&lt;/sup&gt;, distractions
are bad. And so are extra steps: Why spend the time moving the mouse
around to access one menu, then another, when on the command line,
I can just type the command I already know for what I need to do.&lt;/p&gt;
&lt;p&gt;Additionally, the command line is designed to save on extra typing.
Generally, most modern command lines support &amp;ldquo;tab completion,&amp;rdquo; where you
can type the beginning of the command, or a file that it&amp;rsquo;s operating on,
and press the &lt;strong&gt;[TAB]&lt;/strong&gt; key, the command line interpreter will complete
the word for you &amp;ndash; or list the possibilities if there are multiple.&lt;/p&gt;
&lt;p&gt;For a newbie, it might be an intimidating, but for someone who&amp;rsquo;s used to
it, it stays out of your way and lets you get stuff done &amp;ndash; while showing
you a detailed transcript of what you&amp;rsquo;ve been doing, in case you forget
what exactly it was you were trying to do.&lt;/p&gt;
&lt;p&gt;Command lines are even more important on the server. While Windows servers
come with a graphical user interface you can remote login into, Unix&lt;sup id=&#34;fnref:6&#34;&gt;&lt;a href=&#34;#fn:6&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;6&lt;/a&gt;&lt;/sup&gt;
servers generally don&amp;rsquo;t. It&amp;rsquo;s more efficient to just allow administrators
a command line interface &amp;ndash; and for most server administrators, it&amp;rsquo;s
quite enough.&lt;/p&gt;
&lt;p&gt;And while command lines are not closer to the operating system in a
deep technological sense, they are closer to the operating system
by convention. They tend to have all the options that a power user
would want &amp;ndash; and easy ways to specify them, rather than hiding them
behind multiple warning signs and buttons labelled &amp;ldquo;Advanced&amp;hellip;.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Last but not least, if you have a series of GUI actions that you often
do, you usually have to just keep doing them, even if it&amp;rsquo;s very tedious.
Precious few programs let you do something like write a shortcut key
for five menu commands. On the command line, however, you can use
aliases or scripts, where a short command stands for a long command,
or a single command stands for a whole sequence of commands. You just
put into a file the same text you would type at the prompt.&lt;/p&gt;
&lt;h1 id=&#34;how-does-the-command-line-actually-work&#34;&gt;How does the command line actually work?&lt;/h1&gt;
&lt;p&gt;Generally, a terminal emulator or command line window has a process
running in it that presents the prompt (&lt;code&gt;C:\&amp;gt;&lt;/code&gt; or similar on Windows,
normally something ending with &lt;code&gt;$&lt;/code&gt; on Unix). It then takes in the
command, takes the first word, and runs that as a program.
This program is launched as a separate process, just like clicking
on a program icon launches a separate process in a graphical user
interface. The shell waits in the background for the process to finish,
and then presents a new prompt. On a modern multitasking operating
system, the shell generally also allows you to run commands in the
background, and use key combinations (Ctrl-Z on Unix) to put a process
in the background, and commands like &lt;code&gt;fg&lt;/code&gt; to bring processes back
to the foreground. This allows you to run multiple programs at once
within the terminal.&lt;/p&gt;
&lt;p&gt;On Linux, when a program starts, it conventionally has three
open files, 0, 1, and 2, for input, output, and error, respectively.
On the command line, by default (for it is configurable), these
all correspond to the terminal: input is read in from the keyboard
on the terminal (by default line by line), and output and errors
are outputted to the terminal. GUI programs will have these three
files open when they start too, but unless they&amp;rsquo;re started from the
terminal, the output will normally just silently be ignored.&lt;/p&gt;
&lt;p&gt;The program can also draw a window, if a graphical environment is
available. On Linux, it is easy for the same program to have a command
line interface, and a graphical interface &amp;ndash; sometimes at the same time.
This is useful if it&amp;rsquo;s mostly used from the command line, but sometimes
also wants to do things like show a chart or graph that can be generated.&lt;/p&gt;
&lt;p&gt;macOS and Windows have more complicated GUI frameworks that make a GUI
application more different in structure from a command line operation,
but you can still launch GUI applications from the command line.&lt;/p&gt;
&lt;h1 id=&#34;footnotes&#34;&gt;Footnotes&lt;/h1&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;An
&lt;a href=&#34;https://en.wikipedia.org/wiki/Application_software&#34;&gt;&lt;em&gt;application&lt;/em&gt;&lt;/a&gt;
is just a computer program that does a task besides making the computer
system work as a whole, a task interesting to the user. Examples include
word processors, spreadsheets, chat apps, and video games. It&amp;rsquo;s not
so much a rigorous technical term as an amorphous category of software.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;A desktop environment, also known as a graphical shell, is
a graphical user interface for managing the windows you have open,
and providing computer-wide menus for launching applications. It also
controls the root window, which is what you see when you have no windows
open, normally used for shortcuts and files you&amp;rsquo;re currently working
on. Windows and macOS both provide their own desktop environments,
which generally aren&amp;rsquo;t mentioned by name &amp;ndash; they are just part of
the operating system. Linux and most other Unixes, when they have
graphical interfaces at all, can be used with a variety of different
desktop environments.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;This image is taken from &lt;a href=&#34;https://commons.wikimedia.org/wiki/File:DEC_VT100_terminal_transparent.png&#34;&gt;Wikimedia
Commons&lt;/a&gt;.
It is by Jason Scott, and available under &lt;a href=&#34;https://creativecommons.org/licenses/by-sa/4.0/&#34;&gt;CC BY-SA
4.0&lt;/a&gt;. It was modified
by the Wikimedia poster by removing the background.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;Oddly enough, most web browsers support running without the browser
window actually being displayed, in a headless mode. This is generally not
usable purely from the command line, but in the context of being wrapped
in a larger program (which might be a command line program). Additionally,
Microsoft Word and Photoshop can be programmatically controlled &amp;ndash; they
are both &lt;em&gt;scriptable&lt;/em&gt; &amp;ndash; but as far as I know neither Microsoft nor Adobe
have chosen to provide a command line interface to this functionality,
even though they could. Again, it&amp;rsquo;s about what&amp;rsquo;s actually available on
your computer.&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:5&#34;&gt;
&lt;p&gt;It has been said that I have a &lt;a href=&#34;https://www.thecodedmessage.com/tags/adhd/&#34;&gt;deficit of attention&lt;/a&gt;.&amp;#160;&lt;a href=&#34;#fnref:5&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:6&#34;&gt;
&lt;p&gt;I use Unix in a broad sense to include Unix-like operating
systems like Linux and the BSDs, even if they aren&amp;rsquo;t Unix in a
trademark sense.&amp;#160;&lt;a href=&#34;#fnref:6&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
      <title>Can computers think things?</title>
      <link href="https://www.thecodedmessage.com/posts/can-computers-think-things/" />
      <id>https://www.thecodedmessage.com/posts/can-computers-think-things/</id>
      <updated>2023-09-30T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;This blog post isn&amp;rsquo;t about ChatGPT. It
isn&amp;rsquo;t about machine learning, neural nets, or any
&lt;a href=&#34;https://www.smbc-comics.com/comic/conscious-6&#34;&gt;mysterious&lt;/a&gt; or border-line
&lt;a href=&#34;https://www.smbc-comics.com/comic/2009-10-08&#34;&gt;spiritual&lt;/a&gt; form of
computing. That&amp;rsquo;s a whole &amp;rsquo;nother set of philosophical and metaphysical
conundrums (&lt;a href=&#34;https://en.wiktionary.org/wiki/conundra&#34;&gt;conundra&lt;/a&gt;?).&lt;/p&gt;
&lt;p&gt;This is about a way people sometimes speak, informally, about bog-standard
boring non-AI computers and computer programs. You&amp;rsquo;ve probably
heard people speak this way. You&amp;rsquo;ve probably spoken this way sometimes
yourself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;The server thinks your password is wrong.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;The computer thinks you&amp;rsquo;ve lost the connection.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;The phone thinks you want to use your headphones. It&amp;rsquo;s wrong though.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We normally interpret this as a metaphor, but I&amp;rsquo;m not sure it is.
Is the phone &amp;ldquo;thinking&amp;rdquo; you want to use your headphones rather than
your car speaker substantially different from us &amp;ldquo;thinking&amp;rdquo;
our friend would rather get a phone call than a text message?&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;This blog post isn&amp;rsquo;t about ChatGPT. It
isn&amp;rsquo;t about machine learning, neural nets, or any
&lt;a href=&#34;https://www.smbc-comics.com/comic/conscious-6&#34;&gt;mysterious&lt;/a&gt; or border-line
&lt;a href=&#34;https://www.smbc-comics.com/comic/2009-10-08&#34;&gt;spiritual&lt;/a&gt; form of
computing. That&amp;rsquo;s a whole &amp;rsquo;nother set of philosophical and metaphysical
conundrums (&lt;a href=&#34;https://en.wiktionary.org/wiki/conundra&#34;&gt;conundra&lt;/a&gt;?).&lt;/p&gt;
&lt;p&gt;This is about a way people sometimes speak, informally, about bog-standard
boring non-AI computers and computer programs. You&amp;rsquo;ve probably
heard people speak this way. You&amp;rsquo;ve probably spoken this way sometimes
yourself:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;The server thinks your password is wrong.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;The computer thinks you&amp;rsquo;ve lost the connection.&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;The phone thinks you want to use your headphones. It&amp;rsquo;s wrong though.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We normally interpret this as a metaphor, but I&amp;rsquo;m not sure it is.
Is the phone &amp;ldquo;thinking&amp;rdquo; you want to use your headphones rather than
your car speaker substantially different from us &amp;ldquo;thinking&amp;rdquo;
our friend would rather get a phone call than a text message?&lt;/p&gt;
&lt;p&gt;Part of the problem here is that the word &amp;ldquo;think&amp;rdquo; in English can
mean different things.&lt;/p&gt;
&lt;p&gt;It can mean to cognate, to go through a rational series of propositions
in our brains, expressed as internalized speech in our mind&amp;rsquo;s ear or
diagrams in our mind&amp;rsquo;s eye or pure abstractions. &amp;ldquo;I am thinking about
how to approach this physics problem.&amp;rdquo; Computers probably cannot do this,
and certainly are nowhere as good at it as humans are, not even with
this fancy new AI software everyone&amp;rsquo;s playing with.&lt;/p&gt;
&lt;p&gt;But it can also mean to have a belief, a mental model about reality.
&amp;ldquo;I think Joe doesn&amp;rsquo;t like me very much.&amp;rdquo; Or, &amp;ldquo;I think the reason
the car won&amp;rsquo;t start is because the battery is dead.&amp;rdquo; Computers,
I will argue, can do something remarkably similar to humans in this
category.&lt;/p&gt;
&lt;p&gt;Some languages distinguish these two meanings of &amp;ldquo;think.&amp;rdquo; English learners
of German often say &lt;em&gt;denken&lt;/em&gt; (to cognate), when they mean &lt;em&gt;glauben&lt;/em&gt;
(to believe), in contexts where both would translate as &amp;ldquo;to think.&amp;rdquo; And
then, in case that was too simple, there&amp;rsquo;s also &lt;em&gt;meinen&lt;/em&gt;, which means
&amp;ldquo;to suppose&amp;rdquo; or &amp;ldquo;to opine,&amp;rdquo; also used when English speakers might say
&amp;ldquo;to think.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s my thought on this, or rather, my opinion (&lt;em&gt;meine Meinung&lt;/em&gt;):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Computers cannot yet &lt;em&gt;denken&lt;/em&gt;, or cognate, like humans. But computers
can definitely &lt;em&gt;glauben&lt;/em&gt;, or internally believe, specific facts, and
they&amp;rsquo;ve been able to do that since the day they were invented.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In order to figure out whether this is true, we first need to establish
what it means to believe something, and then see if computers can do it.
What does it mean for humans to think something, to believe something
about the world? Can we extract a definition that can then be applied
to computers, to see whether computers are capable of the same thing?&lt;/p&gt;
&lt;p&gt;So, what does it mean for us to think something is true? Well, it means
that we have some internal state, some internal information stored in
the physical arrangement of our brains, that corresponds to that thought
or belief. We then use that internal state to inform our behavior. If we
think our friend would rather get a phone call than a text message, then
we might choose to accomodate that and call them instead of texting them.&lt;/p&gt;
&lt;p&gt;This internal state, when all is going well, corresponds to a specific
external reality. The goal is for the internal state to match the
external reality. Sometimes this goal is not met &amp;ndash; sometimes we
misapprehend the situation, our belief is wrong, or what we think is true
is not true. But if we are wrong, we have the same internal state as
we would have if we were right, and things were working.&lt;/p&gt;
&lt;p&gt;We can therefore define believing or thinking that a proposition X is true
thus:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A being believes X is true if they have an internal state that,
when the being is functioning correctly, corresponds to X being true,
that then informs their behavior such that it is the behavior that
makes sense if X is true, rather than the behavior that makes sense
if X is not true.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Applied to phone example, we have some internal state in our brain that
indicates that &amp;ldquo;Jill would rather get a call than a text.&amp;rdquo; How do we
know that the state indicates that proposition? Well, we know that when
our brains are functioning correctly (a hard thing to define, but also
a concept everyone uses all the time), we only have that internal state
when the proposition is true. And, we also know that this internal state
drives behavior consistent with that proposition being true. Assuming we
want to accommodate Jill&amp;rsquo;s preference, we will call her instead of texting
her, an adaptive decision if the belief is true, and a non-adaptive one
if the belief is false.&lt;/p&gt;
&lt;p&gt;With this framework, it seems almost easier to establish that computers
can think something is true than that humans can do this.  Humans often
have complicated, ambivalent beliefs and thoughts.  Humans will often
believe something for reasons other than an efficient assessment of its
truth value, and act contrary to their own earnestly held beliefs. I think
this definition still works for humans, if you take all the confounding
factors into consideration, but it&amp;rsquo;s hard: We get into things like
&amp;ldquo;conscious&amp;rdquo; or &amp;ldquo;subconscious&amp;rdquo; beliefs, or &amp;ldquo;he says he thinks X, but
his actions show he really thinks Y.&amp;rdquo; And, of course, it&amp;rsquo;s extremely
difficult to define whether a human is &amp;ldquo;functioning correctly.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;With computers, however, they think all sorts of things.
For example, let&amp;rsquo;s talk about whether a computer thinks a
user has administrator privileges. You might see code like
this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; has_admin_privileges: &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; is_admin(conn.get_current_user());
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we have an internal state in the computer, a boolean (i.e. true
or false) variable that is intended to correspond to whether the user
has administrator privileges. If the code is functioning correctly,
this variable will take on the value &lt;code&gt;true&lt;/code&gt;. We know this, because
the definition of &amp;ldquo;functioning correctly&amp;rdquo; is implicit in the way the
programmer wrote the code, and how they named the variable.&lt;/p&gt;
&lt;p&gt;Furthermore, the following lines of code are almost certainly
behaviors in line with that interpretation of the internal state.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; has_admin_privileges {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Do the thing
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    requested_task.perform()&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Signal success
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ok(())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Signal an error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Err(Error::AccessDenied)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, when people say things like &amp;ldquo;my phone thinks I want to use
my Bluetooth headphones,&amp;rdquo; it means that there is information encoded
in the silicon of the phone, possibly in an explicitly-named
variable, that corresponds to that belief.&lt;/p&gt;
&lt;p&gt;So now that I&amp;rsquo;ve thought this through properly, I don&amp;rsquo;t even think
statements like this are metaphorical. I think they are literally true,
and completely appropriate.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>My Dream C&#43;&#43; Additions</title>
      <link href="https://www.thecodedmessage.com/posts/c&#43;&#43;-additions/" />
      <id>https://www.thecodedmessage.com/posts/c&#43;&#43;-additions/</id>
      <updated>2023-08-30T00:00:00+00:00</updated>
      
      <summary type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: I have updated this post to address C++ features that
address these issues or have been purported to.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have long day-dreamed about useful improvements to C++. Some of these
are inspired by Rust, but some of these are ideas I already had before
I learned Rust. Each of these would make programming C++ a better experience,
usually in a minor way.&lt;/p&gt;
&lt;h1 id=&#34;explicit-self-reference-instead-of-implicit-this-pointer&#34;&gt;Explicit &lt;code&gt;self&lt;/code&gt; reference instead of implicit &lt;code&gt;this&lt;/code&gt; pointer&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; This is coming out in C++23, and they did it right!
I&amp;rsquo;m excited! Good job C++!&lt;/p&gt;</summary>
      <content type="html">&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: I have updated this post to address C++ features that
address these issues or have been purported to.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have long day-dreamed about useful improvements to C++. Some of these
are inspired by Rust, but some of these are ideas I already had before
I learned Rust. Each of these would make programming C++ a better experience,
usually in a minor way.&lt;/p&gt;
&lt;h1 id=&#34;explicit-self-reference-instead-of-implicit-this-pointer&#34;&gt;Explicit &lt;code&gt;self&lt;/code&gt; reference instead of implicit &lt;code&gt;this&lt;/code&gt; pointer&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; This is coming out in C++23, and they did it right!
I&amp;rsquo;m excited! Good job C++!&lt;/p&gt;
&lt;p&gt;I admit I haven&amp;rsquo;t been paying close attention to C++ post C++14.
C++17 was up-and-coming and I hadn&amp;rsquo;t finished learning everything
I wanted to about it when I left C++ programming.
And I refuse to be embarrassed for not knowing about a feature in
a programming language that is not my favorite before any compiler
even supports it.&lt;/p&gt;
&lt;p&gt;But I am indeed excited for them! This is a substantial improvement
I have wanted since well before C++11 came out. They&amp;rsquo;ve done it
pretty close to how I wished for it here, and they have good
reasons for how they made it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There are a few weird parts of &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For one, it is a pointer, but it is never allowed to be null, and it
cannot be modified to point to a different object. In both of these
ways, it behaves more like a reference than a pointer.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; bar() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Foo{}; &lt;span style=&#34;color:#75715e&#34;&gt;// Error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Foo &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nullptr&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    foo&lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt;bar(); &lt;span style=&#34;color:#75715e&#34;&gt;// Undefined behavior
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For another, when we want to put a modifier on &lt;code&gt;this&lt;/code&gt;, like &lt;code&gt;const&lt;/code&gt;
or &lt;code&gt;volatile&lt;/code&gt;, there is nowhere obvious in the function signature to
put it. We have to put it awkwardly after the parameters, before the
&lt;code&gt;;&lt;/code&gt; or &lt;code&gt;{&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; bar() &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;volatile&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// Do stuff
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Oddly enough, whether the parameter is taken by lvalue or rvalue can also be
specified, which would make way more sense for a reference parameter
instead of a pointer.&lt;/p&gt;
&lt;p&gt;The modifiers have to go in this odd location because &lt;code&gt;this&lt;/code&gt; is
implicit. This is in line with OOP ideology and theory, but in my mind,
it&amp;rsquo;s just a negative. If you have to think about whether it&amp;rsquo;s &lt;code&gt;const&lt;/code&gt;
or taken by &lt;code&gt;rvalue&lt;/code&gt; anyway when writing the signature, why put those
modifiers somewhere you might forget about, instead of right with
the declaration of the parameter.&lt;/p&gt;
&lt;p&gt;I would change the syntax to fix both of these issues with one fell swoop:
allow an explicit &lt;code&gt;self&lt;/code&gt; as an alternative to implicit &lt;code&gt;this&lt;/code&gt;, and
make it a reference:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; bar(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.baz();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;baz&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;volatile&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// Do stuff
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The type would still be implicit, but modifiers can be specified where
the type would be. You would also only be able to take by reference or
rvalue reference, and never by value, because implicit copy on method
call would be a new feature of questionable value. It would not conflict
with existing code, as a parameter named &lt;code&gt;self&lt;/code&gt; without an explicit type
would be illegal under the current syntax.&lt;/p&gt;
&lt;p&gt;Of course, this looks rather similar to Rust&amp;rsquo;s syntax, but believe it or
not, I had this idea long before I learned that Rust does &lt;code&gt;self&lt;/code&gt; in this
way.&lt;/p&gt;
&lt;h1 id=&#34;a-new-byte-type-for-uint8_t-and-int8_t&#34;&gt;A new &lt;code&gt;byte&lt;/code&gt; type for &lt;code&gt;uint8_t&lt;/code&gt; and &lt;code&gt;int8_t&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;In C++, the type we use for an individual byte of data, by definition,
is &lt;code&gt;char&lt;/code&gt;. This is the definition of &lt;code&gt;char&lt;/code&gt; in the standard, and while
the byte length (&lt;code&gt;CHAR_BIT&lt;/code&gt;) doesn&amp;rsquo;t have to be 8 bits, other standard
provisions and practical considerations mean that on a modern platform,
it always is.&lt;/p&gt;
&lt;p&gt;We might use &lt;code&gt;uint8_t&lt;/code&gt; or &lt;code&gt;int8_t&lt;/code&gt; for bytes in practical code, but
these are defined as &lt;code&gt;typedef&lt;/code&gt;s to &lt;code&gt;unsigned char&lt;/code&gt; and &lt;code&gt;signed char&lt;/code&gt; &amp;ndash;
I don&amp;rsquo;t know whether this is required by the standard but it is always
done in practice.&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;char&lt;/code&gt; is also the type we use for text data, so it is a type
with two different contrasting (perhaps even contradictory) sets of
semantics.&lt;/p&gt;
&lt;p&gt;That leads to many odd results, including the fact that &lt;code&gt;char&lt;/code&gt;
cannot represent all Unicode characters because it has to be 1 byte
long. But the one I want to focus on today is a bit weirder.
What does this code print?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;cstdint&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;message_data&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; message_type;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; message_length;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; data[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;print_message_hdr&lt;/span&gt;(message_data &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;mesg) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Type: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; mesg.message_type &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Length: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; mesg.message_length &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    message_data data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data.message_type &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data.message_length &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print_message_hdr(data);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, if you thought the numbers &lt;code&gt;100&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt; would show up on the
output, you&amp;rsquo;d be wrong. &lt;code&gt;std::cout&lt;/code&gt;&amp;rsquo;s &lt;code&gt;operator&amp;lt;&amp;lt;&lt;/code&gt;&amp;rsquo;s &lt;code&gt;char&lt;/code&gt; overloads
are triggered, and so these fields, clearly meant as integers,
are printed as text:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[jim&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;palatinate:&lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;]&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt; c&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;c&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;11&lt;/span&gt; test.cpp
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[jim&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;palatinate:&lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;]&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt; .&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;a.out
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Type: d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Length:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[jim&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;@&lt;/span&gt;palatinate:&lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;]&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;$&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In order to get the integer print-outs we want, we have to override
this strange default behavior, perhaps by casting the values to
&lt;code&gt;uint16_t&lt;/code&gt; before printing them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;print_message_hdr&lt;/span&gt;(message_data &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;mesg) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Type: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt;(mesg.message_type) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Length: &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;uint16_t&lt;/span&gt;(mesg.message_length) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This results in a better output:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~]$ c++ -std=c++11 test.cpp
[jim@palatinate:~]$ ./a.out
Type: 100
Length: 0
[jim@palatinate:~]$
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So, how do we make this a little more ergonomic? We introduce a &lt;code&gt;byte&lt;/code&gt;
type, that is similar to &lt;code&gt;char&lt;/code&gt;, but overloads differently. Like any
other integer type, it defaults to &lt;code&gt;signed&lt;/code&gt;, and then we add overloads
to &lt;code&gt;operator&amp;lt;&amp;lt;&lt;/code&gt; and others to treat it like an integer, not like a
character. Switching between &lt;code&gt;byte&lt;/code&gt; and &lt;code&gt;char&lt;/code&gt; would be an implicit
cast, but for overloading purposes, they would be different types.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;uint8_t&lt;/code&gt; and &lt;code&gt;int8_t&lt;/code&gt; could then be defined in terms of &lt;code&gt;byte&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I do not know what backwards-compatibility implications it has, but
I do think the decision to make &lt;code&gt;char&lt;/code&gt; mean byte as its primary
meaning instead of &amp;ldquo;character&amp;rdquo; was a particularly poor one, and anything
we can do to migrate away from it would be good.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Someone drew my attention to &lt;code&gt;std::byte&lt;/code&gt;. This one I was aware of,
but had not thought about here as I didn&amp;rsquo;t think it really solves the problem.
As it is, it is not an arithmetic type, and therefore cannot be used as
the underlying type of &lt;code&gt;uint8_t&lt;/code&gt;, leaving the confusing behavior in place.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;real-if-else-expression-syntax&#34;&gt;Real if-else Expression Syntax&lt;/h1&gt;
&lt;p&gt;Oftentimes, in C++, I find myself writing code like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int32_t&lt;/span&gt; error_code;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (setting &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; Setting&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;Socket) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error_code &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; initialize_socket();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#75715e&#34;&gt;// setting == Setting::Pipe
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error_code &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; initialize_pipe();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (error_code &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This &lt;code&gt;error_code&lt;/code&gt; variable is just one example. I often want to
have a variable get different values depending on which side of the
&lt;code&gt;if&lt;/code&gt;-&lt;code&gt;else&lt;/code&gt; statement it&amp;rsquo;s on, without having to declare the variable
without an initializer right ahead of it, and write two assignment
statements. Basically, I want &lt;code&gt;if&lt;/code&gt;-&lt;code&gt;else&lt;/code&gt; to be an expression.&lt;/p&gt;
&lt;p&gt;Now, of course, C++ already has the ternary operator: &lt;code&gt;?:&lt;/code&gt;. But it&amp;rsquo;s so
ugly and unreadable that no one uses it, for good reason. It&amp;rsquo;s hard
to remember what the precedence is, meaning if we want to be rigorous
and friendly to our readers we need to bracket with &lt;code&gt;(&lt;/code&gt; and &lt;code&gt;)&lt;/code&gt; even if
strictly unnecessary, and the result looks like garbage and is hard
to format in a way that&amp;rsquo;s remotely readable:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int32_t&lt;/span&gt; error_code &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (setting &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; Setting&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;Socket
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt; initialize_socket()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; initialize_pipe()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What do I want instead? I want &lt;code&gt;if&lt;/code&gt;-&lt;code&gt;else&lt;/code&gt; to have this role, to
be an expression, where it evaluates to the value of the end of
each block (with no semicolon, to make clear that it&amp;rsquo;s an expression
not a full statement):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int32_t&lt;/span&gt; error_code &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (setting &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; Setting&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;Socket) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    initialize_socket()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    initialize_pipe()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is way better than &lt;code&gt;?:&lt;/code&gt;. The blocks can be multiple statements
long if necessary. You can add &lt;code&gt;if&lt;/code&gt;-&lt;code&gt;else if&lt;/code&gt;-&lt;code&gt;else&lt;/code&gt; chaining. And,
most importantly, it can be formatted like any other &lt;code&gt;if&lt;/code&gt;-&lt;code&gt;else&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Someone drew my attention to a lambda-invocation pattern that is,
in my mind, equally ugly to &lt;code&gt;?:&lt;/code&gt;, and also leaves you without the ability
to return from the enclosing function within the block.  This strikes me
as extremely hackish and not really an improvement, but I suppose that&amp;rsquo;s
where C++ is going. I am at a loss for why they didn&amp;rsquo;t just implement
GCC&amp;rsquo;s expression blocks, followed by &lt;code&gt;if&lt;/code&gt; as expression. It&amp;rsquo;s clearly
much better in my mind.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve seen the technique from time to time but I guess I figured it
was too hackish to mention. I didn&amp;rsquo;t realize it was getting officially
recommended in C++ Core Guidelines. I feel like when they were recommending
it, they should&amp;rsquo;ve simultaneously been trying to get more usable and obvious
features included in the programming language itself. Maybe they are,
and if so I wish them luck in that! Maybe C++30 will be a safe and usable
programming language, equivalent to Rust now.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;variable-shadowing&#34;&gt;Variable Shadowing&lt;/h1&gt;
&lt;p&gt;On a related note, I want to have multiple variables with the same name
shadow, rather than resulting in an error message. I want the new variable
with the same name to simply hide the old variable, rather than giving me
a &amp;ldquo;conflicting declaration&amp;rdquo; error (or similar).&lt;/p&gt;
&lt;p&gt;Why? Well, a lot of production code involves taking the same conceptual
thing, and migrating it through many types. Without shadowing, we have
to use awkward Hungarian notation.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;handle_data&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data_v, size_t size) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data_ch &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)data_v;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; data{data_ch, data_ch &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; size};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Actually do something with `data`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The new way would look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;handle_data&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data, size_t size) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; data{data, data &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; size};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This also cuts down on how many variables are in scope at once.&lt;/p&gt;
&lt;p&gt;This bugs people who are new to Rust sometimes, but it&amp;rsquo;s fairly easy
to learn, and C++ has asked people to learn much, much harder things.
Once learned, it is really useful, as the alternative is to use
Hungarian notation or equivalents. It also helps you use the right
value, as you won&amp;rsquo;t accidentally go back and use an old one, as it&amp;rsquo;s
shadowed.&lt;/p&gt;
&lt;h1 id=&#34;first-class-support-for-sum-types&#34;&gt;First-Class Support for Sum Types&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;std::variant&lt;/code&gt; is awful. I know, because few people except die-hards
use it, and people use the Rust equivalent, &lt;code&gt;enum&lt;/code&gt;s, all the time. The
weirdest thing about &lt;code&gt;std::variant&lt;/code&gt; is that it supposes that all
of the variants hold exactly one value, and one variant per type
is sufficient. In reality, multiple variants might hold values of
the same type, and many variants don&amp;rsquo;t need a value &amp;ndash; both of which
are possible but clumsy to express using &lt;code&gt;std::variant&lt;/code&gt;&amp;rsquo;s semantics.&lt;/p&gt;
&lt;p&gt;But C++11 already introduced &lt;code&gt;enum class&lt;/code&gt; for more powerful &lt;code&gt;enum&lt;/code&gt;s! Let&amp;rsquo;s
go all the way and add Rust-style values associated with it, for a
compiler-implemented tagged union. The implementation of &lt;code&gt;std::option&lt;/code&gt;&amp;rsquo;s
fields would be so much simpler.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;template &amp;lt;typename T&amp;gt;
enum class option {
    None,
    Some {
        T value;
    },

    // OK, define some methods
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This interacts with object lifetimes and constructors in a complicated
way, but if there were interest, I know it could be figured out.
If you don&amp;rsquo;t think this feature is necessary, I suspect you&amp;rsquo;ve spent
too long programming without it. Once you get used to this, it&amp;rsquo;s really
hard to go without.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I am not going to do anything to try to make these things happen.
I&amp;rsquo;m sure I&amp;rsquo;m not the most popular in the C++ community after my
long write-ups of how Rust is so much better, and it&amp;rsquo;s not where
my primary interests lie anymore. But, if someone were to make these
features happen, it would make my life much easier, when for good reasons,
projects I&amp;rsquo;m working on require me to code in C++.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>In Defense of &#39;C/C&#43;&#43;&#39;</title>
      <link href="https://www.thecodedmessage.com/posts/c-c&#43;&#43;/" />
      <id>https://www.thecodedmessage.com/posts/c-c&#43;&#43;/</id>
      <updated>2023-08-28T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;One of the minor points I discussed in my
&lt;a href=&#34;https://www.thecodedmessage.com/posts/stroustrup-response/&#34;&gt;response&lt;/a&gt; to Dr. Bjarne Stroustrup&amp;rsquo;s &lt;a href=&#34;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2739r0.pdf&#34;&gt;memory safety
comments&lt;/a&gt;
was the controversial, apparently deeply upsetting term C/C++. It is
controversial and interesting enough that I decided to say a little more
about it here.&lt;/p&gt;
&lt;p&gt;A little background: Many people, especially outside the C and C++
communities (which, to be clear, don&amp;rsquo;t always like each other that
much) use the term C/C++ to talk about the two programming languages
together, as an informal short-hand for &amp;ldquo;C and C++&amp;rdquo; or &amp;ldquo;C or C++.&amp;rdquo;
Within the &lt;del&gt;C/C++&lt;/del&gt; C and C++ communities, it is widely hated.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;One of the minor points I discussed in my
&lt;a href=&#34;https://www.thecodedmessage.com/posts/stroustrup-response/&#34;&gt;response&lt;/a&gt; to Dr. Bjarne Stroustrup&amp;rsquo;s &lt;a href=&#34;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2739r0.pdf&#34;&gt;memory safety
comments&lt;/a&gt;
was the controversial, apparently deeply upsetting term C/C++. It is
controversial and interesting enough that I decided to say a little more
about it here.&lt;/p&gt;
&lt;p&gt;A little background: Many people, especially outside the C and C++
communities (which, to be clear, don&amp;rsquo;t always like each other that
much) use the term C/C++ to talk about the two programming languages
together, as an informal short-hand for &amp;ldquo;C and C++&amp;rdquo; or &amp;ldquo;C or C++.&amp;rdquo;
Within the &lt;del&gt;C/C++&lt;/del&gt; C and C++ communities, it is widely hated.&lt;/p&gt;
&lt;p&gt;And now for me to say the thing guaranteed to anger the most possible
people: I see both sides of this debate.&lt;/p&gt;
&lt;p&gt;On the one hand, the term &amp;ldquo;C/C++&amp;rdquo; is especially jarring because C and C++
fans regularly engage in actual controversy (famously including Linus
Torvalds, of the C-based Linux kernel, &lt;a href=&#34;http://harmful.cat-v.org/software/c++/linus&#34;&gt;insulting
C++ and its programmers&lt;/a&gt;). It
is frustrating to be a C++ programmer, to have strong opinions on what
it means to be a C++ programmer, to think that C programmers are making
a misguided decision, that using C over C++ is technologically backwards
and regressive, and hear people cavalierly implying that the programming
languages are the same. And likewise, of course, for the C programmer
who feels similarly about C++.&lt;/p&gt;
&lt;p&gt;And continuously, both C and C++ programmers are exposed regularly to
people who mix up the programming languages when it is harmful. They see
bosses and hiring managers who expect you to transition back and forth
between them without any friction, and to enjoy them equally. They see
resources that promise to teach you &amp;ldquo;C/C++ skills,&amp;rdquo; and know that they
won&amp;rsquo;t teach how to use either the way that that language&amp;rsquo;s particular
community actually prefers. They see people using &amp;ldquo;C/C++&amp;rdquo; all the time
to talk about the languages in a way that only would make sense if they
were much more similar than they, in fact, are &amp;ndash; or at the very least,
than a die-hard partisan of C or C++ would think they are.&lt;/p&gt;
&lt;p&gt;And I do think this is understandable.  After all, people don&amp;rsquo;t tend to
lump together other languages like this. Java and C# are probably equally
related (if not more related), and no one writes that they&amp;rsquo;re hiring a
&amp;ldquo;Java/C# programmer.&amp;rdquo; Why should C and C++ get treated this way?&lt;/p&gt;
&lt;p&gt;But, on the other hand, C and C++ are actually extremely closely related
programming languages. I was writing something recently comparing
Rust features to C and C++ features, specifically Rust &lt;code&gt;enum&lt;/code&gt;s to the
tagged union idiom which is used in &amp;hellip; C and C++, in very similar ways.
I know all the reasons why as a C programmer and as a C++ programmer,
I&amp;rsquo;m not supposed to write C/C++, and still, I was tired of writing
&amp;ldquo;C and C++&amp;rdquo; over and over again to describe this particular thing that
those languages have in common.&lt;/p&gt;
&lt;p&gt;It turns out the real problem isn&amp;rsquo;t the act of writing &amp;ldquo;C/C++&amp;rdquo; &amp;ndash; it
turns out that just banning a problematic word doesn&amp;rsquo;t fix the real
problem here at all &amp;ndash; if it has ever fixed any problems.
Some people do need to be told that C and C++ programming are different
programming languages, different communities and different skillsets, even
though they are still related skillsets and related programming languages.
But some people who don&amp;rsquo;t need to be told that still find themselves
needing a shorthand sometimes, and don&amp;rsquo;t feel the cultural need to
be over-accommodating in avoiding it.&lt;/p&gt;
&lt;p&gt;Because when two things are similar &amp;ndash; and stop me if this is confusing! &amp;ndash;
there&amp;rsquo;s some ways in which they&amp;rsquo;re the same, and some ways in which
they&amp;rsquo;re different. Sometimes, it makes sense to lump them together, and
sometimes, it doesn&amp;rsquo;t. But yelling that people shouldn&amp;rsquo;t write &amp;ldquo;C/C++&amp;rdquo;
won&amp;rsquo;t magically help anyone understand this &amp;ndash; especially since those
people are almost certainly not listening, and you&amp;rsquo;re preaching to
the choir.&lt;/p&gt;
&lt;p&gt;In the case of Dr. Stroustrup, he was using the &amp;ldquo;faux pas&amp;rdquo; of the
NSA using &amp;ldquo;C/C++&amp;rdquo; to avoid having to actually address what they said
and defend C++. He brought this up in his criticism of the &lt;a href=&#34;https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF&#34;&gt;NSA white
paper&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As is far too common, it lumps C and C++ into the single category C/C++,
ignoring 30+ years of progress.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I said, among other things, that Dr. Stroustrup was being unnecessarily
exclusionary based on buzz-words:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;He&amp;rsquo;s reading too much into the orthography and the NSA&amp;rsquo;s failure to
use insider &lt;em&gt;shibboleths&lt;/em&gt; of the programming languages they&amp;rsquo;re trying
to criticize. Outside of the &amp;ldquo;C&amp;rdquo; and &amp;ldquo;C++&amp;rdquo; communities, &amp;ldquo;C/C++&amp;rdquo; is a
fairly common way to refer to the two related programming languages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But also, he was calling them out when they were right.  In the specific
category that the NSA was talking about, there actually is no difference,
as I also mention in my post:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;While there might be 30+ years of divergence between C and C++, none
of C++&amp;rsquo;s so-called &amp;ldquo;progress&amp;rdquo; involved removing memory-unsafe C features
from C++, many of which are still in common use, and many of which still
make memory safety in C++ near intractible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Perhaps we all should spend more time thinking critically than nit-picking
word choice. And perhaps I should find something better to do than
writing blog posts joining the fray, so that&amp;rsquo;s all I&amp;rsquo;ll say on the issue
for now.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>C&#43;&#43; Papercuts</title>
      <link href="https://www.thecodedmessage.com/posts/c&#43;&#43;-papercuts/" />
      <id>https://www.thecodedmessage.com/posts/c&#43;&#43;-papercuts/</id>
      <updated>2023-08-26T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;&lt;em&gt;UPDATE: Wow, this post has gotten popular! I&amp;rsquo;ve written
a &lt;a href=&#34;https://www.thecodedmessage.com/posts/c++-additions/&#34;&gt;new post&lt;/a&gt; that adds new papercuts combined
with concrete suggestions for how C++ could improve, if you are
interested. Also, if you want to read more about C++&amp;rsquo;s
deeper-than-papercut issues, I recommend specifically
my post on its &lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;move semantics&lt;/a&gt;. Thank you for reading!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My current day job is now again a C++ role. And so, I find myself again
focusing in this blog post on the downsides of C++.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;&lt;em&gt;UPDATE: Wow, this post has gotten popular! I&amp;rsquo;ve written
a &lt;a href=&#34;https://www.thecodedmessage.com/posts/c++-additions/&#34;&gt;new post&lt;/a&gt; that adds new papercuts combined
with concrete suggestions for how C++ could improve, if you are
interested. Also, if you want to read more about C++&amp;rsquo;s
deeper-than-papercut issues, I recommend specifically
my post on its &lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;move semantics&lt;/a&gt;. Thank you for reading!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;My current day job is now again a C++ role. And so, I find myself again
focusing in this blog post on the downsides of C++.&lt;/p&gt;
&lt;p&gt;Overall, I have found returning to active C++ dev to be exactly what
I expected: I still have the skills, and can still be effective in
it, but now that I have worked in a more modern programming language
with less legacy cruft, the downsides of C++ sting more. There are so
many features I miss from Rust, not only the obvious safety features,
or even primarily those, but also features that C++ could easily add,
like first-class support for sum types (called &lt;code&gt;enum&lt;/code&gt;s in Rust), or
tuples. (&lt;strong&gt;Clarification for C++ Fans:&lt;/strong&gt; &lt;code&gt;std::tuple&lt;/code&gt; and &lt;code&gt;std::variant&lt;/code&gt;
are &lt;em&gt;not&lt;/em&gt; first class support, and if you&amp;rsquo;re used to first class
support, you know how unacceptably clunky they are.)&lt;/p&gt;
&lt;p&gt;In this blog post, I will focus on the minor problems of C++ that
have affected me the most, the little usability &lt;em&gt;papercuts&lt;/em&gt;, the petty
inconveniences that just waste time. Instead of focusing on comparing
them to Rust or other programming languages, I will focus on why they
don&amp;rsquo;t make sense from a C++ point of view, with reference to just C++.
I know better than to hope that by doing this that die-hard C++ fans will
accept my criticism, but perhaps it will be relatable to C++ programmers
who don&amp;rsquo;t have Rust experience.&lt;/p&gt;
&lt;p&gt;Before I start getting into the papercuts, though, I want to address
one of the primary defenses I&amp;rsquo;ve seen of C++, one that I&amp;rsquo;ve found
particularly baffling. It goes something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;C++ is a great programming language. The complaints are just from
people who aren&amp;rsquo;t up to it. If they were better programmers,
they&amp;rsquo;d appreciate the C++ way of doing things, and they wouldn&amp;rsquo;t
need their hand held. Languages like Rust are not helpful for
such true professionals.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Obviously, the phrasing is a bit of a parody, but I&amp;rsquo;ve seen this
sort of attitude so many times. The most charitable view I can take
of it is a claim that C++&amp;rsquo;s difficulty is a sign of its power, and
the natural cost of using a powerful programming language. What it
reads like to me in many cases, however, is as a form of elitism:
a general idea that making things easy for poorer programmers is
pointless, and that good programmers don&amp;rsquo;t benefit from making
things easier.&lt;/p&gt;
&lt;p&gt;As someone who has programmed C++ professionally for a majority of my
career, and who has taught (company-internal) classes in advanced C++,
this is nonsense to me. I do know how to navigate the many papercuts
and foot-guns of C++, and am happy to do so when working on a C++
codebase. But experienced as I am, they still slow me down and
distract me, taking focus away from the actual problems I&amp;rsquo;m trying
to solve, and resulting in less maintainable code.&lt;/p&gt;
&lt;p&gt;And as for the upside, I see very little that C++ gets in exchange for
all of this difficulty. The only ways in which C++ is more performant
or more appropriate than Rust are in terms of platform support, legacy
codebases, optimizations that are only available in specific compilers
that happen to not support Rust, or other concerns irrelevant to the
actual design of the programming language.&lt;/p&gt;
&lt;p&gt;While I am proud of my C++ skills, I am not too proud to appreciate
that better technology can render them partially obsolete. I am not
too proud to appreciate having features that make it easier. In most
cases, it&amp;rsquo;s not a matter of the programming language doing more work
for me, but of C++ creating unnecessary extra make-work, often
due to decisions that made sense when they were made, but have long
since stopped making sense &amp;ndash; don&amp;rsquo;t get me started on header files!&lt;/p&gt;
&lt;p&gt;But I also want my programming language to be beginner-friendly. I am
always going to work with other programmers with a variety of skill-sets,
and I would rather not have to clean up my colleagues&amp;rsquo; mistakes &amp;ndash;
or mistakes of earlier, more foolish versions of myself. If making a
programming language more beginner-friendly sacrifices power, then I
agree that some programming languages should not do it. But many, even
most of C++&amp;rsquo;s beginner-unfriendly (and expert-annoying) features do not
in fact make the language more powerful.&lt;/p&gt;
&lt;p&gt;So, without further ado, here are the biggest papercuts I&amp;rsquo;ve noticed
in the past month of returning to C++ development.&lt;/p&gt;
&lt;h1 id=&#34;const-is-not-the-default&#34;&gt;&lt;code&gt;const&lt;/code&gt; is not the default&lt;/h1&gt;
&lt;p&gt;It is very easy to forget to mark a parameter &lt;code&gt;const&lt;/code&gt; when it can be.
You can just forget to type the keyword. This is especially true for
&lt;code&gt;this&lt;/code&gt;, which is an implicit parameter: there is no time when you are
typing out the &lt;code&gt;this&lt;/code&gt; parameter explicitly, and therefore it won&amp;rsquo;t sit
there looking funny without the appropriate modifiers.&lt;/p&gt;
&lt;p&gt;If C++ had the opposite default, where every value, reference, and pointer
was &lt;code&gt;const&lt;/code&gt; unless explicitly declared mutable, then we&amp;rsquo;d be much more
likely to have every parameter declared correctly based on whether the
function needs to mutate it or not. If someone includes a &lt;code&gt;mutable&lt;/code&gt; keyword,
it would be because they know they need it. If they need it and forget it,
the compiler error would remind them.&lt;/p&gt;
&lt;p&gt;Now, you might not think this is important, because you can just not
use &lt;code&gt;const&lt;/code&gt; and have functions with capabilities they don&amp;rsquo;t need &amp;ndash;
but sometimes you have to take things by &lt;code&gt;const&lt;/code&gt; in C++. If you take a
parameter by non-&lt;code&gt;const&lt;/code&gt; reference, the caller can only use lvalues to
call your function. But if you take a parameter by &lt;code&gt;const&lt;/code&gt; reference,
the caller can use lvalues or rvalues.  So some functions, in order to
be used in natural ways, must take their parameters by &lt;code&gt;const&lt;/code&gt; reference.&lt;/p&gt;
&lt;p&gt;Once you have a &lt;code&gt;const&lt;/code&gt; reference, you can only (easily) call functions
with it that accept &lt;code&gt;const&lt;/code&gt; references, and so if any of those functions
forgot to declare the parameter &lt;code&gt;const&lt;/code&gt;, you have to include a &lt;code&gt;const_cast&lt;/code&gt;
&amp;ndash; or go change the function later to correctly accept &lt;code&gt;const&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Lest you think this is just a sloppy newbie error, note that
many functions in the standard library had to be updated to take
&lt;code&gt;const_iterator&lt;/code&gt; instead of or in addition to &lt;code&gt;iterator&lt;/code&gt; when it was
discovered correctly that they made sense with a &lt;code&gt;const_iterator&lt;/code&gt;:
functions like &lt;code&gt;erase&lt;/code&gt;. It turns out that for functions like &lt;code&gt;erase&lt;/code&gt;,
the collection is what has to be mutable, not the iterator &amp;ndash; a fact
that the maintainers of the C++ library simply got wrong at first.&lt;/p&gt;
&lt;h1 id=&#34;obligatory-copying&#34;&gt;Obligatory Copying&lt;/h1&gt;
&lt;p&gt;In C++, for an object to be copyable is the default, privileged way
for an object to behave. If you don&amp;rsquo;t want your object to be copyable,
and all its fields are copyable, you often have to mark the copy constructor
and copy assignment operator as &lt;code&gt;= delete&lt;/code&gt;. The default is for the compiler
to write code for you &amp;ndash; code that can be incorrect.&lt;/p&gt;
&lt;p&gt;If you do make your class move-only, however, beware, because
that means that there are situations where you can&amp;rsquo;t use
it. In C++11, there was no ergonomic way to do a lambda capture
by move &amp;ndash; which is usually how I want to capture variables
into a closure. This was &amp;ldquo;fixed&amp;rdquo; in C++14 &amp;ndash; for when you want what
should have been the default from the beginning, you can now use
extremely clunky move-capture syntax.&lt;/p&gt;
&lt;p&gt;However, even then, good luck using the lambda. If you
want to put it in a &lt;code&gt;std::function&lt;/code&gt;, you&amp;rsquo;re still out
of luck to this day. &lt;code&gt;std::function&lt;/code&gt; expects the object
it manages to be copyable, and will fail to compile if your
closure object is move-only. This is going to be addressed in C++23, with
&lt;a href=&#34;https://en.cppreference.com/w/cpp/utility/functional/move_only_function/move_only_function&#34;&gt;&lt;code&gt;std::move_only_function&lt;/code&gt;&lt;/a&gt;
&amp;ndash; but in the meantime, I have been forced to write classes with a copy
constructor that throws some sort of run-time logic exception.  And even
in C++23, copyable functions will be the default, assumed situation.&lt;/p&gt;
&lt;p&gt;This is strange, because most complicated objects, especially closures,
are never, and should never be, copied. Generally, copying a complicated
data structure is a mistake &amp;ndash; a missing &lt;code&gt;&amp;amp;&lt;/code&gt;, or a missing &lt;code&gt;std::move&lt;/code&gt;.
But it is a mistake that carries no warning with it, and no visible
sign in the code that a complex, allocation-heavy action is being
undertaken. This is an early lesson to new C++ devs &amp;ndash; don&amp;rsquo;t pass
non-primitive types by value &amp;ndash; but it&amp;rsquo;s possible for even advanced devs
to mess up from time to time, and once it&amp;rsquo;s in the codebase, it&amp;rsquo;s easy
to miss.&lt;/p&gt;
&lt;h1 id=&#34;by-reference-parameter-papercuts&#34;&gt;By-Reference Parameter Papercuts&lt;/h1&gt;
&lt;p&gt;It is unergonomic to return multiple values by tuple in C++. It can be
done, but the calls to &lt;code&gt;std::tie&lt;/code&gt; and &lt;code&gt;std::make_tuple&lt;/code&gt; are long-winded
and distracting, not to mention that you&amp;rsquo;ll be writing unidiomatically,
which is always bad for people who are reading and debugging your code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt;
Someone brought up structured bindings in a comment, as if this fixed
the issue. Structured bindings are a great example of the half-way fixes
that proponents of modern C++ love to cite. Structured bindings help
some, but if you think they make returning by tuple ergonomic, you&amp;rsquo;re
mistaken. You still need to either write &lt;code&gt;std::pair&lt;/code&gt; or
&lt;code&gt;std::make_tuple&lt;/code&gt; in the function return statement, or &lt;code&gt;std::tuple&lt;/code&gt;
in the function&amp;rsquo;s return type. This isn&amp;rsquo;t the worst, but it&amp;rsquo;s
still not as light-weight as full first-class tuple support, and
it&amp;rsquo;s not enough to have convinced people to not use out parameters,
which are my real complaint.&lt;/p&gt;
&lt;p&gt;And even at that, it&amp;rsquo;s not that out parameters (or in-out parameters)
are bad, but that they&amp;rsquo;re bad in C++, as there is no good way to
express them.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So what do we do instead? The clunkiness of tuples leads people to
instead use out parameters. To use an out parameter, you end up taking
a parameter by non-&lt;code&gt;const&lt;/code&gt; reference, meaning the function is supposed
to modify the parameter.&lt;/p&gt;
&lt;p&gt;The problem is, this is only marked in the function signature. If you
have a function that takes a parameter by reference, the parameter looks
the same as a by-value parameter at the call site:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// Return false on failure. Modify size with actual message size,
// decreasing it if it contains more than one message.
bool got_message(const char *mesg, size_t &amp;amp;size);

size_t size = buff.size();
got_message(buff.data(), size);
buff.resize(size);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you&amp;rsquo;re reading the calling code quickly, it might look like the
&lt;code&gt;resize&lt;/code&gt; call is redundant, but it is not. &lt;code&gt;size&lt;/code&gt; is being modified by
&lt;code&gt;got_message&lt;/code&gt;, and the only way to know that it is being modified is to
look at the function signature, which is usually in another file.&lt;/p&gt;
&lt;p&gt;Some people prefer out parameters and in-out parameters to be passed
by pointer for this very reason:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;bool got_message(const char *mesg, size_t *size);

size_t size = buff.size();
got_message(buff.data(), &amp;amp;size);
buff.resize(size);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is great &amp;ndash; or would be, if pointers weren&amp;rsquo;t nullable. What does
a &lt;code&gt;nullptr&lt;/code&gt; parameter mean in this context? Is it going to trigger
undefined behavior? What if you pass a pointer from a caller into it?
People often forget to document what functions do with a null pointer.&lt;/p&gt;
&lt;p&gt;This can be addressed with a non-nullable smart pointer, but very
few programmers actually do this in practice. When something isn&amp;rsquo;t
the default, it tends to not be used everywhere where appropriate.
The sustainable answer to this is changing the default, not heroic
attempts to fight human nature.&lt;/p&gt;
&lt;p&gt;Obligatory side-gripe:
At least in non-owning situations like this, it is possible to write
such a smart pointer. However, if you want to write the obvious companion,
a non-nullable owning smart pointer, a companion version of &lt;code&gt;std::unique_ptr&lt;/code&gt;,
then it cannot be done in a useful way, because such a pointer cannot
then &lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;be moveable&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;method-implementations-can-contradict&#34;&gt;Method Implementations Can Contradict&lt;/h1&gt;
&lt;p&gt;In C++, every time you write a class, especially a lower-level one,
you have a responsibility to make decisions about certain methods with
special semantic importance in the programming language:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Constructor (Copy):&lt;/strong&gt; &lt;code&gt;X(const X&amp;amp;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Constructor (Move):&lt;/strong&gt; &lt;code&gt;X(X&amp;amp;&amp;amp;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Assignment (Copy):&lt;/strong&gt; &lt;code&gt;operator=(const X&amp;amp;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Assignment (Move):&lt;/strong&gt; &lt;code&gt;operator=(X&amp;amp;&amp;amp;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Destructor:&lt;/strong&gt; &lt;code&gt;~X()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For many classes, the default implementations are enough, and if
possible you should rely on them. Whether or not this is possible
depends on whether naively copying all of the fields is a sensible
way to copy the entire object, which is surprisingly easy to forget
to consider.&lt;/p&gt;
&lt;p&gt;But if you need a custom implementation of one of these, you are on
the hook to write all of them. This is known as the &amp;ldquo;rule of 5.&amp;rdquo;
You have to write all of them, even though the correct behavior of the
two assignment operators can be completely determined by the
appropriate constructor combined with the destructor. The compiler could
make default implementations of the assignment operators that refer to
those other functions, and therefore would always be correct, but it
does not. Implementing them correctly is tricky, requiring techniques
like either explicitly protecting against self-assignment, or swapping
with a by-value parameter. In any case, they are boilerplate, and yet
another thing that can go wrong in a programming language that has many
such things.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt;
One commentator did not understand what I meant. It is true
that many classes can use &lt;code&gt;= default&lt;/code&gt; for all these methods.
However, IF you customize the copy constructor or move constructor,
you must THEN also customize the assignment operator to match,
even though the default implementation could have been correct,
if the language was defined more intelligently.&lt;/p&gt;
&lt;p&gt;I thought this was clear by citing the rule of 5, which essentially says this.&lt;/p&gt;
&lt;p&gt;The full rule is explained on &lt;a href=&#34;https://en.cppreference.com/w/cpp/language/rule_of_three&#34;&gt;CPP Reference&lt;/a&gt;.
If you customize the copy or move constructor, the corresponding &lt;code&gt;= default&lt;/code&gt;
assignment operator will be wrong. Be careful! Note how the
example code does not use &lt;code&gt;= default&lt;/code&gt; for the assignment operators,
even though the assignment operators contain no logic.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;modern-c&#34;&gt;&amp;ldquo;Modern&amp;rdquo; C++&lt;/h1&gt;
&lt;p&gt;After seeing comments on Hacker News, I felt compelled to add this
section. Every time someone complains about anything in C++, someone will
mention a newer version of C++ that fixes it. These &amp;ldquo;fixes&amp;rdquo; are usually
not that good, and only feel like fixes if you&amp;rsquo;re used to everything
being kind of clunky.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The default way still is the old, bad way. For example, capturing
lambdas by move should be the default, and &lt;code&gt;std::move_only_function&lt;/code&gt;,
coming soon in C++23, should have been the default &lt;code&gt;std::function&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For that reason, and because there&amp;rsquo;s never warnings enabled on the old,
bad way, even new coders keep doing things the bad way.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, I understand that this is important for backwards-compatibility.
But that is the entire problem: C++ has too many bad decisions accumulated.
Why was copying the default for parameter passing collections, let alone
for lambda capture? I know the historical reasons, but that doesn&amp;rsquo;t
mean that a modern programming language should work that way.&lt;/p&gt;
&lt;p&gt;Even C++11 couldn&amp;rsquo;t clean up the fact that raw pointers and
C-style arrays get nice syntax, while smart pointers and &lt;code&gt;std::array&lt;/code&gt;
look terrible. Even C++11 couldn&amp;rsquo;t clean up that it was working
around a language designed without moves.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Unfortunately, I am all too well aware of why these decisions were
made, and it is exactly one reason: Compatibility with legacy code.
C++ has no editions system, no way to deprecate core language
features.  If a new edition of C++ was made, it would &lt;a href=&#34;https://github.com/carbon-language/carbon-lang&#34;&gt;cease to be
C++&lt;/a&gt; &amp;ndash; though I
support the efforts of people to transition C++ to new syntax
and clean some of this stuff up.&lt;/p&gt;
&lt;p&gt;However, if you ignore backwards-compatibility and the large existing
codebases, none of these papercuts make the programming language more
powerful or better, just harder to use. I&amp;rsquo;ve seen good-faith arguments
in favor of human-maintained header files, surprising as that is to me, but I
challenge my readers to tell me what is beneficial about C++&amp;rsquo;s design
choices in these matters.&lt;/p&gt;
&lt;p&gt;You might find these things trivial, but these all slow programmers
down, while simultaneously annoying them. If you are experienced enough,
your subconscious might be adept at navigating it, but imagine what your
subconscious could do if it didn&amp;rsquo;t have to. But how adept are you at seeing
these mistakes in a code review from your junior colleagues? If you are a
rigorous reviewer, how much more time does it take? How adept are you at
finding these issues quickly when a bug arises?&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;d be more effective, more efficient, and happier if these issues were
resolved. Programming would be both enjoyable and faster to do.
What&amp;rsquo;s the downside? The only upside is continuity with history.
And while I can see the value in that, it is a very limited value,
with very limited scope.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>New Link: Technical Only RSS</title>
      <link href="https://www.thecodedmessage.com/posts/technical-only-rss/" />
      <id>https://www.thecodedmessage.com/posts/technical-only-rss/</id>
      <updated>2023-08-06T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;TLDR: I am adding a new link for RSS subscribers who just want
to subscribe to technical posts. The RSS feed has always been available,
but it is now explicitly one of the links across the top, for those
who want their RSS feed to only give them my new technical posts.&lt;/p&gt;
&lt;p&gt;I am writing this post primarily to let people know about this new
link, but I also want to muse on it a little.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;TLDR: I am adding a new link for RSS subscribers who just want
to subscribe to technical posts. The RSS feed has always been available,
but it is now explicitly one of the links across the top, for those
who want their RSS feed to only give them my new technical posts.&lt;/p&gt;
&lt;p&gt;I am writing this post primarily to let people know about this new
link, but I also want to muse on it a little.&lt;/p&gt;
&lt;p&gt;I realize that I have, in some ways, two blogs here in one website.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.thecodedmessage.com/&#34;&gt;The Coded Message&lt;/a&gt; is primarily read for its &lt;a href=&#34;https://www.thecodedmessage.com/tags/computers/&#34;&gt;technical
content&lt;/a&gt;, especially for the &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust/&#34;&gt;posts
about Rust&lt;/a&gt;. But I also write about &lt;a href=&#34;https://www.thecodedmessage.com/tags/nontechnical/&#34;&gt;other
topics&lt;/a&gt; that interest me, and those posts are
generally much less popular.&lt;/p&gt;
&lt;p&gt;I combine them on the same website for a few reasons.&lt;/p&gt;
&lt;p&gt;For one, it&amp;rsquo;s easier for me to have one blog. Blogging is a hobby for
me, and so it has to play second fiddle to other life obligations,
which is most of why I&amp;rsquo;ve been slow to finish some blog series and some
promised future posts &amp;ndash; I have not forgotten.  This also means that
anything that would make blogging harder for me, including separating
out these blogs into two fully separate websites, is likely to make me
blog substantially less. Laziness might not always be a virtue,
whatever Larry Wall &lt;a href=&#34;https://thethreevirtues.com/&#34;&gt;might say&lt;/a&gt;, but
some amount of it is essential to actually accomplishing goals, especially
in the hobby space.&lt;/p&gt;
&lt;p&gt;But there is also a reason besides laziness, that is a little harder to
articulate. As much as this blog largely concerns my professional work,
it is my personal blog. All of the programming posts are laden with my
personal opinions about programming, and this website is about everything
I personally have to say publicly on any topic, not just programming.
A separation between my professional and personal blogs would lead,
in my own mind, to a sense of obligation to make the professional blog
a polished resource for programmers, with more organization and possibly
even a regular schedule, as opposed to merely being a forum where I hold
forth on whatever topics interest me, which often but not always happens
to be programming.&lt;/p&gt;
&lt;p&gt;That said, I do make all my posts in the hopes that people read them,
and find them useful in some way (even if that use is, as for my
&lt;a href=&#34;https://www.thecodedmessage.com/tags/fiction/&#34;&gt;fiction&lt;/a&gt; posts, primarily entertainment). And I am aware
that a large portion of my readership primarily, or even exclusively,
finds my technical posts useful. As much as I may wish that all of my
readers who are here for Rust content also care about my &lt;a href=&#34;https://www.thecodedmessage.com/tags/nontechnical/&#34;&gt;musings on
other topics&lt;/a&gt;, I know that many of them do not,
or even seriously disagree with me on these topics.&lt;/p&gt;
&lt;p&gt;I try already to accommodate this. If you sign up for
my newsletter, by default, you are only subscribed to
technical posts, and you have to follow an additional link
and explicitly subscribe if you want other topics. If you go to
&lt;a href=&#34;https://www.thecodedmessage.com/&#34;&gt;www.thecodedmessage.com&lt;/a&gt; in your web
browser, you can click the link at the top labelled &lt;a href=&#34;https://www.thecodedmessage.com/tags/computers/&#34;&gt;Computers/Programming
Posts&lt;/a&gt;. And now, if you want to subscribe to just the
technical posts via RSS, there is also a link at the top for that purpose.&lt;/p&gt;
&lt;p&gt;I still encourage people who are interested in my other posts to read
them, and I still plan on having this website combined for at least
the medium-term future, but I wanted people to know that a technical-posts
only RSS feed was available, if they so chose.&lt;/p&gt;
&lt;p&gt;As always, I welcome feedback on my blog in the form of comments and
e-mails (jah259 at cornell dot edu). Thank you so much for reading!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Walk-Through: Prefix Ranges in Rust, a Surprisingly Deep Dive</title>
      <link href="https://www.thecodedmessage.com/posts/prefix-ranges/" />
      <id>https://www.thecodedmessage.com/posts/prefix-ranges/</id>
      <updated>2023-06-24T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&#34;https://vorpal.se/&#34;&gt;Arvid Norlander&lt;/a&gt; has
gone through the trouble of refactoring this code into a
&lt;a href=&#34;https://crates.io/crates/prefix-range&#34;&gt;crate&lt;/a&gt; and publishing it. Thank
you, Arvid!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Rust&amp;rsquo;s &lt;code&gt;BTreeMap&lt;/code&gt; and corresponding &lt;code&gt;BTreeSet&lt;/code&gt; are excellent,
B-tree-based sorted map and key types. The map implements
the ergonomic &lt;a href=&#34;https://www.thecodedmessage.com/posts/rust-map-entry/&#34;&gt;entry API&lt;/a&gt;, more flexible
than other map APIs, made possible by the borrow checker.
They are implemented with the more performant but more gnarly
&lt;a href=&#34;https://en.wikipedia.org/wiki/B-tree&#34;&gt;B-Tree&lt;/a&gt; data structure, rather than
the more common &lt;a href=&#34;https://en.wikipedia.org/wiki/AVL_tree&#34;&gt;AVL trees&lt;/a&gt; or
&lt;a href=&#34;https://en.wikipedia.org/wiki/Red%E2%80%93black_tree&#34;&gt;red-black trees&lt;/a&gt;.
All in all, they are an excellent piece of engineering, and an excellent
standard library feature.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;&lt;em&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&#34;https://vorpal.se/&#34;&gt;Arvid Norlander&lt;/a&gt; has
gone through the trouble of refactoring this code into a
&lt;a href=&#34;https://crates.io/crates/prefix-range&#34;&gt;crate&lt;/a&gt; and publishing it. Thank
you, Arvid!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Rust&amp;rsquo;s &lt;code&gt;BTreeMap&lt;/code&gt; and corresponding &lt;code&gt;BTreeSet&lt;/code&gt; are excellent,
B-tree-based sorted map and key types. The map implements
the ergonomic &lt;a href=&#34;https://www.thecodedmessage.com/posts/rust-map-entry/&#34;&gt;entry API&lt;/a&gt;, more flexible
than other map APIs, made possible by the borrow checker.
They are implemented with the more performant but more gnarly
&lt;a href=&#34;https://en.wikipedia.org/wiki/B-tree&#34;&gt;B-Tree&lt;/a&gt; data structure, rather than
the more common &lt;a href=&#34;https://en.wikipedia.org/wiki/AVL_tree&#34;&gt;AVL trees&lt;/a&gt; or
&lt;a href=&#34;https://en.wikipedia.org/wiki/Red%E2%80%93black_tree&#34;&gt;red-black trees&lt;/a&gt;.
All in all, they are an excellent piece of engineering, and an excellent
standard library feature.&lt;/p&gt;
&lt;p&gt;But they aren&amp;rsquo;t perfect, as I learned recently when I had a very specific
operation that I needed to perform on one. I scanned the method lists
diligently, trying to find the one I needed, but it was not there. &lt;code&gt;range&lt;/code&gt;
was close, but not quite there, and so I would simply have to implement
the operation by hand. &lt;code&gt;range&lt;/code&gt; is defined based on a start key (where,
at our option, it includes keys that are greater than or equal to that
key, or strictly greater than that key) and an end key (where the keys in
the range are either less than or equal, or strictly less than that key).&lt;/p&gt;
&lt;p&gt;Here is an example of the use of &lt;code&gt;range&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; BTreeSet::new();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ABC&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DEF&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DEG&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;HIJ&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;KLM&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NOP&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; elem &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; set.range(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DEF&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;N&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{elem}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It outputs starting with &lt;code&gt;&amp;quot;DEF&amp;quot;&lt;/code&gt;, continuing in order
through the set, but not including &lt;code&gt;&amp;quot;NOP&amp;quot;&lt;/code&gt;, as that is
greater than &lt;code&gt;&amp;quot;N&amp;quot;&lt;/code&gt; (lexigraphically and therefore according to &lt;code&gt;&amp;amp;str&lt;/code&gt;&amp;rsquo;s
&lt;code&gt;Ord&lt;/code&gt; instance). If &lt;code&gt;&amp;quot;N&amp;quot;&lt;/code&gt; were in the set, it would not be printed,
as &lt;code&gt;..&lt;/code&gt; is exclusive on the right side. &lt;code&gt;..=&lt;/code&gt; would include it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Maps and sets: A brief aside&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This discussion only concerns the keys of a map.
For simplicity&amp;rsquo;s sake, throughout the discussion, I&amp;rsquo;ll be using
&lt;code&gt;BTreeSet&lt;/code&gt;, a wrapper around &lt;code&gt;BTreeMap&lt;/code&gt; for when there are
just keys (that are still unique and sorted) and no values. Internally,
it contains a &lt;code&gt;BTreeMap&lt;/code&gt; with the zero-sized struct &lt;code&gt;SetValZST&lt;/code&gt; as its
value type.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;the-problem&#34;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;But that isn&amp;rsquo;t the exact operation I needed. I needed all of the keys
(which were also &lt;code&gt;String&lt;/code&gt;) that started with a certain prefix. So, if
the set was as in the example above, and the prefix was &lt;code&gt;&amp;quot;DE&amp;quot;&lt;/code&gt;, this
operation would give me &lt;code&gt;&amp;quot;DEF&#39;,&amp;quot;DEG&amp;quot;&lt;/code&gt;. As you can see from the example,
and as is easy to prove in general, when the keys are sorted, all the
keys starting with a prefix form a contiguous range. But it is not
a range that can be expressed with the &lt;code&gt;range&lt;/code&gt; operation.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s close, tantalizingly close. Due to the definition of &lt;code&gt;Ord&lt;/code&gt; on
&lt;code&gt;String&lt;/code&gt;, our prefix-based range starts with the first key that is
greater than or equal to the prefix, as strings starting with a prefix
always compare greater to or equal to the prefix. This side of the range
is therefore expressable with the &lt;code&gt;range&lt;/code&gt; operation.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s the other side that causes the problem. We don&amp;rsquo;t have a key where
all the keys in the prefix are less than that key. We know that once we
hit a key string that doesn&amp;rsquo;t start with the prefix, it must be greater
than all the keys that do, as must all subsequent ones, but we cannot
express this bound easily in terms of the prefix. We would need an element
that is either the greatest possible key that starts with that prefix,
or else the least possible key that does not.&lt;/p&gt;
&lt;p&gt;There is a lot of efficiency to be gained by taking advantage of the fact
that the range we want is contiguous, which is why the &lt;code&gt;range&lt;/code&gt; method exists.
But there is no operation that covers this scenario, because of the
narrowness of how the &lt;code&gt;range&lt;/code&gt; operation is defined.&lt;/p&gt;
&lt;p&gt;On the one hand, this is frustrating. We are so close to being able to
do this straight-forwardly with the provided operations. It also seems
like it would be more performant to determine the bounds of that range
by doing a tree search, rather than trying to implement this operation by
hand. Without this operation being available, we seem doomed to slowness.&lt;/p&gt;
&lt;p&gt;On the other hand, it&amp;rsquo;s understandable. The key type of a map is only
really expected to implement the &lt;code&gt;Ord&lt;/code&gt; trait, and nothing about &lt;code&gt;Ord&lt;/code&gt; has
anything to do with prefixes. Creating ranges with &lt;code&gt;range&lt;/code&gt; was allowed,
but based on inclusive and exclusive bounds, which is to say, purely
based on ordering of opaque elements. Evaluating a prefix as a range,
on the other hand (or even merely proving that the keys forming a prefix
do indeed constitute a contiguous range) would be outside of the scope
of the operations represented by the &lt;code&gt;Ord&lt;/code&gt; trait.&lt;/p&gt;
&lt;p&gt;So I needed a way of getting keys that start with a specific prefix.
So what did I do? I simply coded a manual form of the operation,
looping starting from the beginning of the range, and checking each
iteration whether we&amp;rsquo;d left the range yet:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; key &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; keys.range::&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, _&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;((Bound::Included(prefix), Bound::Unbounded)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;key.starts_with(prefix) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;// We&amp;#39;ve gone past the end of the range
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ... Actually do something with the key
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This seemed reasonable enough. My colleagues asked me to put in a comment
to clarify that, since the map was sorted, all the items with a prefix
would be contiguous, and therefore &lt;code&gt;break&lt;/code&gt; was correct and not &lt;code&gt;continue&lt;/code&gt;.
It worked, and was performant enough for my purposes in writing the code,
but perhaps not as much as ideally could be achieved. I couldn&amp;rsquo;t help
but wonder if it could be made a little more performant if it were part of the
standard library, if we had insight into and ability to access the inner
structure of how a &lt;code&gt;BTreeSet&lt;/code&gt; is laid out. Obviously, in such a case
the code would also be more concise, and (more importantly) obviously
correct, without need for a comment.&lt;/p&gt;
&lt;p&gt;The performance considerations, if present, however, would be
minimal. Looping through a &lt;code&gt;BTreeSet&lt;/code&gt; is a reasonable operation, and I
took advantage of the fact that my range was contiguous to stop once we&amp;rsquo;d
gone past the last item. At best, explicit library support for prefixes
would simply detect this condition slightly sooner, further up in the
tree, without having to actually find the node with the offending item.&lt;/p&gt;
&lt;p&gt;The next bit of code I wrote was for a closely related operation: dropping
values outside of the prefix. What I wrote seemed like it definitely
would be substantially less performant than a specially coded operation
from the standard library would be. It certainly was harder to prove correct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;prefixed&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; set: &lt;span style=&#34;color:#a6e22e&#34;&gt;BTreeSet&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;, prefix: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BTreeSet&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; set.split_off(prefix);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; not_in_prefix &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;set).iter().find(&lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;s&lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;s.starts_with(prefix));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; not_in_prefix &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; not_in_prefix.map(&lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt;s&lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; s.to_owned());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; Some(not_in_prefix) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; not_in_prefix {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.split_off(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;not_in_prefix);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This uses two calls to &lt;code&gt;split_off&lt;/code&gt;, which like &lt;code&gt;range&lt;/code&gt; needs a concrete
&lt;code&gt;T&lt;/code&gt;, a concrete &lt;code&gt;String&lt;/code&gt;, to serve as a comparison-point for where to
split. And it is certainly less performant than a dedicated method would
have been, as it also uses a call to &lt;code&gt;find&lt;/code&gt; to find a concrete &lt;code&gt;String&lt;/code&gt;
for the end of the range, which constitutes an additional loop through
all the strings in the range.&lt;/p&gt;
&lt;h1 id=&#34;questions&#34;&gt;Questions&lt;/h1&gt;
&lt;p&gt;This raised two questions in my mind:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Is there a way to convert a prefix into a range that can be used with
&lt;code&gt;range&lt;/code&gt; and &lt;code&gt;split_off&lt;/code&gt;?  More concretely, is there a way to construct
a &lt;code&gt;String&lt;/code&gt; such that it is the least possible &lt;code&gt;String&lt;/code&gt; that is still
greater than all the possible strings that start with our prefix,
but less than or equal to all strings that do not? Would doing so
in fact improve performance?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How hard would it be to add this feature to the standard library,
both for iterating and for splitting the set?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this blog post, we will focus on the first question. The second
question is reserved for a future blog post.&lt;/p&gt;
&lt;h1 id=&#34;testing-prefixed&#34;&gt;Testing &lt;code&gt;prefixed&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;code&gt;prefixed&lt;/code&gt; function needs the optimization more than the loop,
so we&amp;rsquo;ll focus on that in our discussion. And as we&amp;rsquo;re discussing an
optimization of the &lt;code&gt;prefixed&lt;/code&gt; function, and as it is in any case a
gnarly function, we will want to write some unit tests for it.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s one example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[test]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;it_works&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; BTreeSet::new();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hey&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;heyyy&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;H&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prefixed(set, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;H&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;assert_eq!&lt;/span&gt;(set.len(), &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;assert!&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;set.contains(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;heyyy&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This probably isn&amp;rsquo;t enough. Additional unit tests will be left as an
exercise to the reader.&lt;/p&gt;
&lt;h1 id=&#34;constructing-an-upper-bound&#34;&gt;Constructing an upper bound&lt;/h1&gt;
&lt;p&gt;So, let us return to our example. In our example, the prefix was &lt;code&gt;&amp;quot;DE&amp;quot;&lt;/code&gt;.
As discussed, the lower bound is easy: Everything that starts with a
&lt;code&gt;&amp;quot;DE&amp;quot;&lt;/code&gt; is greater than or equal to &lt;code&gt;&amp;quot;DE&amp;quot;&lt;/code&gt;.  Strings outside of the range
to the left will not:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DD&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt;);       &lt;span style=&#34;color:#75715e&#34;&gt;// Prints &amp;#34;false&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt;);       &lt;span style=&#34;color:#75715e&#34;&gt;// Prints &amp;#34;true&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DEF&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt;);      &lt;span style=&#34;color:#75715e&#34;&gt;// Prints &amp;#34;true&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DEG&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt;);      &lt;span style=&#34;color:#75715e&#34;&gt;// Prints &amp;#34;true&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DF&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt;);       &lt;span style=&#34;color:#75715e&#34;&gt;// Still prints &amp;#34;true&amp;#34; -- need something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NOP&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt;);      &lt;span style=&#34;color:#75715e&#34;&gt;// Still prints &amp;#34;true&amp;#34; -- need something
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The upper bound is also easy enough, actually &amp;ndash; we just need to
increment the last character. Anything that starts with a &lt;code&gt;&amp;quot;DE&amp;quot;&lt;/code&gt;
will also compare strictly less to &lt;code&gt;&amp;quot;DF&amp;quot;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DE&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DF&amp;#34;&lt;/span&gt;);        &lt;span style=&#34;color:#75715e&#34;&gt;// Prints &amp;#34;true&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DEF&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DF&amp;#34;&lt;/span&gt;);       &lt;span style=&#34;color:#75715e&#34;&gt;// Prints &amp;#34;true&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DEG&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DF&amp;#34;&lt;/span&gt;);       &lt;span style=&#34;color:#75715e&#34;&gt;// Prints &amp;#34;true&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DF&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DF&amp;#34;&lt;/span&gt;);        &lt;span style=&#34;color:#75715e&#34;&gt;// Prints &amp;#34;false&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;NOP&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DF&amp;#34;&lt;/span&gt;);       &lt;span style=&#34;color:#75715e&#34;&gt;// Prints &amp;#34;false&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This seems easy enough to handle. We just need to write a function that
increments the last character in a string, something with this
signature:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;upper_bound_from_prefix&lt;/span&gt;(prefix: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;) -&amp;gt; String;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Incrementing the last character in a string seems like it&amp;rsquo;s
just a matter of incrementing the last byte, so let&amp;rsquo;s see
what that looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;upper_bound_from_prefix&lt;/span&gt;(prefix: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;) -&amp;gt; String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; prefix &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prefix.to_string();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;unsafe&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// SAFETY: It is not. ☹️. XXX
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; prefix_bytes &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prefix.as_bytes_mut();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        prefix_bytes[prefix_bytes.len() &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    prefix
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, that&amp;rsquo;s not good. It passes the unit test I wrote, but that&amp;rsquo;s because
we need to write more unit tests. Unfortunately, like many programmers
before us, we have forgotten about UTF-8. Rust requires all its strings
to be stored as valid UTF-8 as a safety invariant. Fortunately, because
we&amp;rsquo;re using Rust, we notice that we&amp;rsquo;re violating this invariant when an
operation we have to invoke is marked as &lt;code&gt;unsafe&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In order to capture this failure, we would have to write a unit
test where the prefix ends in a multi-byte Unicode character.
Unfortunately, because this is a safety issue, the test might not
even fail (but it might be worth doing as an exercise anyway).&lt;/p&gt;
&lt;p&gt;That isn&amp;rsquo;t even to mention the possibility that the prefix is empty,
which would result in a panic in this code!&lt;/p&gt;
&lt;p&gt;So, how can we get the last character of a string? &lt;code&gt;get&lt;/code&gt; allows us
to do substrings with byte indexes, but returns &lt;code&gt;None&lt;/code&gt; if it is not a
valid substring. We can loop backwards until we find an index that
works for the split, and we can return an option in case the string
is empty:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;upper_bound_from_prefix&lt;/span&gt;(prefix: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;) -&amp;gt; Option&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt; prefix.len()).rev() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; Some(last_char_str) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prefix.get(i&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; rest_of_prefix &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;debug_assert!&lt;/span&gt;(prefix.is_char_boundary(i));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                prefix[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;i]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// ???
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    None
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But that gives us two &lt;code&gt;str&lt;/code&gt;s, and we want to increment a char.
So we have to extract the singular &lt;code&gt;char&lt;/code&gt; from the &lt;code&gt;last_char_str&lt;/code&gt;,
which we know to have exactly one &lt;code&gt;char&lt;/code&gt; in it. Looking over the
operations of &lt;code&gt;str&lt;/code&gt;, we have only one real option:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; last_char &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; last_char_str
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .chars()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .next()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .expect(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;last_char_str will contain exactly one char&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;walking-through-chars&#34;&gt;Walking Through &lt;code&gt;char&lt;/code&gt;s&lt;/h1&gt;
&lt;p&gt;But once we do have a &lt;code&gt;char&lt;/code&gt;, we cannot simply do &lt;code&gt;+ 1&lt;/code&gt; on it.  This
operation isn&amp;rsquo;t defined on a &lt;code&gt;char&lt;/code&gt;. And before you say that we should
convert it to &lt;code&gt;u32&lt;/code&gt; and back, you should know that the operation is
left undefined on &lt;code&gt;char&lt;/code&gt; for a reason. &lt;code&gt;char&lt;/code&gt;s are supposed to remain
valid Unicode code points.&lt;/p&gt;
&lt;p&gt;So, we must do something else that will skip over invalid code points.
There is no obvious operation in &lt;code&gt;char&lt;/code&gt; that will do it, but if
we look in the &amp;ldquo;Trait Implementations&amp;rdquo; section, we find something
that looks potentially relevant: &lt;code&gt;Step&lt;/code&gt;. And looking at
&lt;code&gt;char&lt;/code&gt;&amp;rsquo;s implementation of &lt;code&gt;Step&lt;/code&gt;, we see the
&lt;a href=&#34;https://github.com/rust-lang/rust/blob/ee8b035faba3728644d36fbb689feb8047b965e6/library/core/src/iter/range.rs#L426-L440&#34;&gt;exact function&lt;/a&gt;
we want:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;forward_checked&lt;/span&gt;(start: &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;, count: &lt;span style=&#34;color:#66d9ef&#34;&gt;usize&lt;/span&gt;) -&amp;gt; Option&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; start &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; start &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; res &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Step::forward_checked(start, count)&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; start &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xD800&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0xD800&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; res {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        res &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Step::forward_checked(res, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x800&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; res &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;::&lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// SAFETY: res is a valid unicode scalar
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// (below 0x110000 and not in 0xD800..0xE000)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Some(&lt;span style=&#34;color:#66d9ef&#34;&gt;unsafe&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;::from_u32_unchecked(res) })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        None
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, this gives us an &lt;code&gt;Option&lt;/code&gt;. Why? Well, you can see that from
the code: What if &lt;code&gt;last_char&lt;/code&gt; is the highest possible Unicode code point,
&lt;code&gt;0x10FFFF&lt;/code&gt;, also known as &lt;code&gt;char::MAX&lt;/code&gt;? We&amp;rsquo;re going to procrastinate
handling this (admittedly rare) situation, and panic for now. Spoiler:
Fortunately, there is a solution, which we will discuss later.&lt;/p&gt;
&lt;p&gt;This is a great example of why Rust is great. Because this operation
is defined to return an &lt;code&gt;Option&lt;/code&gt;, we have to explicitly say what
we&amp;rsquo;re doing in case it returns &lt;code&gt;None&lt;/code&gt;. We don&amp;rsquo;t even have to have
a unit test for &lt;code&gt;0x10FFFF&lt;/code&gt; code-points in our prefix to realize
that we have to cover this case (although now would be
a great time to write one).&lt;/p&gt;
&lt;p&gt;Also unfortunately, we can&amp;rsquo;t directly call &lt;code&gt;forward_checked&lt;/code&gt; &amp;hellip; not
if we want to use stable Rust, in any case. It&amp;rsquo;s marked as a nightly-only
&amp;ldquo;unstable API.&amp;rdquo; Fortunately, however, we can access it indirectly,
through the &lt;code&gt;Range&lt;/code&gt; API. Some rooting around in the standard library
reveals that &lt;code&gt;nth&lt;/code&gt;, on an iterator on a closed range, calls
&lt;code&gt;forward_checked&lt;/code&gt;, yielding :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; last_char_incr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (last_char &lt;span style=&#34;color:#f92672&#34;&gt;..=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;::&lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .nth(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .expect(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;XXX fixme: can&amp;#39;t handle highest possible codepoint&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This actually works, with the caveat of handling &lt;code&gt;char::MAX&lt;/code&gt; set
aside. All my unit tests except my &lt;code&gt;0x10FFFF&lt;/code&gt; one pass. Altogether,
here is the state of things:
We have a &lt;code&gt;prefixed&lt;/code&gt; function that uses this to call
&lt;code&gt;split_off&lt;/code&gt; with an appropriate value, without iterating
through all the strings in range in the set:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;upper_bound_from_prefix&lt;/span&gt;(prefix: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;) -&amp;gt; Option&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;prefix.len()).rev() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; Some(last_char_str) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prefix.get(i&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; rest_of_prefix &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;debug_assert!&lt;/span&gt;(prefix.is_char_boundary(i));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;prefix[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;i]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; last_char &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; last_char_str
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .chars()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .next()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .expect(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;last_char_str will contain exactly one char&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; last_char_incr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (last_char&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .nth(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .expect(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;XXX fixme used highest possible codepoint&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; new_string &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;format!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{rest_of_prefix}{last_char_incr}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; Some(new_string);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    None
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;prefixed&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; set: &lt;span style=&#34;color:#a6e22e&#34;&gt;BTreeSet&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;, prefix: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BTreeSet&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; set.split_off(prefix);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; Some(not_in_prefix) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; upper_bound_from_prefix(prefix) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.split_off(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;not_in_prefix);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    set
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;cleaning-up-the-edge-case&#34;&gt;Cleaning Up the Edge Case&lt;/h1&gt;
&lt;p&gt;OK, now that we&amp;rsquo;ve got something that (kind of) works, it&amp;rsquo;s time
to do some clean-up.&lt;/p&gt;
&lt;p&gt;So, first, of course, we should address the &lt;code&gt;XXX fixme&lt;/code&gt;,
the &lt;code&gt;0x10FFFF&lt;/code&gt; case. So what do we do in that case? Well, if we
use &lt;code&gt;X&lt;/code&gt; to stand in for this &amp;ldquo;highest code point character&amp;rdquo;,
we can reason about it a little.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say the prefix is &lt;code&gt;&amp;quot;deX&amp;quot;&lt;/code&gt;. In order for something to be
out of the range of the prefix, it can&amp;rsquo;t start with &lt;code&gt;&amp;quot;deY&amp;quot;&lt;/code&gt;, as
there is no &lt;code&gt;&#39;Y&#39;&lt;/code&gt; character greater than &lt;code&gt;&#39;X&#39;&lt;/code&gt;. So, it would
have to differ on the previous character. It would have to start
with &lt;code&gt;&amp;quot;df&amp;quot;&lt;/code&gt; or greater.&lt;/p&gt;
&lt;p&gt;So, if our prefix ends with this special character, we can
simply drop it, and move one character back, and increment
that character instead. Strangely enough, that just means going
through our &lt;code&gt;for&lt;/code&gt; loop again (and no, I did not plan this). See,
if we keep going backwards to find another character to increment,
we&amp;rsquo;ll get the previous character. Our way of extracting characters
from the suffix works even if there&amp;rsquo;s more than one character in
the second substring &amp;ndash; it&amp;rsquo;ll just get the first character, which is
exactly what we want.&lt;/p&gt;
&lt;p&gt;So we can actually write:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; Some(last_char_incr) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (last_char &lt;span style=&#34;color:#f92672&#34;&gt;..=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;::&lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt;).nth(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Adding some comments to explain, and adjusting existing code to no
longer lie to the reader (&lt;code&gt;last_char_str&lt;/code&gt; might now contain more than
one character) we get this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;upper_bound_from_prefix&lt;/span&gt;(prefix: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;) -&amp;gt; Option&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;prefix.len()).rev() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; Some(last_char_str) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prefix.get(i&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; rest_of_prefix &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#a6e22e&#34;&gt;debug_assert!&lt;/span&gt;(prefix.is_char_boundary(i));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;prefix[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;i]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; last_char &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; last_char_str
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .chars()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .next()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .expect(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;last_char_str will contain at least one char&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; Some(last_char_incr) &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (last_char &lt;span style=&#34;color:#f92672&#34;&gt;..=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt;::&lt;span style=&#34;color:#66d9ef&#34;&gt;MAX&lt;/span&gt;).nth(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#75715e&#34;&gt;// Last character is highest possible code point.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#75715e&#34;&gt;// Go to second-to-last character instead.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; new_string &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;format!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{rest_of_prefix}{last_char_incr}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; Some(new_string);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    None
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If our string contains only copies of this highest possible code point,
this returns &lt;code&gt;None&lt;/code&gt;, which is appropriate because there will be no
strings greater than the strings prefixed with these characters, just like
there&amp;rsquo;s nothing that comes after names that start with &amp;ldquo;Z&amp;rdquo; in alphabetical
order, nor anything that comes after names that start with &amp;ldquo;Zz&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Note that if we want to save the other sets that are created by
&lt;code&gt;split_off&lt;/code&gt;, we can. We can easily modify this function to return all
three sets: The set of keys that come lexigraphically before the prefix, the
set that starts with the prefix, and the set of keys that come after the
keys that start with the prefix.&lt;/p&gt;
&lt;h1 id=&#34;performance&#34;&gt;Performance&lt;/h1&gt;
&lt;p&gt;This code certainly hasn&amp;rsquo;t been optimized to the fullest extent possible.
In such a case, we probably would want to do some more extreme
optimizations, like working with &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;/code&gt; rather than &lt;code&gt;String&lt;/code&gt;s, and
check if they were valid UTF-8 only at the point when it is necessary
(if it in fact is necessary for our application). Or, alternatively,
we might want to fork the standard library&amp;rsquo;s BTree implementation
and actually add this operation. Both of these are gnarly, but if the
absolute best possible performance was truly our goal, they would both be in
scope.&lt;/p&gt;
&lt;p&gt;But I am reserving that for a future blog post. Detailed profiling
of different implementations of this operation would require that level
of optimization to be fully interesting and is therefore also reserved for
a future blog post. Instead, here, I will walk through some informal
reasoning about the performance of this new implementation of &lt;code&gt;prefixed&lt;/code&gt;,
and whether it is also useful for iteration rather than splitting off
a new set.&lt;/p&gt;
&lt;p&gt;So, let&amp;rsquo;s do some back-of-the-envelope reckoning.  In creating this
upper bound, we had to reconstruct the prefix string, which costs us an
allocation as well as a string copy. In exchange, we saved an extra call
for &lt;code&gt;find&lt;/code&gt;, which might have had to loop over many, many strings that
start with this prefix. We can expect this implementation of &lt;code&gt;prefixed&lt;/code&gt; to
be more performant, therefore, in situations where there are many strings
that start with the prefix (and the prefix is not pathologically long).&lt;/p&gt;
&lt;p&gt;For iterating over the range, however, we would be making an allocation,
and only potentially saving us some walking through the tree. Given that
allocations are expensive (and potentially also involve some amount of
walking around memory), it&amp;rsquo;s probably not going to be worth it unless
the tree is extremely large.&lt;/p&gt;
&lt;h1 id=&#34;a-warning-unto-the-test-shy&#34;&gt;A Warning unto the Test-Shy&lt;/h1&gt;
&lt;p&gt;In an earlier draft of this post, I had the following code
to increment a &lt;code&gt;char&lt;/code&gt; rather than what I wrote above:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(last_char &lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;).nth(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This seems like it should work, in spite of having no upper bound.
It stands to reason that &lt;code&gt;char::MAX&lt;/code&gt; would, in such a case, serve
as an implicit upper bound. It does still return an &lt;code&gt;Option&amp;lt;char&amp;gt;&lt;/code&gt;,
and when would &lt;code&gt;None&lt;/code&gt; happen if not in such a situation?&lt;/p&gt;
&lt;p&gt;But fortunately, I had a test case:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[test]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;maxicode&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; BTreeSet::new();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hey&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;heyyy&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;H&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\u{10FFFF}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;eyyy&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;H&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\u{10FFFF}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;I&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set.insert(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;H&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        set
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; set &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; prefixed(set, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;H&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\u{10FFFF}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;assert_eq!&lt;/span&gt;(set.len(), &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;assert!&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;set.contains(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;I&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This test case, in that earlier code, actually panicked! It turns
out that in the case of an open-ended range like &lt;code&gt;(last_char ..)&lt;/code&gt;,
which results in a value of the type &lt;code&gt;RangeFrom&lt;/code&gt;, it is simply
assumed that going forward is possible. Instead of calling
&lt;code&gt;forward_checked&lt;/code&gt;, its
&lt;a href=&#34;https://github.com/rust-lang/rust/blob/ee8b035faba3728644d36fbb689feb8047b965e6/library/core/src/iter/range.rs#L880-L886&#34;&gt;&lt;code&gt;nth&lt;/code&gt; method&lt;/a&gt;
calls &lt;code&gt;forward&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[inline]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;nth&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self, n: &lt;span style=&#34;color:#66d9ef&#34;&gt;usize&lt;/span&gt;) -&amp;gt; Option&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;A&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; plus_n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Step::forward(self.start.clone(), n);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self.start &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Step::forward(plus_n.clone(), &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Some(plus_n)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And in
&lt;a href=&#34;https://github.com/rust-lang/rust/blob/ee8b035faba3728644d36fbb689feb8047b965e6/library/core/src/iter/range.rs#L87-L89&#34;&gt;&lt;code&gt;forward&lt;/code&gt;&lt;/a&gt;,
every &lt;code&gt;None&lt;/code&gt; is converted into a panic:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;forward&lt;/span&gt;(start: &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;, count: &lt;span style=&#34;color:#66d9ef&#34;&gt;usize&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Step::forward_checked(start, count).expect(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;overflow in `Step::forward`&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;I hope you enjoyed this walk-through. You can find the final
version of &lt;code&gt;prefixed&lt;/code&gt; and two test cases &lt;a href=&#34;https://www.thecodedmessage.com/range.rs&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Please let me know what you think of this format in the comments. Also
let me know if you have any follow-up topics you want me to explore,
or other problems you would want walk-throughs of.&lt;/p&gt;
&lt;p&gt;And, of course, please feel free to provide corrections and even
nit-picks!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>There is No One True Best Programming Language (but some are still better than others)</title>
      <link href="https://www.thecodedmessage.com/posts/best-programming-language/" />
      <id>https://www.thecodedmessage.com/posts/best-programming-language/</id>
      <updated>2023-05-24T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I am no stranger to programming language controversy. I have a &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;whole
category&lt;/a&gt; on my blog dedicated to explaining why Rust
is better than C++, and I&amp;rsquo;ve taken the extra step of organizing it into
an &lt;a href=&#34;https://www.thecodedmessage.com/rust-c-book/&#34;&gt;MDBook&lt;/a&gt; for everyone&amp;rsquo;s convenience. Most of them have
been argued about on Reddit, and a few even on Hacker News. Every single
one of them have been subject to critique, and in the process, I&amp;rsquo;ve been
exposed to every corner, every trope and tone and approach of programming
language &lt;del&gt;debate&lt;/del&gt; religious war, from the polite and well-considered
to the tiresome and repetitive all the way to the rude and non-sensical.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I am no stranger to programming language controversy. I have a &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;whole
category&lt;/a&gt; on my blog dedicated to explaining why Rust
is better than C++, and I&amp;rsquo;ve taken the extra step of organizing it into
an &lt;a href=&#34;https://www.thecodedmessage.com/rust-c-book/&#34;&gt;MDBook&lt;/a&gt; for everyone&amp;rsquo;s convenience. Most of them have
been argued about on Reddit, and a few even on Hacker News. Every single
one of them have been subject to critique, and in the process, I&amp;rsquo;ve been
exposed to every corner, every trope and tone and approach of programming
language &lt;del&gt;debate&lt;/del&gt; religious war, from the polite and well-considered
to the tiresome and repetitive all the way to the rude and non-sensical.&lt;/p&gt;
&lt;p&gt;There are two tropes in particular that many times have been proferred to
me (or rather, levered at me) about programming languages, two opposite
errors that I would like to critique. I would say that I&amp;rsquo;d like to nip
them in the bud, or respond to them once and for all, but I know the
power of my blog is limited, so instead I&amp;rsquo;d just like to give my opinion
on them, and explain why they are erroneous. Here are the errors:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There is one best programming language.&lt;/li&gt;
&lt;li&gt;Every programming language has its place.&lt;/li&gt;
&lt;/ol&gt;
&lt;h1 id=&#34;error-1-there-is-one-best-programming-language&#34;&gt;Error #1: There is one best programming language&lt;/h1&gt;
&lt;p&gt;Some languages have fans in the original sense of &lt;em&gt;fanatic&lt;/em&gt;. Some
languages inspire a level of devotion in programmers where they forswear
other programming languages with an almost religious loyalty. These
fanatics truly believe that the programming language is perfect, and that
no other language can so perfectly capture the structure of computing
and of algorithmic reasoning &amp;ndash; or even be acceptable in light of the
existence of a perfect programming language.&lt;/p&gt;
&lt;p&gt;Any threat to this programming monolatry is then attacked as intrinsically
irrational.  After all, if everyone would just do the basic and obvious
step of rewriting everything in this ideal programming language, then
all bugs would be fixed. Then, &amp;ldquo;the wolf also shall dwell with the lamb,
and the leopard shall lie down with the kid,&amp;rdquo; everyone will be immortal,
and the messiah will come&amp;hellip;  And this, of course, is insufferable to
normal people, who realize that programming languages are tools, not gods.&lt;/p&gt;
&lt;p&gt;Rust, admittedly, brings this out in people. So does Lisp, and so
does Haskell. And lest you think I&amp;rsquo;m exaggerating with the religious
references, someone even wrote a Haskell book entitled &lt;a href=&#34;https://cosmius.bitbucket.io/tkhe/&#34;&gt;&lt;em&gt;To Kata Haskellen
Evangelion&lt;/em&gt;&lt;/a&gt;, Biblical Greek for the
blasphemous and hopefully tongue-in-cheek title &lt;em&gt;The Gospel according
to Haskell&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I know what you&amp;rsquo;re thinking; I can hear it in my head. You&amp;rsquo;re thinking:
&amp;ldquo;You&amp;rsquo;re one to talk, Jimmy! &lt;a href=&#34;https://www.thecodedmessage.com/&#34;&gt;&lt;em&gt;The Coded Message&lt;/em&gt;&lt;/a&gt; is a Rust blog, and
worse, a Rust evangelism blog! How dare you criticize when you&amp;rsquo;re one
of the worst offenders?&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Nevertheless, in spite of what you might think, I don&amp;rsquo;t think Rust is
the one true programming language. I think it&amp;rsquo;s &lt;a href=&#34;https://www.thecodedmessage.com/posts/paradigm-shift/&#34;&gt;ahead of other mainstream
programming languages&lt;/a&gt; in terms of strong typing
and functional features (key word &amp;ldquo;mainstream&amp;rdquo;), and I personally enjoy
working on it full time, all true. But while I am a fan, I don&amp;rsquo;t think it&amp;rsquo;s
perfect, or even unique in most of the ways it&amp;rsquo;s good.&lt;/p&gt;
&lt;p&gt;Instead, I bring up this error for the reason I promised: Because
it has been levelled against me. Early on, with &lt;a href=&#34;https://www.thecodedmessage.com/posts/hello-rust/&#34;&gt;my first Rust
post&lt;/a&gt;, I wrote this statement (and see if you
can see why it was controversial):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If you are a systems programmer, if you are used to C and C++ and to
trying to solve systems programming types of problems, Rust is magical,
just like when you learned your previous favorite programming language.&lt;/p&gt;
&lt;p&gt;If you are not, Rust is overkill for your task at hand and you shouldn&amp;rsquo;t
be using it. I earnestly recommend Haskell.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This got me quite a bit of anger on Reddit. One commenter was furious that
I recommended Haskell, because they had tried to learn it in the past
and had a bad time. Another tried to tell me I was being stubborn because
the collected testimony of the Rust Reddit hadn&amp;rsquo;t somehow managed to override
my 18 years of professional programming experience and convince me that
garbage collection was not a necessary thing to have in a programming language
sometimes.&lt;/p&gt;
&lt;p&gt;And the key term there is Rust Reddit: There are some people there who
think everyone should be writing Rust, even people who have every reason
to benefit from a garbage collector and who have nothing to gain from
the strictness of a borrow checker, because they think Rust is just the
absolute best possible language. And the Rust sub-reddit does what any
good echo chamber does, and brings out that vibe in every Rustacean.&lt;/p&gt;
&lt;p&gt;But the echo chamber did not get me. Although I&amp;rsquo;ve moderated my opinion
some &amp;ndash; I&amp;rsquo;ve realized that there are some times where Rust beats out GC&amp;rsquo;d
languages for applications outside of my narrow definition of systems
programming, if only because it is both so mainstream and so successful
at bringing in modern FP features &amp;ndash; I still hold by my fundamental
point:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sometimes, indeed probably for most programming projects, Rust
is the wrong choice. Just like I wouldn&amp;rsquo;t use Excel to do systems programming,
I wouldn&amp;rsquo;t use Rust to keep track of splitting expenses on a trip.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Even for &amp;ldquo;serious&amp;rdquo; programming projects (whatever that means), sometimes,
you simply do need a garbage collector. Sometimes, the semantics of
Rust are too deep-cut or complicated to teach to the people you need
to do your programming.&lt;/p&gt;
&lt;p&gt;Heck, sometimes even existing infrastructure or existing legacy codebases
or just existing skillsets are more important than what programming
language features you have. Sometimes, Rust would take a re-write.
And re-writing in Rust is not a panacea, or even always
a good idea.&lt;/p&gt;
&lt;h1 id=&#34;error-2-every-programming-language-has-its-place&#34;&gt;Error #2: Every programming language has its place&lt;/h1&gt;
&lt;p&gt;This one of course gets levelled against me far more often, especially in
my Rust vs C++ debates. Most people realize programming languages
are technical tools, and a skilled programmer can pick new ones up with
relative ease. But some people act and talk instead as if, say, C++ programmers
were an ethnic or religious group. If I call for the gradual deprecation
and obsolescence of C++ in favor of Rust &amp;ndash; while understanding that
legacy code is a genuine concern that will be with us for decades &amp;ndash;
these people act as if I&amp;rsquo;m calling for crimes against humanity, saying
&lt;a href=&#34;https://en.wiktionary.org/wiki/sing_Kumbaya&#34;&gt;Kumbaya&lt;/a&gt;-reminiscent
statements like &amp;ldquo;All programming languages have their place.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;But of course, some tools are simply obsoleted by other tools. While Rust
won&amp;rsquo;t serve your needs if what you really need is garbage collection,
there are very few scenarios where C++ still beats Rust for new
development.  Sure, C++ has improved over time, but Rust doesn&amp;rsquo;t have a
legacy to weigh it down, and so can actually do things &lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;right the first
time&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some people disagree with this in a way I respect, because of support for
optimizing compilers, or the vagueness and immaturity of the semantics
of unsafe Rust, or some other concrete reason where C++ has something to
offer as a tool. Others simply live in worlds where too much code is in
C++, and it would be impossible to migrate anytime soon, and that also
makes sense to me. But I simply cannot take seriously an assertion that
in some axiomatic way, reminiscent of the intrinsic value of all human
beings, every programming language has its value.&lt;/p&gt;
&lt;p&gt;Why should this be true?  It&amp;rsquo;s not like which programming language someone
uses is an intrinsic quality. I&amp;rsquo;ve changed from a C++ programmer to a
Rust programmer, and so can you. Perhaps some of the people saying this
are hobbyist programmers, asserting the right of people to enjoy C++
personally, and to program it as nerds. And that&amp;rsquo;s fair! But that&amp;rsquo;s
also not what I&amp;rsquo;m talking about. I&amp;rsquo;m talking about what the best
programming language is to use for projects that people will use in
anger, where it matters whether a language is likely to &lt;a href=&#34;https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF&#34;&gt;lead to security
vulnerabilities&lt;/a&gt;
when used. If what programming language you use for such projects is
a key part of your identity, then that&amp;rsquo;s not an OK way to structure
your identity.&lt;/p&gt;
&lt;p&gt;If it were true that all languages had their place and their value, does
that mean that there should be shops writing in the obsolete versions of
C++, like the original C with Classes? Does that mean that there should be
shops writing code in &lt;a href=&#34;https://en.wikipedia.org/wiki/INTERCAL&#34;&gt;INTERCAL&lt;/a&gt;?
Does that mean that there&amp;rsquo;s some situations in which it&amp;rsquo;s best to do
greenfield development in COBOL?&lt;/p&gt;
&lt;p&gt;One example of this trope is the famous essay &lt;a href=&#34;https://meyerweb.com/eric/comment/chech.html&#34;&gt;&amp;quot;&amp;lsquo;Considered Harmful&amp;rsquo; Essays
Considered Harmful&amp;quot;&lt;/a&gt;,
which has of course been cited to criticize my own
&lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;&amp;ldquo;Considered Harmful&amp;rdquo; post&lt;/a&gt; (for
more on the &amp;ldquo;Considered Harmful&amp;rdquo; trope, see the &lt;a href=&#34;https://en.wikipedia.org/wiki/Considered_harmful&#34;&gt;Wikipedia
article&lt;/a&gt;).  Ironically
but unsurprisingly, &amp;ldquo;&amp;lsquo;Considered Harmful&amp;rsquo; Essays Considered Harmful&amp;rdquo; is
dogmatic in exactly the way it criticizes, in spite of giving itself a
(silly and ill-defended) out. In spite of recommending that &amp;ldquo;considered
harmful&amp;rdquo; essays be replaced by &amp;ldquo;benefits and weaknesses&amp;rdquo; lists,
or even &amp;ldquo;perceived benefits and weaknesses&amp;rdquo; lists, it does not follow
its own advice. It does not list benefits of the &amp;ldquo;Considered Harmful&amp;rdquo;
essays it considers harmful.&lt;/p&gt;
&lt;p&gt;So I will fill in this deficit. &amp;ldquo;Considered Harmful&amp;rdquo; essays are good
when a feature of a tool does indeed cause harm, and a better option is
available &amp;ndash; as is often actually the case. The title is a cliché, which
is a good thing in this case: it signals to the reader, in a light-hearted
way, what the thesis of the document is &amp;ndash; as opposed to &amp;ldquo;benefits and
weaknesses&amp;rdquo; lists which tend to be biased in any case and can amount
to passive-aggressiveness. Weaknesses in one&amp;rsquo;s argument or benefits in
one&amp;rsquo;s opponents argument can and should be acknowledged and addressed,
but that doesn&amp;rsquo;t mean you have to pretend not to have a position.
Just because something has some benefit doesn&amp;rsquo;t mean that it can&amp;rsquo;t, overall,
be fairly considered harmful.&lt;/p&gt;
&lt;p&gt;Indeed, my own post did do some &amp;ldquo;benefits and weaknesses,&amp;rdquo; in spite of
being titled as a &amp;ldquo;Considered Harmful&amp;rdquo; essay. It did spend some time
explaining why C++ made the decisions they did, and what the benefits
of C++&amp;rsquo;s decisions were, even in the context of a post about why these
decisions were considered harmful.  C++ had to implement non-destructive
moves for backwards-compatibility.  They had boxed themselves into them,
harmful as they are. That doesn&amp;rsquo;t make them any less harmful, but it
does make them understandable.&lt;/p&gt;
&lt;p&gt;So I disagree with the people who have used that post to criticize me,
and ask them why they don&amp;rsquo;t also turn the arguments of that post against
itself. Perhaps I could write:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;lsquo;&amp;ldquo;Considered Harmful&amp;rdquo; Essays Considered Harmful&amp;rsquo; Considered Harmful&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The only problem with this would be how to punctuate it. That and,
I&amp;rsquo;m sure it would widely be considered&amp;hellip; quite silly.&lt;/p&gt;
&lt;h1 id=&#34;conclusion-restatement-and-summary&#34;&gt;Conclusion: Restatement and Summary&lt;/h1&gt;
&lt;p&gt;Programming languages are tools. They are important tools, so it&amp;rsquo;s good
to make sure they are of high quality, and do the things we demand of
them, because they are often asked to do critical tasks for society. They
are also not to be conflated with the people using the tools, who can
retrain on new tools if they&amp;rsquo;re worth their salt.&lt;/p&gt;
&lt;p&gt;Tools should not be idolized, and tools cannot be perfect. It is
impossible to make a tool that can serve any purpose equally well
&amp;ndash; programming language design, in particular, will always have
trade-offs. However, it is possible to make a tool that loses to another
tool in all categories, and that is what C++ will soon be in comparison
to Rust, if it is not already there.&lt;/p&gt;
&lt;p&gt;And C++ programmers have their place in the new Rust world &amp;ndash; it&amp;rsquo;s
very easy to learn Rust from a C++ background. And C++ history has
its place there too &amp;ndash; Rust builds on C++, and it wouldn&amp;rsquo;t have been
possible without the contributions of those who worked on making C++
what it is. Everything that is community about C++, everything that is
people, everything that has moral value, can be migrated to Rust.&lt;/p&gt;
&lt;p&gt;But that doesn&amp;rsquo;t mean that C++, the tool, has a place in production
programming beyond legacy (i.e. pre-existing) projects. Again, there still
may be a few other valid reasons to favor C++ over Rust (though they&amp;rsquo;re
getting fewer and weaker with time), but a bald assertion that &amp;ldquo;every
language has its place&amp;rdquo; is not one of them.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>x86S: A Long Time Coming</title>
      <link href="https://www.thecodedmessage.com/posts/x86s/" />
      <id>https://www.thecodedmessage.com/posts/x86s/</id>
      <updated>2023-05-23T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Intel has just released a new &lt;a href=&#34;https://www.intel.com/content/www/us/en/developer/articles/technical/envisioning-future-simplified-architecture.html&#34;&gt;white
paper&lt;/a&gt;,
where they discuss removing a lot of the legacy cruft of the Intel/AMD
architecture they call Intel64. Only 64-bit operating systems &amp;ndash; and
a narrow set of 32-bit legacy apps that don&amp;rsquo;t use segmentation (a
small subset in theory but basically all of them in practice) &amp;ndash; will
be supported. I am surprised at how excited I am, although after all
this time perhaps the better word is &amp;ldquo;relieved.&amp;rdquo;&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Intel has just released a new &lt;a href=&#34;https://www.intel.com/content/www/us/en/developer/articles/technical/envisioning-future-simplified-architecture.html&#34;&gt;white
paper&lt;/a&gt;,
where they discuss removing a lot of the legacy cruft of the Intel/AMD
architecture they call Intel64. Only 64-bit operating systems &amp;ndash; and
a narrow set of 32-bit legacy apps that don&amp;rsquo;t use segmentation (a
small subset in theory but basically all of them in practice) &amp;ndash; will
be supported. I am surprised at how excited I am, although after all
this time perhaps the better word is &amp;ldquo;relieved.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Finally, Intel computers will dispense with the illusion that the default
mode is the DOS-compatible, 16-bit &amp;ldquo;real mode.&amp;rdquo; They will drop the conceit
that modern memory protection, not to mention the ability to address more
than 1MB of memory (approximately, yes I know about A20), is opt-in &amp;ndash;
which it currently, literally, is. All of the code to accommodate these
legacy modes can be phased out. All of the circuitry and/or microcode
to implement all of these legacy modes can be removed &amp;ndash; though I&amp;rsquo;m sure
Intel has had ways to keep it from doing too much damage, it definitely
increased the complexity of their processors.&lt;/p&gt;
&lt;p&gt;This is one of the biggest tech debt paydowns I&amp;rsquo;ve seen in a
long time. I have long felt about Intel architecture somewhat
analogously to how Richard P. Gabriel, author of &lt;a href=&#34;https://www.dreamsongs.com/RiseOfWorseIsBetter.html&#34;&gt;&amp;ldquo;The Rise of Worse
is Better&amp;rdquo;&lt;/a&gt;, felt
about C++ and Unix decades ago:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The good news is that in 1995 we will have a good operating system
and programming language; the bad news is that they will be Unix and C++.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Similarly, I have always felt that Intel architecture would become
reasonable someday, that it would gradually convert itself to something
less absurd than its traditional state. I was excited when AMD (not
Intel, note) came out with what Intel now calls Intel64, getting rid
of segmentation in 64-bit mode and adding 8 sorely needed additional
general-purpose registers (for a total of 16).&lt;/p&gt;
&lt;p&gt;Now, finally, they&amp;rsquo;re phasing out the legacy modes. No more DOS on a
modern PC (and it wouldn&amp;rsquo;t work anyway for other reasons). Good!&lt;/p&gt;
&lt;p&gt;Like many tech debt paydowns of this magnitude and this level of
historical relevance, it&amp;rsquo;s about the cognitive burden as much as it&amp;rsquo;s
about the actual implementation or the actual code and circuitry to
work around the complexity. We can now, slowly but surely, forget
the arcane details of how things used to be.&lt;/p&gt;
&lt;p&gt;It brings me a tinge of nostalgia, actually. 16-bit DOS programming
was where I first learned assembly, at least to read it. Segmentation
and the different processor modes was firmly in my awareness when I
used a DOS computer with Windows 3.1 as a child. I remember playing
with the edge cases, like &amp;ldquo;unreal mode&amp;rdquo; which was like real mode
but where each segment could be addressed with 32-bit registers.
Knowing the complexity of Intel architecture was relevant, and
part of how I learned computer architecture in general.&lt;/p&gt;
&lt;p&gt;But more recently, all of this knowledge has seemed overpresent.
Too many times I&amp;rsquo;ve seen people assume Intel architecture and bring
these old irrelevancies of PCs into conversation and even formal
talks, assuming familiarity with not just operating system and systems
concepts but the Intel-specific details of them. They&amp;rsquo;ll be talking
about registers and you&amp;rsquo;ll see that instead of generic names like &lt;code&gt;r3&lt;/code&gt;,
&lt;code&gt;r4&lt;/code&gt;, they&amp;rsquo;re talking about specific Intel registers. Or they&amp;rsquo;ll mention
&lt;code&gt;cr3&lt;/code&gt; instead of generically saying &amp;ldquo;page table base register,&amp;rdquo; or
&amp;ldquo;the &lt;code&gt;syscall&lt;/code&gt; instruction&amp;rdquo; or even the obsolescent 32-bit &lt;code&gt;int 0x80&lt;/code&gt;
instead of saying &amp;ldquo;issuing a syscall through a trap.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The biggest example is how often I hear people talking about &amp;ldquo;ring 0&amp;rdquo;
and &amp;ldquo;ring 3&amp;rdquo; when they should be saying &amp;ldquo;kernel mode&amp;rdquo; and &amp;ldquo;user mode.&amp;rdquo;
The numbered rings are so jarringly and gratuitously Intel-specific. It makes
me wonder if they genuinely think all processor architectures number
protection rings or privilege levels like that (they do not), or if they
think the intermediate rings between 0 and 3 are still relevant to modern
OS design on Intel (they are not). Or perhaps they&amp;rsquo;re just okay with assuming
Intel, ignoring the mobile and embedded worlds, and also bringing in an
irrelevant, overengineered concept while they&amp;rsquo;re at it.&lt;/p&gt;
&lt;p&gt;Maybe this will stop now that Intel is eliminating the unused rings 1
and 2. Maybe people will stop occasionally talking as if protected mode
was an exceptional mode, now that it won&amp;rsquo;t be a mode at all, but the only
way the processor runs.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>A New Garden: Rust vs C&#43;&#43; mdbook</title>
      <link href="https://www.thecodedmessage.com/posts/rust-v-c&#43;&#43;-mdbook/" />
      <id>https://www.thecodedmessage.com/posts/rust-v-c&#43;&#43;-mdbook/</id>
      <updated>2023-04-24T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Here it is, &lt;a href=&#34;https://www.thecodedmessage.com/rust-c-book/&#34;&gt;the Rust vs C++ mdbook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve wanted for a while to re-organize some of the
content on my blog into &lt;a href=&#34;https://www.thecodedmessage.com/gardens/&#34;&gt;gardens&lt;/a&gt;. I got
the idea from the blog post &lt;a href=&#34;https://hapgood.us/2015/10/17/the-garden-and-the-stream-a-technopastoral/&#34;&gt;“The Garden and the Stream: A
Technopastoral”&lt;/a&gt;.
Basically, some content is ill-suited to date-based, time-organized
systems like blogs. In fact, most of my content remains valid over a
long period of time, rather than participating in conversation (with
&lt;a href=&#34;https://www.thecodedmessage.com/posts/stroustrup-response/&#34;&gt;some exceptions&lt;/a&gt;), but
rapidly becomes less discoverable after I&amp;rsquo;ve written it, as it is
buried by newer posts.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Here it is, &lt;a href=&#34;https://www.thecodedmessage.com/rust-c-book/&#34;&gt;the Rust vs C++ mdbook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve wanted for a while to re-organize some of the
content on my blog into &lt;a href=&#34;https://www.thecodedmessage.com/gardens/&#34;&gt;gardens&lt;/a&gt;. I got
the idea from the blog post &lt;a href=&#34;https://hapgood.us/2015/10/17/the-garden-and-the-stream-a-technopastoral/&#34;&gt;“The Garden and the Stream: A
Technopastoral”&lt;/a&gt;.
Basically, some content is ill-suited to date-based, time-organized
systems like blogs. In fact, most of my content remains valid over a
long period of time, rather than participating in conversation (with
&lt;a href=&#34;https://www.thecodedmessage.com/posts/stroustrup-response/&#34;&gt;some exceptions&lt;/a&gt;), but
rapidly becomes less discoverable after I&amp;rsquo;ve written it, as it is
buried by newer posts.&lt;/p&gt;
&lt;p&gt;If I want to have content that is useful in a long-term fashion, the
blog is not the ideal structure. While you can always scroll down,
or look through &lt;a href=&#34;https://www.thecodedmessage.com/tags/&#34;&gt;tags&lt;/a&gt;, a more refined system would be
to store information in gradually evolving, more comprehensive
documents, that are gradually augmented or refined over time,
that is to say, a &lt;a href=&#34;https://www.thecodedmessage.com/gardens/&#34;&gt;garden&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://www.thecodedmessage.com/about/&#34;&gt;About Me&lt;/a&gt; page on a blog is one example of this, but
my blog series about &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;Rust vs. C++&lt;/a&gt; seemed like
another one where I had a lot of material that could be better structured
and more coherently presented in a single, hierarchical document.&lt;/p&gt;
&lt;p&gt;So I&amp;rsquo;ve posted it as an &lt;code&gt;mdbook&lt;/code&gt;, &lt;a href=&#34;https://www.thecodedmessage.com/rust-c-book/&#34;&gt;here&lt;/a&gt;. I don&amp;rsquo;t like
to think of this as a &amp;ldquo;book&amp;rdquo; in a form that would ever be published on
paper &amp;ndash; it&amp;rsquo;s not long enough, interesting enough, or complete enough for
that. That would also go away from the garden aesthetic, where it is a
continuous work-in-progress that is always evolving.  But I do think the
&lt;code&gt;mdbook&lt;/code&gt; format is better suited to the material than my existing blog
series, for long-term access.&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t incorporated all the material from my blog series yet, as some
of the older material I think could stand a re-write. It is
maintained in the open on &lt;a href=&#34;https://github.com/jhartzell42/rust-c-book/&#34;&gt;GitHub&lt;/a&gt;,
so feel free to give feedback there in terms of issues and even merge
requests. It&amp;rsquo;s released under the CC license for non-commercial,
attributed, share-alike use, with &lt;a href=&#34;https://github.com/jhartzell42/rust-c-book/blob/main/LICENSE&#34;&gt;this license file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While I will continue to try and integrate existing material into this
garden, and expand on it when I am inspired to do so, I plan on not focusing
on Rust vs. C++ going forward. If there are any substantial additions,
however, I will update you on this blog.&lt;/p&gt;
&lt;p&gt;Thank you for reading! More, different Rust content is coming soon!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Rust: A New Attempt at C&#43;&#43;&#39;s Main Goal</title>
      <link href="https://www.thecodedmessage.com/posts/rust-new-cpp/" />
      <id>https://www.thecodedmessage.com/posts/rust-new-cpp/</id>
      <updated>2023-04-06T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I know I set the &lt;a href=&#34;https://www.thecodedmessage.com/posts/review-2022&#34;&gt;goal&lt;/a&gt; for myself of doing less
polemics and more education, but here I return for another &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;Rust vs
C++&lt;/a&gt; post. I did say I doubted I would be able to
get fully away from polemics, however, and I genuinely think this post
will help contextualize the general Rust vs. C++ debate and contribute
to the conversation. Besides, most of the outlining and thinking for
this post &amp;ndash; which is the majority of the work of writing &amp;ndash; was already
done when I set that goal. It also serves as a bit of conceptual glue,
structuring and contextualizing many of my existing posts.  So please
bear with me as I say more on the topic of Rust and C++.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I know I set the &lt;a href=&#34;https://www.thecodedmessage.com/posts/review-2022&#34;&gt;goal&lt;/a&gt; for myself of doing less
polemics and more education, but here I return for another &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;Rust vs
C++&lt;/a&gt; post. I did say I doubted I would be able to
get fully away from polemics, however, and I genuinely think this post
will help contextualize the general Rust vs. C++ debate and contribute
to the conversation. Besides, most of the outlining and thinking for
this post &amp;ndash; which is the majority of the work of writing &amp;ndash; was already
done when I set that goal. It also serves as a bit of conceptual glue,
structuring and contextualizing many of my existing posts.  So please
bear with me as I say more on the topic of Rust and C++.&lt;/p&gt;
&lt;p&gt;Rust is a polarizing programming language, because of how radical it
is. It has &lt;a href=&#34;https://www.thecodedmessage.com/posts/paradigm-shift&#34;&gt;gone the furthest&lt;/a&gt; in introducing
features from functional programming languages into the mainstream world,
and ignoring long-held programming language design principles from the
realm of &lt;a href=&#34;https://www.thecodedmessage.com/tags/beyond-oop/&#34;&gt;object-oriented programming&lt;/a&gt;. Its fans can be
very enthusiastic, sometimes off-puttingly so, stereotypically demanding
that all software be rewritten in Rust even when completely unfeasible &amp;ndash;
a stereotype that is mostly untrue, but whose existence and occasional
true examples shows the intensity of the debate. But a lot of Rust&amp;rsquo;s
criticism comes specifically from C++ programmers, and correspondingly
a lot of Rustaceans&amp;rsquo; criticisms of other programming languages is
directed specifically at C++, including &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;mine&lt;/a&gt;. Even
the creator of C++, while not mentioning it by name, &lt;a href=&#34;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2739r0.pdf&#34;&gt;entered the
fray&lt;/a&gt;
(and along with other Rustaceans, &lt;a href=&#34;https://www.thecodedmessage.com/posts/stroustrup-response/&#34;&gt;I
responded&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a good reason for this particular rivalry. While usable in other
domains, Rust is strongest where C++ has hitherto been unopposed: as a
high-level systems programming language. Many of Rust&amp;rsquo;s greatest strengths
are &lt;a href=&#34;https://www.thecodedmessage.com/posts/raii/&#34;&gt;directly based off of ideas originated in C++&lt;/a&gt;. And
Rust has, in many ways, the same goals that C++ has. It can be argued &amp;ndash;
and in this post I shall argue &amp;ndash; that Rust has the exact same overall
goal that C++ does, albeit with a different interpretation of
how that goal is best accomplished.&lt;/p&gt;
&lt;h1 id=&#34;zero-cost-abstractions&#34;&gt;Zero-Cost Abstractions&lt;/h1&gt;
&lt;p&gt;C++ has an explicit goal of providing zero-cost abstractions.&lt;/p&gt;
&lt;p&gt;This is a bit of a confusing term of art and has the potential
to be misleading, but it comes attached with explanations that
clarify it some. It is also referred to as the &amp;ldquo;zero-overhead
principle,&amp;rdquo; which Dr. Bjarne Stroustrup, father of C++,
&lt;a href=&#34;https://www.stroustrup.com/ETAPS-corrected-draft.pdf&#34;&gt;explains&lt;/a&gt; (see
pg. 4) describes as containing two components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What you don’t use, you don’t pay for (and Dr. Stroustrup means
&amp;ldquo;paying&amp;rdquo; in the sense of performance costs, e.g. in higher latency,
slower throughput, or higher memory usage)&lt;/li&gt;
&lt;li&gt;What you do use, you couldn’t hand code any better&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is also an &lt;a href=&#34;https://en.cppreference.com/w/cpp/language/Zero-overhead_principle&#34;&gt;executive summary of the
concept&lt;/a&gt;
at &lt;a href=&#34;https://en.cppreference.com/w/&#34;&gt;CppReference.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I, however, prefer the terminology of &amp;ldquo;zero-cost abstraction,&amp;rdquo;
confusing as it can be, because it embodies a hidden third principle,
that is unstated among those other two, and against which those other
two principles are balanced. The word &amp;ldquo;abstraction&amp;rdquo; is the key, and the
third principle is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can still get the abstractive and expressive power you expect from
a modern programming language.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This third principle is necessary to distinguish higher-level &amp;ldquo;zero cost&amp;rdquo;
languages like C++ and Rust from lower-cost languages like C.&lt;/p&gt;
&lt;p&gt;To fully explain why I include this third principle, and to delve into
the history of the concept in general, I want to talk more about C.&lt;/p&gt;
&lt;h1 id=&#34;c-the-portable-assembly&#34;&gt;C: The Portable Assembly&lt;/h1&gt;
&lt;p&gt;C has often been described as a &amp;ldquo;portable assembly language.&amp;rdquo; Unlike
other high level programming languages before it (&amp;ldquo;high level&amp;rdquo; at
the time meaning anything higher level than raw assembly language),
it exposed users directly to gnarly machine-language abstractions like
pointers, and to common assembly-language capabilities like shifting
and bitwise operators.&lt;/p&gt;
&lt;p&gt;The goal was to give the programmer something minimally distinct from
assembly language, where the programmer had almost as much control over
the computer as an assembly language programmer without sacrificing
portability. Few higher-level features have been added, even now:
there was no built-in string type, and only a limited array type that
exposed the underlying concept of pointers the instant you poked at it.
Structures are little more than a way of calculating offsets, and memory
management is done by explicitly invoking memory management routines.&lt;/p&gt;
&lt;p&gt;C&amp;rsquo;s preference, in general, was to only add onto assembly those features
absolutely necessary for portability, and not to impose any other
structure on the programmer &amp;ndash; or, said another way, not to provide
any other structure to the programmer.&lt;/p&gt;
&lt;p&gt;This was far from an iron-clad rule. And there are definitely exceptions:
C, built into the programming language, prefers null-terminated strings
(also known as &amp;ldquo;C strings&amp;rdquo;) to arrangements that use specific lengths,
a substantial constraint on the programmer beyond assembly language and
probably a mistake overall.&lt;/p&gt;
&lt;p&gt;More deeply, and probably less avoidably at the time, C assumes a
traditional call structure. Many techniques that can be used to
implement closures, co-routines, or other more radical alternatives
to a call stack are difficult to impossible to do with standard C &amp;ndash;
while generally being possible in any assembly language.&lt;/p&gt;
&lt;p&gt;But, with these exceptions, C generally does tend to only provide
one overarching abstraction, portability, and when it does, it
has the same zero-cost goals that C++ has, to only make the user
pay for the abstractions they actually use, and to provide abstractions
as efficiently as the equivalent hand-coded assembly.&lt;/p&gt;
&lt;p&gt;Put another way, C++&amp;rsquo;s zero-cost overhead principle, as Dr. Stroustrup
defines it, is more or less inherited from C. Where C++ differs from
C is in the &amp;ldquo;abstraction&amp;rdquo; part of providing &amp;ldquo;zero-cost abstractions.&amp;rdquo;
Everything you can do in C++ you can do in (potentially tedious and
repetitive and error-prone) C, but C++ provides more abstractions,
beyond just what is necessary for portability.&lt;/p&gt;
&lt;h1 id=&#34;c-a-more-abstracted-c&#34;&gt;C++: A More Abstracted C&lt;/h1&gt;
&lt;p&gt;This gives us a framework for understanding the entire goal of C++,
and I would argue, of Rust. Once we understand that C++ is trying to
keep the zero-cost principle of C, where abstractions do not come
with a performance penalty (and where &amp;ldquo;zero&amp;rdquo; is a reference to the
difference between the performance cost and a manual assembly-language
implementation), but with the expressive and abstractive power of a
higher-level programming language, everything else about C++ makes sense.&lt;/p&gt;
&lt;p&gt;C++ was originally christened &amp;ldquo;C with Classes,&amp;rdquo; and it tried to add
Object-Oriented Programming to C. All the mechanisms of OOP could be
portably added to C directly by an application or library developer
with judicious use of function pointers and structure nesting (and
&lt;a href=&#34;https://en.wikipedia.org/wiki/GLib&#34;&gt;&lt;code&gt;glib&lt;/code&gt;&lt;/a&gt; is a famous example of a
library that does exactly that), but C++ built this abstraction
into the programming language itself.&lt;/p&gt;
&lt;p&gt;Objective-C also did this (and according to Wikipedia it &amp;ldquo;first appeared&amp;rdquo;
one year sooner in 1984), but Objective-C has always felt like two
programming languages glued together. In Objective-C, the object-oriented
features do not inherit the zero-overhead principle from C &amp;ndash; nor do they
look like C at all. They look instead like a Smalltalk dialect, where
switching between C and this odd Smalltalk dialect was permitted on an
expression-by-expression basis using an odd mix of square brackets and
&lt;code&gt;@&lt;/code&gt;-signs.&lt;/p&gt;
&lt;p&gt;In C++, the added abstractions, including OOP, take on more of
a resemblance to C, and importantly, continue to try to retain
C&amp;rsquo;s advantages in systems programming by making the new features
zero-overhead.&lt;/p&gt;
&lt;p&gt;During much of the history of C++, OOP was considered to be the most
important abstraction that a programming language could offer. But
once it was added, it expanded the scope of C++ abstractions. Nowadays,
C++ is considered multi-paradigm, and provides not just OOP, but a
wide array of abstraction.&lt;/p&gt;
&lt;p&gt;Nowadays, C++ tries to keep up with other programming languages in
what features it offers, to the extent that it can while being limited
by the zero-cost principle. This is in sharp contrast to C, which
continues to try to define existing features better and make them
more rigorous within the existing feature scope. The only features
C++ rejects out of hand are those that do not jive with zero-cost
abstraction, showing that in actuality C++&amp;rsquo;s defining trait is to
have the three-pronged concept of zero-cost abstraction that
I introduced above, two prongs about &amp;ldquo;zero cost&amp;rdquo; and one about
&amp;ldquo;abstraction&amp;rdquo;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What you don’t use, you don’t pay for&lt;/li&gt;
&lt;li&gt;What you do use, you couldn’t hand code any better&lt;/li&gt;
&lt;li&gt;We give you the power of abstraction expected for a programming language
of the day&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is why garbage-collection is not offered in C++ (though it is still
possible to implement manually) &amp;ndash; it cannot be offered in a zero-cost
way. However, C++&amp;rsquo;s alternative to garbage collection, namely
&lt;a href=&#34;https://www.thecodedmessage.com/posts/raii/&#34;&gt;RAII&lt;/a&gt;, continues to become more effective as new features
like move semantics and &lt;code&gt;std::unique_ptr&lt;/code&gt; were added, to the extent that
in modern C++, it would be unimaginable not to have those features,
and they have become essential to C++&amp;rsquo;s memory management model.&lt;/p&gt;
&lt;p&gt;These three goals explain why C++ keeps accruing new features,
whereas C maintains the features it has. They explain why C++ had
to add templates &amp;ndash; as a zero-cost alternative to OOP, or a zero-cost
way of implementing collections. They explain why C++ had to add move
semantics &amp;ndash; because without it, RAII is a worse abstraction than GC.&lt;/p&gt;
&lt;h1 id=&#34;rust-a-c-redo&#34;&gt;Rust: A C++ Redo&lt;/h1&gt;
&lt;p&gt;Rust simply does a better job at achieving these goals, because Rust
gets to start from scratch, with the modern concept of what&amp;rsquo;s expected in
a high-level programming language, rather than working forwards through
time. And, in doing so, it avoids a lot of the mistakes that C++ made, and
can design a language that includes all of the modern features together.&lt;/p&gt;
&lt;p&gt;A full set of OOP features is no longer ideologically required, so Rust
&lt;a href=&#34;https://www.thecodedmessage.com/tags/beyond-oop/&#34;&gt;doesn&amp;rsquo;t offer them&lt;/a&gt;. Instead, safety has become
a &lt;em&gt;sine qua non&lt;/em&gt;, so Rust offers that (with an opt-out provision).
One might argue that safety violates the zero-cost abstraction because
of bounds checking, but that&amp;rsquo;s simply not true as defined. You only
pay for bounds checks if you&amp;rsquo;re actually using the feature of safety
&amp;ndash; unchecked unsafe accesses &lt;a href=&#34;https://www.thecodedmessage.com/posts/unsafe/&#34;&gt;are in fact available just an &lt;code&gt;unsafe&lt;/code&gt; keyword
away&lt;/a&gt; &amp;ndash; and the feature of safety is implemented as
efficiently as one would by hand (by inserting bounds checks into array
accesses).&lt;/p&gt;
&lt;p&gt;Similarly, C++ has learned that move semantics turn out to be essential
in an RAII/value-semantics model to avoid spurious copy-and-deletes and/or
indirections for e.g. storing &lt;code&gt;std::string&lt;/code&gt;s in a &lt;code&gt;std::vector&lt;/code&gt; that might
be resized. Before move semantics, C++ often forced violations of the
zero-cost abstraction principle by providing abstractions that would do
extraneous copies or required extra indirections to use effectively, which
is not what an assembly language programmer would ever write. However,
since C++ move semantics were bolted on after the fact, it does them in a
&lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;deeply confusing way&lt;/a&gt;, where Rust gets to reset and
design itself for destructive moves from the get-go.&lt;/p&gt;
&lt;h1 id=&#34;a-note-on-the-raii-model&#34;&gt;A Note on &amp;ldquo;the RAII Model&amp;rdquo;&lt;/h1&gt;
&lt;p&gt;In my &lt;a href=&#34;https://www.thecodedmessage.com/posts/raii/&#34;&gt;RAII post&lt;/a&gt; I referred to C++&amp;rsquo;s alternative
to garbage collection, centered on RAII, as the &amp;ldquo;RAII model,&amp;rdquo; and wrote
that &lt;code&gt;std::unique_ptr&lt;/code&gt; and move semantics were essential to this model.
A Reddit comment later explained that I must be confused, because RAII
pre-dates those features.&lt;/p&gt;
&lt;p&gt;They had misunderstood me, and I stand by my statements, but I think it
is worth some clarification. By &amp;ldquo;RAII model,&amp;rdquo; I mean RAII and other
features which, when combined, provide an alternative to garbage collection.
And the RAII model before C++11 did indeed lack features essential to
competing with garbage collection. It was simply a worse model then, and
much harder to use correctly in a complicated codebase.&lt;/p&gt;
&lt;p&gt;In a similar way, I would say that in Rust, borrow checking and
destructive moves are essential to the RAII model, because without it,
the model is a much worse competitor to garbage collection. And yes,
that does imply that C++&amp;rsquo;s concept of RAII is fundamentally deficient
by not being paired with borrow checking, just like pre-C++11 RAII was
fundamentally deficient by not being paired with move semantics and
&lt;code&gt;std::unique_ptr&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The alternative to garbage collection that C++ and Rust have built has
been a work in progress through most of its history. Rust had to
be a new programming language rather than an evolution for a number of
reasons, but fixing C++&amp;rsquo;s lack of borrow checking and &lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;weird move
semantics&lt;/a&gt; were some of the most important such
reasons.&lt;/p&gt;
&lt;h1 id=&#34;backwards-compatibility&#34;&gt;Backwards-Compatibility&lt;/h1&gt;
&lt;p&gt;Of course, C++ does have goals that Rust drops &amp;ndash; and in doing so,
it can do better at this core goal. The biggest such goal is perhaps
also a trivial example: C++ has the goal of being source-compatible
with earlier versions of C++, and even to some extent with C. This
makes sense, as backwards-compatibility between versions is sort of a
fundamental expectation of any programming language, certainly one that
tries to provide a modern set of abstractions, but it does restrain
C++&amp;rsquo;s development.&lt;/p&gt;
&lt;p&gt;While Rust tries to be backwards compatible with itself, dropping
compatibility with C++ has allowed it to get out of a lot of C++&amp;rsquo;s
&lt;a href=&#34;https://www.thecodedmessage.com/posts/multiparadigm/&#34;&gt;accumulated cruft of complexity&lt;/a&gt;, much
of which is inherited from C times.&lt;/p&gt;
&lt;p&gt;This accomplishes a lot on its own. C++&amp;rsquo;s syntax has gotten
so complex over the years that many in the C++ community are
doing their own resets of the syntax, including Herb Sutter&amp;rsquo;s
&lt;a href=&#34;https://github.com/hsutter/cppfront&#34;&gt;&lt;code&gt;cppfront&lt;/code&gt;&lt;/a&gt; and Google&amp;rsquo;s
&lt;a href=&#34;https://github.com/carbon-language/carbon-lang&#34;&gt;Carbon&lt;/a&gt;.  Even if
starting from scratch to accomplish C++&amp;rsquo;s goals was the only thing Rust
did, it would still result in a much better programming language, more
ergonomic and with fewer pitfalls.&lt;/p&gt;
&lt;p&gt;Some criticize Rust by saying that in another 30 or 50 years, Rust will
end up as convoluted as C++ is now. This criticism has confused me,
because it seems possible, even likely, that this is true, but that
doesn&amp;rsquo;t strike me as a reason to not (gradually and responsibly) switch
from C++ to Rust (especially for new projects or for when rewrites are
particularly called for). If this is true, that just means programming
languages are subject to entropy and obsolescence like everything
else. And in that case, C++ will just continue to get worse, Rust will
also continue to get worse, and Rust will be better than C++ the entire
time. If all programming languages accrue cruft as they age, in what
world is that a reason to use the cruftier programming language?&lt;/p&gt;
&lt;p&gt;Most Rustaceans are not, despite the stereotype, treating Rust as some
apocalyptic, messianic programming language to end all programming
languages. I wouldn&amp;rsquo;t be surprised if 20 or 30 years from now, a new
programming language will emerge, accomplishing the same goals from a
fresh start. And when that happens, I will probably advocate in favor
of this new programming language just like I now advocate in favor of
Rust.&lt;/p&gt;
&lt;p&gt;The goal isn&amp;rsquo;t to have an eternally good programming languages; the
goal is to have tools now. What should new projects be written in now?
When a rewrite is called for (as it sometimes is), should it include a
new programming language now that there is a viable alternative?&lt;/p&gt;
&lt;p&gt;I suspect that many making this argument are including an unstated
assumption &amp;ndash; that C++&amp;rsquo;s cruft is actually a sign of its maturity, and
fitness for production use. Alternatively, and a little more charitably,
they might assume that Rust isn&amp;rsquo;t ready for production use yet, and by
the time it is, it will be just as crufty as C++, perhaps converging to
the same level of cruft. But while there are a few categories where Rust
lags C++, they are mistaken in the big picture. For the vast majority
of C++ projects, Rust is already a better option for if the project had
to be rewritten from scratch (a big &amp;ldquo;if,&amp;rdquo; but irrelevant to the merits
of the programming languages).&lt;/p&gt;
&lt;h1 id=&#34;rust-deficits&#34;&gt;Rust Deficits&lt;/h1&gt;
&lt;p&gt;Rust has a few downsides compared to C++.&lt;/p&gt;
&lt;p&gt;Interfacing with C is an important goal for reasons besides
backwards-compatibility. On many platforms, C serves as a
lowest-common-denominator programming language, and its ABI serves as an
&lt;a href=&#34;https://faultlore.com/blah/c-isnt-a-language/&#34;&gt;inter-language protocol&lt;/a&gt;.
C++ does provide smoother interfacing with this protocol than Rust does.&lt;/p&gt;
&lt;p&gt;Relatedly, C++ generally has a relatively stable ABI on a given platform
for a given compiler vendor. This allows dynamic libraries to be used
as plugins with minimal glue code, something that in Rust normally
requires awkwardly working through a C ABI interface. Personally, I think
machine-language plugins as dynamically loaded libraries are mostly
a relic of past software distribution models, and haven&amp;rsquo;t seen many
situations where they make sense, but I could think of a few edge cases.&lt;/p&gt;
&lt;p&gt;In both of these cases, Rust is clumsier, but not completely incapable.
Rust still can speak the protocol that is the C ABI, just not as natively
and smoothly-integrated as C++.&lt;/p&gt;
&lt;p&gt;Other downsides of Rust have to do with network effects and Rust
adoption. There is only one Rust compiler, while there are multiple
C++ compilers, that work together through a standards process. GCC
is currently in the process of getting Rust support, and we&amp;rsquo;ll see
how well that works out for Rust.&lt;/p&gt;
&lt;p&gt;Similarly, there are a lot of libraries that exist in C++ that don&amp;rsquo;t
yet exist in Rust or have Rust bindings. Though that&amp;rsquo;s true of any
pair of programming languages, it is a specific reason some developers
might still want to write new projects in C++ in favor of Rust.&lt;/p&gt;
&lt;p&gt;Finally, while I still think Rust would be a better programming language
than C++ even if unsafe code were allowed everywhere, I think Rust
could do more to make its rules clearer in the unsafe realm. The fact
that the latest research on Rust&amp;rsquo;s memory models seems so deeply
difficult to square with how &lt;code&gt;async&lt;/code&gt; code often works &lt;a href=&#34;https://github.com/rust-lang/unsafe-code-guidelines/issues/148&#34;&gt;as in this
bug report&lt;/a&gt;
makes me nervous.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m sure there are other ways in which Rust is behind C++, and the
devil is as always in the details. I&amp;rsquo;m sure I&amp;rsquo;ll find out about some
of them as soon as I post this post.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;This was all topics I&amp;rsquo;ve discussed in other blog posts, but I hope this
brings some perspective on how I think about the programming languages
in general, and provides a conceptual framework for thinking about some
of my other posts. I was a fan of C++ because of its goals, and I&amp;rsquo;m now
a fan of Rust because I think Rust pulls them off better. When I was
skeptical of Rust, it was because I did not think Rust would pull them
off better, but that was due to a misunderstanding.&lt;/p&gt;
&lt;h1 id=&#34;next-steps&#34;&gt;Next Steps&lt;/h1&gt;
&lt;p&gt;I am considering using (a revised version of) this post
as an introduction, and then trying to bring all of my
Rust vs C++ content into an &lt;code&gt;mdbook&lt;/code&gt; so it could be more of a
&lt;a href=&#34;https://hapgood.us/2015/10/17/the-garden-and-the-stream-a-technopastoral/&#34;&gt;garden&lt;/a&gt;.
It would have a title like &amp;ldquo;Rust: A Better C++ Than C++&amp;rdquo; and be licensed
under some CC non-commercial license, and it would accept MRs from
other people as a community resource for consolidating resources on this
particular issue. Then, if I had further ideas I could put them in there.
What do people think of that idea?&lt;/p&gt;
&lt;p&gt;I realize now that I write this that the repo where I
already have the bones of this idea is actually &lt;a href=&#34;https://github.com/jhartzell42/rust-c-book&#34;&gt;already
public&lt;/a&gt;. I think I&amp;rsquo;m going
to restart from scratch with just a reorganization existing blog posts,
and save the more ambitious ideas in those notes files for later. What
do people think?&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Guest Collaboration: Paradigm Shift</title>
      <link href="https://www.thecodedmessage.com/posts/paradigm-shift/" />
      <id>https://www.thecodedmessage.com/posts/paradigm-shift/</id>
      <updated>2023-03-28T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Does the choice of programming language matter?&lt;/p&gt;
&lt;p&gt;For years, many programmers would answer &amp;ldquo;no&amp;rdquo;. There was an &amp;ldquo;OOP
consensus&amp;rdquo; across languages as different as C++ and Python. Choice
of programming language was just a matter of which syntax to use to
express the same OOP patterns, or what libraries were needed for the
application. Language features like type checking or closures were seen
as incidental, mere curiosities or distractions.&lt;/p&gt;
&lt;p&gt;To the extent there was a spectrum of opinions, it was between OOP
denizens and those that didn&amp;rsquo;t really think software architecture mattered
at all &amp;mdash; an feeble attempt of corporatization against true programmers
and their free-spirited ways. The office park versus the squatters. That&amp;rsquo;s
how we got the wave of so-called &amp;ldquo;scripting languages&amp;rdquo;.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Does the choice of programming language matter?&lt;/p&gt;
&lt;p&gt;For years, many programmers would answer &amp;ldquo;no&amp;rdquo;. There was an &amp;ldquo;OOP
consensus&amp;rdquo; across languages as different as C++ and Python. Choice
of programming language was just a matter of which syntax to use to
express the same OOP patterns, or what libraries were needed for the
application. Language features like type checking or closures were seen
as incidental, mere curiosities or distractions.&lt;/p&gt;
&lt;p&gt;To the extent there was a spectrum of opinions, it was between OOP
denizens and those that didn&amp;rsquo;t really think software architecture mattered
at all &amp;mdash; an feeble attempt of corporatization against true programmers
and their free-spirited ways. The office park versus the squatters. That&amp;rsquo;s
how we got the wave of so-called &amp;ldquo;scripting languages&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;But OOP was the least of their concerns. They shrugged along with some
sort of class system, and save their criticism for (static) types and
compilation (an implementation strategy, not language property).&lt;/p&gt;
&lt;p&gt;Now, times are changing. When in the last 30 years have we seen so many
concurrent pivots in major languages?&lt;/p&gt;
&lt;p&gt;Perhaps it began with lambdas. Once, they were seen as curiosities from
the functional world, a special case of an OOP class overriding a single
method (which is exactly how you had to write them in C++ in Java). Now,
Java has lambdas.  Even JavaScript thought its &lt;code&gt;function()&lt;/code&gt; syntax was too
heavy, replacing it with a lighter-weight &lt;code&gt;=&amp;gt;&lt;/code&gt;. Hold up, even &lt;em&gt;Excel&lt;/em&gt; has
lambdas. Functional programming has intruded against the mainstream consensus.&lt;/p&gt;
&lt;p&gt;When this intrusion broke through, the old equilibrium cracked. Both the
OOP consensus and scripting language counterculture started to crumble.
Now, Javascript, Python, and Ruby are getting type checking. Java is
getting a whole mish-mash of &amp;ldquo;functional&amp;rdquo; features. C++ is de-emphasizing
inheritance and doubling down instead on templates. Even Go is getting
generics.&lt;/p&gt;
&lt;p&gt;So here we&amp;rsquo;ve reached a funny point. Before we had a bunch of languages
which roughly did the same thing. Now we have the same bunch of languages
all adopting the same features they never dreamed of having before. Within
that cohort there is &lt;em&gt;still&lt;/em&gt; little reason to adopt one or another,
but over time there are clear reasons to choose the newer versions over
the older versions. You might not care about Java vs Go, but you sure
as hell want the version with generics over the versions that don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;So among 20+ year old languages, the choice of languages absolutely
matters for programmers with time machines (or contemplating Debian
stable), but what about for the rest of us?&lt;/p&gt;
&lt;p&gt;Well, there are newer languages now mainstream (enough) too. And here we
find the front of the pack, the language bringing functional features
into the mainstream more completely and thoroughly than others (because
being born with them helps): Rust.&lt;/p&gt;
&lt;p&gt;There are other languages zooming out in front of the pack, leading Rust
just as Rust leads the others. Being way out ahead is exciting. But it
can be lonely. It might be cold. And you might run out of steam. Being at
the front of the pack, the furthest along of the mainstream, is nice. You
still see where we&amp;rsquo;re going better. You go there early. But you&amp;rsquo;re not
alone; you&amp;rsquo;re shoulder to shoulder with others doing the same.&lt;/p&gt;
&lt;p&gt;If that sounds nice, learn Rust. Don&amp;rsquo;t learn it as a mish-mash of exotic
cool features. And don&amp;rsquo;t let it lull you into thinking you must do some
sort of whiz-bang systems programming that almost no one does.&lt;/p&gt;
&lt;p&gt;Learn Rust, idiomatic Rust, yes, for solving all the mundane problems
you face in your programming life, but also to get a head start on what
will be the next era of accepted programming practice. Learn type classes
(aka traits) in their full power (and not just the object-safe ones),
and learn how Rust&amp;rsquo;s move semantics can be used to simulate type-state.&lt;/p&gt;
&lt;p&gt;These features might seem niche now, but remember, so once did lambdas.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Rust Tidbits #1</title>
      <link href="https://www.thecodedmessage.com/posts/rust-tidbits-1/" />
      <id>https://www.thecodedmessage.com/posts/rust-tidbits-1/</id>
      <updated>2023-03-24T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;This is a collection of little Rust thoughts that weren&amp;rsquo;t complicated
enough for a full post. I saved them up until I had a few, and now I&amp;rsquo;m
posting the collection. I plan on continuing to do this again for
such little thoughts, thus the #1 in the title.&lt;/p&gt;
&lt;h1 id=&#34;serde-flattening&#34;&gt;&lt;code&gt;serde&lt;/code&gt; flattening&lt;/h1&gt;
&lt;p&gt;What if you want to read a JSON file, process some of the fields, and
write it back out, without changing the other fields? Can you still use
&lt;code&gt;serde&lt;/code&gt;? Won&amp;rsquo;t it only keep fields that you know about in your data
structure?&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;This is a collection of little Rust thoughts that weren&amp;rsquo;t complicated
enough for a full post. I saved them up until I had a few, and now I&amp;rsquo;m
posting the collection. I plan on continuing to do this again for
such little thoughts, thus the #1 in the title.&lt;/p&gt;
&lt;h1 id=&#34;serde-flattening&#34;&gt;&lt;code&gt;serde&lt;/code&gt; flattening&lt;/h1&gt;
&lt;p&gt;What if you want to read a JSON file, process some of the fields, and
write it back out, without changing the other fields? Can you still use
&lt;code&gt;serde&lt;/code&gt;? Won&amp;rsquo;t it only keep fields that you know about in your data
structure?&lt;/p&gt;
&lt;p&gt;Turns out, you can parse the fields you want, while also just
preserving the fields you don&amp;rsquo;t!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[derive(Serialize, Deserialize)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; known_field: &lt;span style=&#34;color:#a6e22e&#34;&gt;KnownField&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; known_field2: &lt;span style=&#34;color:#a6e22e&#34;&gt;KnownField2&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#[serde(flatten)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; unknown_fields: &lt;span style=&#34;color:#a6e22e&#34;&gt;BTreeMap&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, serde_json::Value&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I found out about this &lt;a href=&#34;https://serde.rs/attr-flatten.html#capture-additional-fields&#34;&gt;in the &lt;code&gt;serde&lt;/code&gt;
documentation&lt;/a&gt;,
so it&amp;rsquo;s not an original insight, but it came in handy for me recently
and so I&amp;rsquo;m trying to raise awareness:&lt;/p&gt;
&lt;h1 id=&#34;let-surprises&#34;&gt;&lt;code&gt;let&lt;/code&gt; surprises!&lt;/h1&gt;
&lt;p&gt;So, in Jon Gjengset&amp;rsquo;s popular Twitter thread &lt;a href=&#34;https://www.thecodedmessage.com/posts/trivia-rust-types/&#34;&gt;transcribed
here&lt;/a&gt;, he wrote this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Did you know that whether or not &lt;code&gt;let _ = x&lt;/code&gt; should move &lt;code&gt;x&lt;/code&gt; is actually
fairly subtle?
&lt;a href=&#34;https://github.com/rust-lang/rust/issues/10488&#34;&gt;https://github.com/rust-lang/rust/issues/10488&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I didn&amp;rsquo;t think much of this, besides making a note to self not to use
&lt;code&gt;let _ = x&lt;/code&gt; to ever drop anything, which hopefully I wouldn&amp;rsquo;t have done
anyway because &lt;code&gt;drop(x)&lt;/code&gt; is much more self-evident in what it intends.
I remember also vaguely hoping that it did drop, because in my mind that
was the obvious, logical thing for it to do.&lt;/p&gt;
&lt;p&gt;But then later, as I was writing a &lt;code&gt;match&lt;/code&gt;, I realized why &lt;code&gt;_&lt;/code&gt; couldn&amp;rsquo;t
mean drop, from the match context:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;match&lt;/span&gt; foo.bar.baz {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    MyEnum::Option1(_) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// This shouldn&amp;#39;t move from `foo.bar.baz`, but just
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// inspects whether it is `MyEnum::Option1`. Otherwise, there&amp;#39;d
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// be no straight-forward way to perform that inspection!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// And indeed, it doesn&amp;#39;t.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        None
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    MyEnum::Option2(&lt;span style=&#34;color:#66d9ef&#34;&gt;ref&lt;/span&gt; baz_inner) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Some(foobar(baz_inner))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, if &lt;code&gt;let _ = x&lt;/code&gt; was to be consistent with this use case, well,
that meant that &lt;code&gt;_&lt;/code&gt; has to not drop, as it&amp;rsquo;s important for &lt;code&gt;_&lt;/code&gt; to
mean the same thing. And, after all, the left-hand side of a &lt;code&gt;let&lt;/code&gt;
is just another pattern context!&lt;/p&gt;
&lt;p&gt;But wait, I thought!  Does this mean that you can write &lt;code&gt;let ref x = y;&lt;/code&gt;? Yes, it does. It&amp;rsquo;s just another way of writing &lt;code&gt;let x = &amp;amp;y;&lt;/code&gt;&amp;hellip;
But just because you can write it that way, doesn&amp;rsquo;t mean you should.
Keeping to idiom is important.&lt;/p&gt;
&lt;p&gt;Nevertheless, fun fact! The more you know!&lt;/p&gt;
&lt;h1 id=&#34;remember-serde-structs-can-be-function-local&#34;&gt;Remember: &lt;code&gt;serde&lt;/code&gt; &lt;code&gt;struct&lt;/code&gt;s Can Be Function-Local&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s say you need to extract three fields out of some JSON, like
&lt;code&gt;name&lt;/code&gt;, &lt;code&gt;age&lt;/code&gt;, and &lt;code&gt;phone_number&lt;/code&gt; (which, ironically, is a string in
JSON terms, and not a number). One of the great things about Rust
and &lt;code&gt;serde&lt;/code&gt; is that you can just write those fields in a &lt;code&gt;struct&lt;/code&gt;
with the &lt;code&gt;Deserialize&lt;/code&gt; trait (which is deriveable)
and grab the values into such a struct, even if there&amp;rsquo;s
other actual fields in the JSON:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[derive(Deserialize)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Person&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name: String,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    phone_number: String,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    age: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; person: &lt;span style=&#34;color:#a6e22e&#34;&gt;Person&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; serde_json::from_str(json_str);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The question then becomes, where should &lt;code&gt;Person&lt;/code&gt; go? Well, if you
plan on passing around this &lt;code&gt;Person&lt;/code&gt; value, and structuring the rest
of your code in terms of it, then it should be a prominent type.&lt;/p&gt;
&lt;p&gt;But more often, especially in my own code, I immediately split such
a structure into its constituent parts, which I then will use for
other things:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; Person {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    name,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    phone_number,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    age,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; serde_json::from_str(json_str);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; person_database.lookup(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;name)&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;handle.set_phone_number(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;phone_number);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; demographic &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; demographic_for_age(age.trunc() &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is very reasonable. It makes sense that our internal data
structures would be designed for whatever logic we want to do on
them, rather than having them coincidentally match the wire format.
For most complicated applications, having the internal data
format match the wire format literally is actually sort of a code
smell.&lt;/p&gt;
&lt;p&gt;So, we often will have types that we use to deserialize (and serialize)
JSON in exactly one function. In that situation, the type should in
fact be written locally to that function. So in the example above,
where &lt;code&gt;struct Person { ... }&lt;/code&gt; is immediately followed by the
&lt;code&gt;serde_json::from_str&lt;/code&gt;, I didn&amp;rsquo;t just write them next to each
other as convenience. I would literally put them together in
a function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;do_thing&lt;/span&gt;(json_str: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;) -&amp;gt; Result&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    do_something_else()&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#[derive(Deserialize)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Person&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        name: String,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        phone_number: String,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        age: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; Person {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        name,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        phone_number,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        age,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; serde_json::from_str(json_str);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; person_database.lookup(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;name)&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    handle.set_phone_number(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;phone_number);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; demographic &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; demographic_for_age(age.trunc() &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I bring this up mostly because many programmers don&amp;rsquo;t seem to be
aware that you can do this, or don&amp;rsquo;t think to. I&amp;rsquo;ve seen people write
types like &lt;code&gt;Person&lt;/code&gt; at the top level. I realize that many programming
languages either don&amp;rsquo;t let you do this sort of embedding, or else strongly
discourage it. But I&amp;rsquo;m a big believer in giving things the least scope
they need, and for many &lt;code&gt;serde&lt;/code&gt;-related types, that&amp;rsquo;s function scope.&lt;/p&gt;
&lt;h1 id=&#34;rust-shadowing&#34;&gt;Rust Shadowing&lt;/h1&gt;
&lt;p&gt;Speaking of minimal scope, I wanted to write in praise of Rust&amp;rsquo;s penchant
for shadowing that allows you to not have to come up with a bunch of names
for the same thing. Oftentimes, we just convert the same information
from type to type: wire format in bytes, to parsed wire format, to
application domain format (wrapped in an &lt;code&gt;Option&lt;/code&gt; in a &lt;code&gt;Result&lt;/code&gt;), to
application domain format with errors and absence handled (not wrapped
in those things&amp;hellip; Fortunately, Rust lets us shadow and re-use names
for these different variables, and ultimately we get code that looks
something like this (although no type annotations are normally necessary):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; foo: &lt;span style=&#34;color:#a6e22e&#34;&gt;FooTypeC&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; foo: &lt;span style=&#34;color:#a6e22e&#34;&gt;FooTypeA&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; get_foo();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; foo: &lt;span style=&#34;color:#a6e22e&#34;&gt;FooTypeB&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; transform_foo(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;foo)&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;match&lt;/span&gt; foo {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Some(foo) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; transform_foo_again(foo)&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        None &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; FooTypeC::default(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is really helpful, along with the fact that braces &lt;code&gt;{&lt;/code&gt; &amp;hellip; &lt;code&gt;}&lt;/code&gt;
enclose expressions, in really minimizing how much scope each variable
has. But it&amp;rsquo;s also really helpful, because if shadowing wasn&amp;rsquo;t available,
what would we name all these different variables? &lt;code&gt;foo_a&lt;/code&gt; and &lt;code&gt;foo_b&lt;/code&gt;
and similar stupid names? This is an issue in certain other programming
languages where shadowing isn&amp;rsquo;t as straight-forward, and the &lt;a href=&#34;https://www.thecodedmessage.com/posts/hungarian/&#34;&gt;results
aren&amp;rsquo;t fun&lt;/a&gt;.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>The Importance of Logging</title>
      <link href="https://www.thecodedmessage.com/posts/logging/" />
      <id>https://www.thecodedmessage.com/posts/logging/</id>
      <updated>2023-03-21T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Intro programming classes will nag you to do all sorts of
programming chores: make sure your code actually compiles,
write unit tests, write comments, split the code into functions
(though sometimes the commenting and factoring advice is
&lt;a href=&#34;https://www.hillelwayne.com/post/what-comments/&#34;&gt;bad&lt;/a&gt;).  Today, however,
I want to talk about one little chore, one particular little habit, that
is just as essential as all of those things, but rarely covered in the
CS100 lectures or grading rubrics: logging.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Intro programming classes will nag you to do all sorts of
programming chores: make sure your code actually compiles,
write unit tests, write comments, split the code into functions
(though sometimes the commenting and factoring advice is
&lt;a href=&#34;https://www.hillelwayne.com/post/what-comments/&#34;&gt;bad&lt;/a&gt;).  Today, however,
I want to talk about one little chore, one particular little habit, that
is just as essential as all of those things, but rarely covered in the
CS100 lectures or grading rubrics: logging.&lt;/p&gt;
&lt;p&gt;And why am I choosing this particular topic for a blog post today?
Simple: It&amp;rsquo;s to punish an earlier version of myself for not logging
enough, for not caring about logging enough. It turns out it&amp;rsquo;s important.
But I&amp;rsquo;ll get back to the OOP blog series soon enough, don&amp;rsquo;t worry!&lt;/p&gt;
&lt;p&gt;Logging &amp;ndash; writing text describing what&amp;rsquo;s been happening in your program
to a file or other storage system &amp;ndash; is essential for any software
system. Luckily, Rust has a (nearly) standard logging framework,
technically outside the standard library but maintained by many of
the same people and solidly endorsed by the community: &lt;a href=&#34;https://docs.rs/log/latest/log/&#34;&gt;the &lt;code&gt;log&lt;/code&gt;
crate&lt;/a&gt;. But note: Even though this post
is written specifically for Rustaceans, much of the advice and commentary
in here will apply to logging systems in all programming languages.&lt;/p&gt;
&lt;p&gt;Logging is essential for debugging and troubleshooting. When you
find a bug, you need to find out which specific part of the program is
actually broken out of the many parts, because it&amp;rsquo;s often not the part
that&amp;rsquo;s visbly acting weird. This is often the first step in addressing a
new bug after &lt;a href=&#34;https://www.thecodedmessage.com/posts/reproducibility/&#34;&gt;reproducing it&lt;/a&gt;, or even part of
figuring out how to reproduce it &amp;ndash; or the step before that, so
obvious it goes without saying, of noticing that a bug exists.&lt;/p&gt;
&lt;p&gt;In fact, logs can be helpful at every stage of the debugging process.
You have to confirm your assumptions on what parts are known to
work. After all, the whole program is supposed to work, and often times,
the thing that&amp;rsquo;s broken is something that you would&amp;rsquo;ve assumed definitely
worked, until absolutely everything else was ruled out.&lt;/p&gt;
&lt;p&gt;Every programmer understands this intuitively, even as a student or a
beginning self-taught programmer: When you are developing a project, and
it&amp;rsquo;s not working, the easiest &lt;em&gt;ad hoc&lt;/em&gt; debugging technique is &amp;ldquo;debug print
statements,&amp;rdquo; a go-to technique of CS100 students worldwide. Ironically,
CS100 professors often advocate against this in favor of debuggers, in
spite of the fact that logging, the grown-up version of debug prints,
is more generally useful, as code often exhibits bugs in environments
where it didn&amp;rsquo;t happen to be running in a debugger, like production.&lt;/p&gt;
&lt;p&gt;Debug prints work, by accomplishing two goals:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Verifying that the program got to the point of that debug print line.&lt;/li&gt;
&lt;li&gt;Verifying that the data it has at that point is correct.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Logging is fundamentally debug print statements, but phrased and
annotated correctly, so that it looks professional both in the code
and in the log, and uses actual logging mechanisms with
timestamps and log levels and stuff.&lt;/p&gt;
&lt;p&gt;So instead of:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;initialize_rainbows();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Got here 2&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;initialize_sunshine();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;println(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Got here!!!!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You write the much nicer-looking:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;initialize_rainbows();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;info!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Rainbows fully initialized&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;initialize_sunshine();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;info!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Sunshine fully initialized&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;when-to-log&#34;&gt;When To Log&lt;/h1&gt;
&lt;p&gt;You should log as much as possible.&lt;/p&gt;
&lt;p&gt;Every time you make a decision, you should log it. Every time you query
a URL or build a string of some kind, you should log it. Every time
you load a config parameter, you should definitely log it. This might
seem silly, because you&amp;rsquo;re duplicating the configuration file, but
a bug processing configuration (or prioritizing different sources of
configuration) can be especially hard to find.&lt;/p&gt;
&lt;p&gt;Logging can be used instead of comments to organize functions into
parts. If you feel the need to tell the reader of your code
what each part of a function does, perhaps you should tell your
poor ops person which parts you&amp;rsquo;ve reached in the same breath.
So instead of:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;close_out_section&lt;/span&gt;(self) -&amp;gt; Result&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Flush dirty data
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; datum &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self.data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; datum.is_dirty() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            datum.flush()&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Close files
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; file &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self.files {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        file.flush()&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        file.close();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    decrease_global_section_count()&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ok(())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You could write:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;close_out_section&lt;/span&gt;(self) -&amp;gt; Result&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;info!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Closing out section: {}&amp;#34;&lt;/span&gt;, self.name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;debug!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Flushing dirty data&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; datum &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self.data {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; datum.is_dirty() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#a6e22e&#34;&gt;trace!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;{} is dirty, flushing...&amp;#34;&lt;/span&gt;, datum.name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            datum.flush()&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;debug!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Closing files&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; file &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self.files {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;trace!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Closing {}&amp;#34;&lt;/span&gt;, file.name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        file.flush()&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        file.close();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;debug!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Decreasing global section count&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    decrease_global_section_count()&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;debug!&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Section successfully closed!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ok(())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These log statements serve both as comments to your reader and information
to your administrator at the same time! And, since you are writing to
someone who is perhaps not looking at the source code, you don&amp;rsquo;t feel
silly adding even more information that&amp;rsquo;d be obvious to a reader &amp;ndash;
which is useful also to readers of the source code, who might not share
your definition of what is obvious. In spite of what you may have heard,
it&amp;rsquo;s still a good idea to err on the side of explaining things more
&lt;a href=&#34;https://www.hillelwayne.com/post/what-comments/&#34;&gt;in comments&lt;/a&gt;. (Yes,
I linked that post twice. It&amp;rsquo;s that good.)&lt;/p&gt;
&lt;p&gt;You may object that all this logging might slow down your process a
little, and I can see wanting to avoid it in the middle of a computational
loop. But oftentimes, people avoid logging when there is no possible
performance excuse, when much slower I/O is happening all around it,
in comparison to which the logging would be a rounding error. Remember
that famous Donald Knuth quote: &amp;ldquo;[P]remature optimization is the root
of all evil&amp;hellip;.&amp;rdquo;&lt;/p&gt;
&lt;h1 id=&#34;log-levels&#34;&gt;Log Levels&lt;/h1&gt;
&lt;p&gt;In addition to performance, you might claim that the amount of logging
that I show above is spammy, and that the resulting log files would
cause an information overload.
But our programming foreparents were wise, and created an additional
tool to address both this, and the potential performance problems: log
levels.&lt;/p&gt;
&lt;p&gt;An error message is different from a warning is different from information
is different from debug printing. We want to distinguish these, so we can
avoid seeing insufficiently important logs. There are many systems of log
levels, and Rust&amp;rsquo;s &lt;code&gt;log&lt;/code&gt; crate endorses a pretty typical list, enumerated
in its &lt;a href=&#34;https://docs.rs/log/latest/log/enum.Level.html&#34;&gt;&lt;code&gt;Level&lt;/code&gt; enum&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Level&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Error,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Warn,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Info,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Debug,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Trace,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;They form an ordered, descending scale of severity, so that &lt;code&gt;Trace&lt;/code&gt; is
the least severe. You probably always want to enable &lt;code&gt;Error&lt;/code&gt;-level logs
(though even they can be turned off) but you probably only want to enable
&lt;code&gt;Trace&lt;/code&gt;-level logs if you&amp;rsquo;re doing some serious debugging.&lt;/p&gt;
&lt;p&gt;In recognition of how the levels are ordered, log filtering is typically
done by setting a level, and then logs of that level or more severe
are let through. So if the level is &lt;code&gt;Debug&lt;/code&gt;, &lt;code&gt;Warn&lt;/code&gt; logs are also outputted,
but if it is &lt;code&gt;Error&lt;/code&gt;, &lt;code&gt;Warn&lt;/code&gt; logs are suppressed. See the &lt;a href=&#34;https://docs.rs/log/latest/log/enum.LevelFilter.html&#34;&gt;&lt;code&gt;LevelFilter&lt;/code&gt;
enum&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Errors are for problems that stop the process, or at least the specific
thing the process was doing (e.g. API or RPC request being serviced).
Warnings are for where something seems wrong but we&amp;rsquo;re going to do it
anyway.&lt;/p&gt;
&lt;p&gt;Info, debug, and trace are honestly kind of just labels with decreasingly
urgent-sounding names, levels for the sake of levels. You should
use them according to importance, so that most of the absolute nonsense
can get filtered out as mere &lt;code&gt;trace&lt;/code&gt;, like implementation details
or extra information. You also want the occasional interesting
high-level stuff to be captured with &lt;code&gt;info&lt;/code&gt;, like what high-level task
is the process currently working on. Medium-level tasks can get &lt;code&gt;debug&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In general, the more performance-critical the code, the lower the log
level you want to use, to increase the likelihood that you&amp;rsquo;ll just
have a (very predictable) branch to indicate that you don&amp;rsquo;t need to
print that line. Then, if there&amp;rsquo;s an actual problem, an operator can
raise the log level (which they can sometimes do on a per-module basis)
when those lines are worth seeing.&lt;/p&gt;
&lt;p&gt;As a corrollary, configuration should use &lt;code&gt;info&lt;/code&gt; and &lt;code&gt;warn&lt;/code&gt; heavily, and
generally log at higher log levels. Configuration only happens once,
and in one section, so it&amp;rsquo;s allowed to be spammy. Furthermore, raising
the log level at run-time won&amp;rsquo;t help reveal more configuration logs:
unless the configuration is re-processed, you&amp;rsquo;ve just already missed
those messages. Finally, configuration is never too latency sensitive
for logging &amp;ndash; configuration is the least performance sensitive part
of your program.&lt;/p&gt;
&lt;p&gt;So there is no excuse. Loading different configuration than you thought
you had is a shockingly common cause of bugs and confusing system
behavior. Log obsessively in your configuration code, at high log levels.&lt;/p&gt;
&lt;h1 id=&#34;using-the-log-crate-in-your-rust-projects&#34;&gt;Using the Log Crate in Your Rust Projects&lt;/h1&gt;
&lt;p&gt;So how do we log in Rust?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;log&lt;/code&gt; is a framework &amp;ndash; in the words of its well-written
&lt;a href=&#34;https://docs.rs/log/latest/log/&#34;&gt;documentation&lt;/a&gt;, it is a &amp;ldquo;lightweight
logging facade.&amp;rdquo; The front-end is shared: You output logs through the
&lt;code&gt;log&lt;/code&gt; crate itself. The backend is pluggable, meaning that different
backends exist with different features.&lt;/p&gt;
&lt;p&gt;As a result, as the documentation says, libraries should
just use the &lt;code&gt;log&lt;/code&gt; crate, so that when they output logs,
it will work with any backend. Applications choose the
backends, and import an appropriate crate, like for example
&lt;a href=&#34;https://docs.rs/env_logger/latest/env_logger/index.html&#34;&gt;&lt;code&gt;env_logger&lt;/code&gt;&lt;/a&gt;.
The &lt;code&gt;log&lt;/code&gt; documentation has a &lt;a href=&#34;https://docs.rs/log/latest/log/#available-logging-implementations&#34;&gt;list of available backend
crates&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This split between what crates should be used by libraries as opposed
to application is not uncommon in Rust. For example, it also comes up
with error handling, where libraries should generally use &lt;code&gt;thiserror&lt;/code&gt; to
preserve error information in a way that applications can programmatically
investigate, but applications generally want to use &lt;code&gt;anyhow&lt;/code&gt; and &lt;code&gt;eyre&lt;/code&gt;
to ergonomically convey any errors they cannot handle to the user.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Write Everything Down (Part 4): My Desktop Environment</title>
      <link href="https://www.thecodedmessage.com/posts/org4-desktop/" />
      <id>https://www.thecodedmessage.com/posts/org4-desktop/</id>
      <updated>2023-02-28T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I&amp;rsquo;d like to share with you how I use my computer, in a way that is
(for me) &lt;a href=&#34;https://www.thecodedmessage.com/tags/adhd/&#34;&gt;ADHD&lt;/a&gt; friendly and well-suited for implementing
my &lt;a href=&#34;https://www.thecodedmessage.com/posts/my-organization-system/&#34;&gt;organization system&lt;/a&gt;.  Tools are
important to any organizational and productivity system, and optimizing
your tools for your brain and your workflow are important.  My computer
is my most important productivity tool, where my work happens, and where
my life/chore/errand/calendar organization happens, so it should be an
interesting example of an optimized key tool.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I&amp;rsquo;d like to share with you how I use my computer, in a way that is
(for me) &lt;a href=&#34;https://www.thecodedmessage.com/tags/adhd/&#34;&gt;ADHD&lt;/a&gt; friendly and well-suited for implementing
my &lt;a href=&#34;https://www.thecodedmessage.com/posts/my-organization-system/&#34;&gt;organization system&lt;/a&gt;.  Tools are
important to any organizational and productivity system, and optimizing
your tools for your brain and your workflow are important.  My computer
is my most important productivity tool, where my work happens, and where
my life/chore/errand/calendar organization happens, so it should be an
interesting example of an optimized key tool.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I consider this a non-technical post, as it is intended for
a general audience. Even though it is about a computer set-up that
I&amp;rsquo;m not recommending to a non-technical audience, this &lt;em&gt;description&lt;/em&gt;
and &lt;em&gt;explanation&lt;/em&gt; of my computer set-up should be accessible enough for
everybody. However, it is also literally about computers, so it&amp;rsquo;s going
in the &amp;ldquo;Computers/Programming Posts&amp;rdquo; bucket as well &amp;ndash; and therefore it
will show up under both feeds.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&amp;rsquo;s been some time since I&amp;rsquo;ve written about
&lt;a href=&#34;https://www.thecodedmessage.com/tags/organization&#34;&gt;organization&lt;/a&gt; &amp;ndash; I had basically paused the series
until further inspiration struck. I had even outlined this very post,
and considered writing in more detail about my personal computer usage,
how my desktop actually looks, and the actual techniques I use to get
this machine to work for me for programming, blogging, and planning. The
reason I didn&amp;rsquo;t was basically because I didn&amp;rsquo;t think it would be
interesting enough.&lt;/p&gt;
&lt;p&gt;But inspiration did finally strike, in the form of two things that
changed my mind and convinced me that there was an audience for this
post, two things that happened very close together in time:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;I learned that huge numbers of people were excited to hear about how
&lt;a href=&#34;https://www.cgpgrey.com/&#34;&gt;somebody&lt;/a&gt; had optimized their arrangement
of iPhone app icons on the &lt;a href=&#34;https://www.relay.fm/cortex&#34;&gt;Cortex&lt;/a&gt;
podcast. This was a completely standard iPhone, running unmodified,
not-even-jailbroken iOS &amp;ndash; perhaps the least customizable, least
interesting consumer operating system out there. If huge numbers of
people were interested in how icons are arranged on iOS, and how that
can be optimized for productivity and to match someone&amp;rsquo;s brain, people
will definitely be interested in how I use my computers, which do not
even use a normal user interface for Linux and are extremely customized
to how I think.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Several friends of mine in rapid succession thought that my
computer interface was worthy of comment to me or to others as
a way of characterizing me. One friend even said, when I showed her
how a few &lt;code&gt;vim&lt;/code&gt; commands worked, that she understood why I used this
for my organization files.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So I&amp;rsquo;ll start by taking a screenshot of how my desktop looks right now,
literally as I write this, to use as a conversational starting point:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/desktop-screenshot.png&#34; alt=&#34;Desktop Screenshot&#34;&gt;&lt;/p&gt;
&lt;p&gt;I know I&amp;rsquo;ve shown some screenshots in my &lt;a href=&#34;https://www.thecodedmessage.com/posts/my-organization-system/&#34;&gt;last
post&lt;/a&gt;, but this time we&amp;rsquo;re going
to discuss it in some more detail.&lt;/p&gt;
&lt;p&gt;It looks very &amp;hellip; computer-y. Very low-level. Very much as if I&amp;rsquo;m
doing programming, even though I&amp;rsquo;m actually doing blogging.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not just the presence of the terminal, either, though just using
a command line is considered to be advanced or even programmer-level
computer usage these days. It&amp;rsquo;s the whole aesthetic. There&amp;rsquo;s no &lt;a href=&#34;https://en.wikipedia.org/wiki/Window_%28computing%29#Window_decoration&#34;&gt;window
decorations&lt;/a&gt;
on either the left side of the screen where I&amp;rsquo;m editing my post, nor on
the right side of the screen where I&amp;rsquo;m having a command line session &amp;ndash;
that is to say, no title bar, no minimize-maximize-close icons, no menu
bars. Clearly, if I want to save the file I&amp;rsquo;m working on, I can&amp;rsquo;t go up
to the menu and click &lt;code&gt;File -&amp;gt; Save&lt;/code&gt;. And, actually, there don&amp;rsquo;t seem
to be any places designed for clicking at all.&lt;/p&gt;
&lt;p&gt;Along the top, instead of a start menu or a system menu or a dock of
application launchers, I have a bunch of status information, formatted in
such a way so that you have to know what you&amp;rsquo;re reading to understand it:
one number highlighted out of several; the word &lt;code&gt;Tall&lt;/code&gt;; &lt;code&gt;jim@palatinate: ~/Writing/TheCodedMessage/conte...&lt;/code&gt;, which is the same text as my prompt
in the terminal, and indicates who I am, what computer I&amp;rsquo;m logged into,
and what directory I&amp;rsquo;m currently in (in the currently highlighted
terminal). Then, what WiFi I&amp;rsquo;m connected to, my CPU percentage, memory
usage, date and time, and battery status.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s not a single icon among these status indicators &amp;ndash; it&amp;rsquo;s just a
long line of text. Text, that goes well with the text of the blog post
I&amp;rsquo;m editing and the text of the command line. I can see why sometimes
friends refer to my computer interface as &amp;ldquo;not logged into a graphical
environment&amp;rdquo; or &amp;ldquo;in text mode&amp;rdquo; or &amp;ldquo;in command line only mode&amp;rdquo; &amp;ndash; even
though that is actually a thing, and is literally not the situation my
computer is in.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a modern graphical login session! Here&amp;rsquo;s me using a web browser if
you don&amp;rsquo;t believe me (Chromium is off-brand Chrome, made from the
same source code):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/web.png&#34; alt=&#34;Web Browser Screenshot&#34;&gt;&lt;/p&gt;
&lt;p&gt;And of course, I can also view videos with &lt;a href=&#34;https://www.videolan.org/&#34;&gt;VLC&lt;/a&gt;
or look at pictures with &lt;a href=&#34;https://help.gnome.org/users/eog/stable/&#34;&gt;Eye of
GNOME&lt;/a&gt; (yes, I can use GNOME
components even though I don&amp;rsquo;t use the GNOME desktop environment), and
in literal text mode, that wouldn&amp;rsquo;t be possible.&lt;/p&gt;
&lt;p&gt;But I understand why people call my set-up text mode, and now that I&amp;rsquo;m
paying attention, I see that in a very literal sense, there aren&amp;rsquo;t any
images or icons at all on my screen right now, just text in various
colors. That is an intentional choice, and how I like it, and it
does have to do with me being a programmer (in at least being aware
of my options and capable of configuring it), so fair.&lt;/p&gt;
&lt;p&gt;So what is going on? Why does my computer look so text-y, even if
it&amp;rsquo;s not technically text-mode?&lt;/p&gt;
&lt;h1 id=&#34;xmonad&#34;&gt;xmonad&lt;/h1&gt;
&lt;p&gt;To be clear, my set-up is not typical of how Linux computers
normally look. On Linux, you get your choice of desktop
interface, of what software draws things like window borders
and docks and start menus. Usually, people use ones like
&lt;a href=&#34;https://www.gnome.org/&#34;&gt;GNOME&lt;/a&gt; or &lt;a href=&#34;https://kde.org/&#34;&gt;KDE&lt;/a&gt; (or
dozens of others), which look much more like macOS or Windows,
with a normal amount of icons, and sometimes even futuristic,
overly dynamic graphics. Here&amp;rsquo;s a screenshot of KDE from &lt;a href=&#34;https://commons.wikimedia.org/wiki/File:Screenshot_of_KDE_4.3.png&#34;&gt;Wikimedia
Commons&lt;/a&gt;
to demonstrate:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/kde.png&#34; alt=&#34;KDE&#34;&gt;&lt;/p&gt;
&lt;p&gt;But I instead chose &lt;a href=&#34;https://xmonad.org/&#34;&gt;xmonad&lt;/a&gt;, which is designed
for things like minimalism, deep configurability, and keyboard control
&amp;ndash; and in general designed almost exactly for my priorities. My XMonad
set-up is not that weird, for an XMonad set-up. Like any XMonad set-up,
however, it is deeply customized to my particular workflow.&lt;/p&gt;
&lt;p&gt;But before we get into my customizations and use of it, I&amp;rsquo;d like to talk
a bit about why I prefer XMonad to other, more traditional desktop
environments. It&amp;rsquo;s not to be weird or to show off my technical skills or
even to communicate that I&amp;rsquo;m a programmer and a nerd &amp;ndash; I actually don&amp;rsquo;t
very much like that people think I&amp;rsquo;m programming when I&amp;rsquo;m actually working
on a writing project, nor do I like that other people find borrowing my
laptop intimidating. Instead, it&amp;rsquo;s about adapting to what I feel comfortable
with, and what works well with how my brain works.&lt;/p&gt;
&lt;p&gt;So the lack of distractions, the lack of icons, is actually very important
to helping me focus, as is the simplicity of the interface. My ADHD
doesn&amp;rsquo;t manifest by having my eyes be regularly pulled away to where
the icons are because they&amp;rsquo;re pretty &amp;ndash; or at least, if it does I&amp;rsquo;m not
aware of it. But if there is a dock of icons on the screen, my awareness
that the dock is there can be a distraction to me, taking up precious
space in my brain of very limited short-term memory that could be better
served juggling the other things going on in the computer. This distraction
even happens on macOS, even when the dock is hidden &amp;ndash; I have to be aware
of it so I know &lt;em&gt;not&lt;/em&gt; to move my mouse to the bottom of the screen, or that
if I do, I will suddenly see icons.&lt;/p&gt;
&lt;p&gt;The title bars that typically line the top of windows are such a
distraction, as are the menu bars (with &lt;code&gt;File&lt;/code&gt;, &lt;code&gt;Edit&lt;/code&gt;, etc.) that
give you a list of things to do. If I were designing an operating
system UI from scratch &amp;ndash; which I have often fantasized about &amp;ndash;
the menu would show up as an overlay on top of the window when you
pressed the &lt;code&gt;[ALT]&lt;/code&gt; key, and a list of available keyboard shortcuts
would show up when you pressed and released &lt;code&gt;[CTRL]&lt;/code&gt;, reminding
you that paste, for example, is &lt;code&gt;Ctrl-V&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Back in real life, I also don&amp;rsquo;t have menu bars on my machine for my most
commonly used apps.  But the replacement, unfortunately, isn&amp;rsquo;t an overlay,
but simply knowing the relevant commands for both &lt;code&gt;gvim&lt;/code&gt; and terminal,
both literal commands, and keyboard and mouse gestures, like
&lt;code&gt;Ctrl-D&lt;/code&gt; to log out or middle-click to paste the last thing you
highlighted &amp;ndash; because I find &lt;code&gt;Ctrl-C&lt;/code&gt;/&lt;code&gt;Ctrl-V&lt;/code&gt; too tedious and
prefer copy-and-paste through the &amp;ldquo;secondary clipboard&amp;rdquo; Linux
supports: highlight and middle mouse click, or three fingers on
my laptop trackpad.&lt;/p&gt;
&lt;p&gt;The streamlined simplicity allows me to just see the text of the actual
app I&amp;rsquo;m using. It reminds me of math textbooks. I prefer math textbooks
that just are about math. I saw a math textbook for the high school level
once that was full of pictures of youths doing math, very visually
busy, lots of stuff going on. I thought to myself, I don&amp;rsquo;t know how
long I could read this book, not because I would jump from thing to
thing, but because I would try to extract the actual math out of it,
and filtering out the rest would be well-nigh impossible, and quite
fatiguing.&lt;/p&gt;
&lt;p&gt;Thus, xmonad lets me choose exactly what goes on the screen. Even
&lt;code&gt;xmobar&lt;/code&gt;, the system status bar across the top with all that status
information is optional &amp;ndash; you can make it so that it appears and
disappears based on a keyboard shortcut, or leave it out altogether. And
certainly, no panel of icons &amp;ndash; if I want to start a program, I have a
keyboard combination to start the terminal, another to start the browser,
and another to type in the name of a program I want to run (which I
could also do, of course, from the terminal). The iOS equivalent would
be to have one icon for Safari, and besides that to literally always use
search to find your app, with no icons visible and an empty home screen.&lt;/p&gt;
&lt;p&gt;One thing that I like about iOS, however, is also true of xmonad:
when you start a program it takes up the entire screen. For the life
of me, I don&amp;rsquo;t understand what I ever saw in having different windows
that could overlap on your desktop. What were you doing with the empty
space? Why was it so essential to be able to arrange the screen any way
with enough work? Isn&amp;rsquo;t it more important to be able to have the screen
in the configuration you want consistently?&lt;/p&gt;
&lt;p&gt;In macOS, if I want a window to be full screen, that&amp;rsquo;s easy enough &amp;ndash; but
it&amp;rsquo;s still not the default, even if it&amp;rsquo;s the only window. However, if I
want multiple windows to be tiled, then I have to do so many steps. The
cost of the flexibility of freely moving window arrangements around is
that the one I do want is harder.&lt;/p&gt;
&lt;p&gt;In xmonad, when I open a window, it takes up the whole screen. If I open
a second window, they split the screen. I can use key combinations to
adjust which one is on which side, or to switch from left-right tiling to
top-bottom tiling, or to move the dividing bar left or right, but most
of the time I can just immediately use it.&lt;/p&gt;
&lt;p&gt;I can also use a key combination (⌘-TAB &amp;ndash; it would be &lt;code&gt;ALT&lt;/code&gt;, but I
have ⌘ generally configured to replace &lt;code&gt;ALT&lt;/code&gt;) to switch which window is
focused, but I usually use the mouse for that. I have focus-follows-mouse
enabled, so I don&amp;rsquo;t actually have to click the mouse before I can start
typing in the newly-focused window.&lt;/p&gt;
&lt;p&gt;If I open a third window, then, it works perfectly how I like it:
arranged so I can see all three:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/three-windows.png&#34; alt=&#34;Three Windows&#34;&gt;&lt;/p&gt;
&lt;p&gt;More than three windows is similar to three &amp;ndash; but I don&amp;rsquo;t let that
happen normally. I stick to three windows per screen, or specifically,
per virtual desktop.&lt;/p&gt;
&lt;h1 id=&#34;virtual-desktops&#34;&gt;Virtual Desktops&lt;/h1&gt;
&lt;p&gt;Virtual desktops are a key component of how I use my computer.  macOS
has the feature as well, described by the less techie-sounding name of
&lt;a href=&#34;https://support.apple.com/guide/mac-help/work-in-multiple-spaces-mh14112/mac&#34;&gt;spaces&lt;/a&gt;
(and it appears that in that context, it&amp;rsquo;s also pretty easy to set up
split-screening, which is good news). Virtual desktops are like
having multiple full-screen windows that you switch between, except
that each virtual desktop can have multiple windows on it. In my
context, it means I never have more than three windows on a screen
at a time, but I have multiple sets of three windows that go together
that I can switch between, in my case indexed by number.&lt;/p&gt;
&lt;p&gt;If I want to go to virtual desktop 1, I press ⌘-1 (where ⌘ is the
command or logo key, a Windows™ logo on my keyboard even though I
bought this computer from Dell™ with Linux™ pre-installed). To go
to virtual desktop 3, I press ⌘-3. The currently available virtual
desktops are shown on my status bar, with the currently showing one
highlighted in yellow &amp;ndash; if they weren&amp;rsquo;t, I would probably have forgotten
about windows left in other virtual desktops when I first started using
them. In the screenshot above of three windows, you can see that I am
working in desktop 4.  There are also windows on desktops 1, 2, and 5,
but none on desktop 3, which is why there is no 3 shown. They go up to
9, or at least 9 that are accessible by that keyboard short-cut in my
current configuration.&lt;/p&gt;
&lt;p&gt;If I want to move a window from one virtual desktop to another, I just
need to type &lt;code&gt;⌘-Shift-N&lt;/code&gt; while hovering my mouse over the window, where &lt;code&gt;N&lt;/code&gt;
is the desktop I want to move it to. Sometimes, the windows come out
in the wrong arrangement on the new desktop, but I can use &lt;code&gt;⌘-Enter&lt;/code&gt;
to switch them.&lt;/p&gt;
&lt;p&gt;Virtual desktops are key to my workflow and my focus, because each one
corresponds to a mode of using my computer, a type of action. I can
switch between them, but while I&amp;rsquo;m within one, the only indication that
others are available is up in the status bar.&lt;/p&gt;
&lt;p&gt;I use specific virtual desktops for specific tasks on a permanent
basis. When I have not recently been doing the task, there might
be no windows in them, but when I want to do that task, I switch to
that virtual desktop and start windows there. This keeps information
about what is where in my long-term memory, as a fact about how my
system works, rather than in my prospective memory, which &lt;a href=&#34;https://www.thecodedmessage.com/posts/write-everything-down&#34;&gt;as I&amp;rsquo;ve
discussed&lt;/a&gt; is far more problematic.&lt;/p&gt;
&lt;p&gt;To be specific, this is what I use each virtual desktop for:&lt;/p&gt;
&lt;h2 id=&#34;desktop-1-browsing&#34;&gt;Desktop 1: Browsing&lt;/h2&gt;
&lt;p&gt;Desktop 1 is a full-screen browser session. If you look at my &lt;a href=&#34;https://www.thecodedmessage.com/web.png&#34;&gt;web
screenshot&lt;/a&gt; (also displayed above), you see that I am on desktop 1.&lt;/p&gt;
&lt;p&gt;This is the only place I put a web browser window; you don&amp;rsquo;t need more
than one because of tabs. I will occasionally also move a terminal or
editor window to this desktop, if I need to type something into the
terminal directly from a web browser, or manually retype text based
off of what I&amp;rsquo;m reading there, but this is rare. Similarly, I will
occasionally split-screen two web browser windows for the same reason &amp;ndash;
but only for as long as I need to see both pages at once.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t use tabs as heavily as some people. I don&amp;rsquo;t relate to the ADHD
person with hundreds of tabs open. I generally have Slack, e-mail,
and then whatever exact thing I&amp;rsquo;m using the web browser for. If this
is programming, and I&amp;rsquo;m reading documentation or troubleshooting an
issue, that might be multiple tabs deep (e.g. of different but related
documentation, or of documentation and source). And occasionally I&amp;rsquo;ll
absent-mindedly find myself going on a tangent. But besides Slack,
and sometimes e-mail, I close the relevant tabs as soon as I&amp;rsquo;m done
doing the task &amp;ndash; tabs are transient.&lt;/p&gt;
&lt;p&gt;When I do read documentation from the web to write code, I do fully switch
desktop environments as I write the code vs reading the documentation.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t like that this is how I access my e-mail. I would prefer to
have it set up with a TUI-based system, while still syncing with the
GMail app on my phone. I know I can do that &amp;ndash; I&amp;rsquo;ve done it before &amp;ndash;
but I simply haven&amp;rsquo;t gotten around to it.&lt;/p&gt;
&lt;p&gt;One final note: To help me maintain focus, I do have a blacklist of
websites I don&amp;rsquo;t let myself go to, implemented through &lt;code&gt;/etc/hosts&lt;/code&gt;.
This doesn&amp;rsquo;t actually restrict me, because I can always go to those
websites on my &amp;ldquo;unproductive&amp;rdquo; computer (mostly for Netflix), or on my
phone. They do, however, prevent me from going off the rails and drifting
into a Reddit rabbit-hole when I&amp;rsquo;m supposed to be working. I can always
unblock a website if I (temporarily or permanently) do need to access
it from one of my primary computers.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the blacklist, all the domain names that my computer resolves
as referring to &lt;code&gt;localhost&lt;/code&gt;, my local computer, rather than the actual
IP address of my server. Here&amp;rsquo;s all the websites the browser will
therefore fail to connect to:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;127.0.0.1       facebook.com
127.0.0.1       www.facebook.com
127.0.0.1       quora.com
127.0.0.1       www.quora.com
127.0.0.1       twitter.com
127.0.0.1       www.twitter.com
127.0.0.1       news.google.com
127.0.0.1       etrade.com
127.0.0.1       us.etrade.com
127.0.0.1       www.etrade.com
127.0.0.1       reddit.com
127.0.0.1       www.reddit.com
127.0.0.1       news.ycombinator.com
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;desktop-2-coding-primary&#34;&gt;Desktop 2: Coding (Primary)&lt;/h2&gt;
&lt;p&gt;This is where I look at and edit files in the repo and project that I&amp;rsquo;m
currently working on. I have a terminal open to the project directory,
and normally two &lt;code&gt;gvim&lt;/code&gt; windows &amp;ndash; &lt;code&gt;gvim&lt;/code&gt; is my preferred text editor &amp;ndash;
open to files within that project. The large full-height space is for the
file I&amp;rsquo;m editing, the smaller space above the terminal for a file I&amp;rsquo;m
referring to, but within the same project. If I want to edit the other
file instead, I switch them so that &lt;code&gt;gvim&lt;/code&gt; window is the new tall one &amp;ndash;
there&amp;rsquo;s a keyboard shortcut for that.  The terminal stays on the right,
and in the case of multiple windows on the right, the terminal stays as
the lowest.&lt;/p&gt;
&lt;p&gt;I continuously open and close new &lt;code&gt;gvim&lt;/code&gt; windows, which is part of why
I use &lt;code&gt;gvim&lt;/code&gt; &amp;ndash; it loads fast enough for this to be a viable strategy.&lt;/p&gt;
&lt;h2 id=&#34;desktop-3-coding-secondary&#34;&gt;Desktop 3: Coding (Secondary)&lt;/h2&gt;
&lt;p&gt;Sometimes, when you&amp;rsquo;re working on a project, you need to know how
something&amp;rsquo;s done in a different project. Perhaps you need to know
an implementation detail of a function you&amp;rsquo;re calling, or maybe just
the interface. Perhaps you know the other project did the thing
you&amp;rsquo;re trying to do, and you need to see how they did it. Perhaps
you suddenly realized you can&amp;rsquo;t have X dependency, and now you need
to know if Y depends on X.&lt;/p&gt;
&lt;p&gt;Sometimes this is a different internal project, sometimes it&amp;rsquo;s an
open source project you need to download off GitHub. But it&amp;rsquo;s
a different repo, with a working copy in a different directory,
and that means that I have a different virtual desktop for it,
with a different terminal in that directory.&lt;/p&gt;
&lt;p&gt;There, I mostly do reading, but I can also do editing in a pinch.
For example, if I need to make a change that straddles two repos, the
application (for example) will often be in desktop 2 and the library in
desktop 3. If it straddles 3 repos, I either switch which repo desktop 3
is used for (it is only used for one at a time) or I spill over to
desktop 4 as a tertiary coding repo, as a non-standard use of that
desktop. I usually feel vaguely uncomfortable when I do that, though.&lt;/p&gt;
&lt;h2 id=&#34;desktop-4-blogging&#34;&gt;Desktop 4: Blogging&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;m on desktop 4 right now as I&amp;rsquo;m writing this, because that is the
desktop I use for blogging &amp;ndash; and most other forms of prose writing
(though specifically not documentation for work, which counts normally
as part of a coding project).&lt;/p&gt;
&lt;p&gt;I blog just as I program. I use &lt;code&gt;gvim&lt;/code&gt; to edit text files. I use a
terminal to open the right text files, list which text files are present,
keep &lt;code&gt;git&lt;/code&gt; up-to-date with what I&amp;rsquo;m working on, and build and deploy my
blog. In this case, by &amp;ldquo;build,&amp;rdquo; I mean translate it from a directory
full of &lt;a href=&#34;https://en.wikipedia.org/wiki/Markdown&#34;&gt;Markdown&lt;/a&gt; files
into a website, which I then upload to my server.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a screenshot of me editing the markdown for this post in the
left window, and trying and failing to run my build-and-upload script
in the other folder (which refused to upload as I hadn&amp;rsquo;t synchronized
my files with GitHub yet):&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/markdown.png&#34; alt=&#34;Markdown and Upload&#34;&gt;&lt;/p&gt;
&lt;p&gt;I prefer editing my blog as a bunch of plain text files on my computer.
It gives me a sense of control that I would not get if I installed
Wordpress on my server &amp;ndash; or used the official Wordpress. It allows
me to use &lt;code&gt;gvim&lt;/code&gt; to edit them as plain text, which I refer to
&lt;a href=&#34;https://en.wikipedia.org/wiki/WYSIWYG&#34;&gt;WYSIWYG&lt;/a&gt; editing.&lt;/p&gt;
&lt;p&gt;Generally, I&amp;rsquo;m only working on one file and so I have a terminal window
and single solitary &lt;code&gt;gvim&lt;/code&gt; window, rather than two or three &lt;code&gt;gvim&lt;/code&gt;
windows. It only makes sense to work on one file at a time in writing
normally, unlike in programming where there&amp;rsquo;s intricate mutual references.
Occasionally, for a blog series like this, I will open a previous
part of the blog series to see how much I&amp;rsquo;m repeating myself.&lt;/p&gt;
&lt;h2 id=&#34;desktop-5-organization&#34;&gt;Desktop 5: Organization&lt;/h2&gt;
&lt;p&gt;You might notice, however, that in none of the other desktops do I
describe having any of my organizational files open. I have detailed
organizational files, which I edit in &lt;code&gt;gvim&lt;/code&gt;, and discussed in detail
in the &lt;a href=&#34;https://www.thecodedmessage.com/posts/my-organizational-system/&#34;&gt;previous post&lt;/a&gt;. And as
you can see in the sample screenshot from that post (reposted here),
this organizational system lives entirely on desktop 5:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/org-screenshot.png&#34; alt=&#34;Org System&#34;&gt;&lt;/p&gt;
&lt;p&gt;I do not have the complete list of things I have to do hanging over me
while I&amp;rsquo;m doing each thing, only when I&amp;rsquo;m planning. Instead, when I
reach the end of whatever I&amp;rsquo;m working on &amp;ndash; or, as often happens, when
I find I&amp;rsquo;ve generated a new TODO item that I want to write down but not
yet fully switch my focus to &amp;ndash; then I switch to virtual desktop 5 to
interact with my TODO system. When I switch back, with a new task or
with the idea safely written down, I can then (more) fully focus on my
task without worrying about other ones.&lt;/p&gt;
&lt;h2 id=&#34;desktop-6-signal&#34;&gt;Desktop 6: Signal&lt;/h2&gt;
&lt;p&gt;When I run the desktop version of signal, which I do sometimes, it runs
on its own virtual desktop, namely desktop 6.&lt;/p&gt;
&lt;h2 id=&#34;desktop-7-long-running-processes&#34;&gt;Desktop 7: Long-running processes&lt;/h2&gt;
&lt;p&gt;This is where I put VPN sessions, if they&amp;rsquo;re tied to a terminal window.
It&amp;rsquo;s also where I put some very long-running builds or locally hosted
servers.&lt;/p&gt;
&lt;h1 id=&#34;editor-and-terminal&#34;&gt;Editor and Terminal&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve already discussed in a previous session how I use the web browser.
Occasionally, I use a variety of other random graphical programs: an image
viewer, a PDF viewer, or a &lt;a href=&#34;https://www.videolan.org/&#34;&gt;video player&lt;/a&gt;.
But most often, the two types of windows I have open besides the web
browser are &lt;code&gt;gvim&lt;/code&gt;, a text editor, and &lt;code&gt;alacritty&lt;/code&gt;, a terminal emulator.&lt;/p&gt;
&lt;p&gt;Both of these tools are primarily used by computer professionals of
some stripe, so it&amp;rsquo;s a little unfair of me to bristle when people
see them &amp;ndash; also without any icons on the screen &amp;ndash; and assume I
am a programmer. I do have specific reasons for using them for
non-programming tasks, that match my habits well, so I&amp;rsquo;d like
to discuss them further.&lt;/p&gt;
&lt;p&gt;Both of them are tools that require substantial investment
in skill. Obviously, to use a terminal, you have to know commands.
You can&amp;rsquo;t discover the interface like you can with a series of menus,
or settings pages, or icons. Similarly but less obviously, &lt;code&gt;gvim&lt;/code&gt;, like
any version of &lt;code&gt;vim&lt;/code&gt;, is close to useless to anyone who doesn&amp;rsquo;t know it.
Both of them require reading documentation in the form of a book (or
website) to explain to you what to do and at least get you started.&lt;/p&gt;
&lt;p&gt;But I did all of that investment years ago, as a youth, and it&amp;rsquo;s
been paying off ever since &amp;ndash; to the point where if I try to
edit text, or navigate file systems, without these tools, I feel
substantially hindered.&lt;/p&gt;
&lt;h2 id=&#34;vim&#34;&gt;Vim&lt;/h2&gt;
&lt;p&gt;I start with &lt;code&gt;gvim&lt;/code&gt; because it&amp;rsquo;s the more relevant to my organizational
particularities. It&amp;rsquo;s a text editor, which means that unlike something
like Google Docs or Microsoft Word, it edits plain text files, files
that just have sequences of characters organized into a sequence of
lines. Characters can include Unicode &amp;ndash; including accented letters,
Chinese characters and emojis &amp;ndash; but not styling like &lt;strong&gt;bold&lt;/strong&gt; and
&lt;em&gt;italics&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Text editors are important to programmers because programming is done
via collections of plain text files, and so text editors are universally
useful tools for handling all of them. Rather than each programming
language having its own special file format requiring its own special
editor, text files allow programmers to bring their preferred text editors
with them to a variety of projects, thus allowing a deeper investment
in the skill of using the text editor.&lt;/p&gt;
&lt;p&gt;Even this blog, which is not a programming project but a writing
project, is maintained using text files, using Markdown, a format which
interprets &lt;code&gt;*italics*&lt;/code&gt; as &lt;em&gt;italics&lt;/em&gt; and &lt;code&gt;**bold**&lt;/code&gt; as &lt;strong&gt;bold&lt;/strong&gt;, and Hugo,
a software package that converts a hierarchy of Markdown-formatted plain
text files appropriately into a website. And for Markdown, just as for
any programming language, I can choose any text editor I want to, and
it will be compatible.&lt;/p&gt;
&lt;p&gt;This choice, the choice of text editor, can be greatly personal to a
programmer. The rivalry between two major text editors from earlier
eras of Unix, &lt;code&gt;vi&lt;/code&gt; and &lt;code&gt;emacs&lt;/code&gt;, was often referred to as a &lt;a href=&#34;https://en.wikipedia.org/wiki/Editor_war&#34;&gt;holy
war&lt;/a&gt; for how intense the fights
about it would get on &lt;a href=&#34;https://en.wikipedia.org/wiki/Usenet&#34;&gt;Usenet&lt;/a&gt;
(an old discussion forum that ran on an &lt;a href=&#34;https://en.wikipedia.org/wiki/UUCP&#34;&gt;old pre-Internet
network&lt;/a&gt;). &lt;code&gt;gvim&lt;/code&gt;, which is the
text editor I use, is a form of &lt;code&gt;vim&lt;/code&gt;, which is a form of &lt;code&gt;vi&lt;/code&gt;, so
I have a definite position in that holy war. And I&amp;rsquo;m sure I&amp;rsquo;m going
to hear from people who disagree with my position in response to this
blog post!&lt;/p&gt;
&lt;p&gt;While my &lt;code&gt;gvim&lt;/code&gt; window looks like a terminal window &amp;ndash; and &lt;code&gt;vim&lt;/code&gt; can indeed run
inside of a terminal &amp;ndash; it&amp;rsquo;s actually a separate graphical application.
That is what the initial &lt;code&gt;g&lt;/code&gt; stands for, &amp;ldquo;graphical.&amp;rdquo;  When I edit a
file, I want a new window to be opened, and I also want to be able to use
the mouse to click on a location on the screen and move my cursor there.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vim&lt;/code&gt;, like many of the tools I use, is optimized for expert use, rather
than discoverability by beginners. It&amp;rsquo;s designed to be a skill to be
invested in: I put in the effort to learn how to use it a long time ago,
and it pays off over a lifetime. The commands I can make from my keyboard
are more powerful than most computer text editing facilities can support,
allowing me to with a few keystrokes perform complex manipulations of the
text.&lt;/p&gt;
&lt;p&gt;This is essential, in my mind, for efficient programming, which is
why I put the effort in to learn it. However, it is also particularly
well-suited to my organizational files, which, if you remember from my
&lt;a href=&#34;https://www.thecodedmessage.com/posts/my-organizational-system/&#34;&gt;previous post&lt;/a&gt;, consists of plain
text files with lots of highly-nested bulleted lists, like this
outline for this section of the post:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;* gvim
    * Text editor
        * Plain text and website generation
    * vim
        * But not terminal vim
        * Still has separate &amp;#34;window&amp;#34;
        * And can use mouse if necessary
    * Line-based editing good for organization
        * Commands work on lines
            * Delete
            * Paste last delete
            * Select multiple
            * Shift indentation level
        * Org-mode style use of hierarchical bullet points
            * Perfect match for those commands
            * No notes longer than a line
                * Make it more hierarchical instead
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When I edit plain text files in this format &amp;ndash; a custom habit inspired by
&lt;a href=&#34;https://orgmode.org/&#34;&gt;Org mode&lt;/a&gt; but still compatible with Markdown &amp;ndash;
it&amp;rsquo;s important for me to be able to operate on the scale of entire lines.
And operating on entire lines is one of &lt;code&gt;vim&lt;/code&gt;&amp;rsquo;s strongest points!
&lt;code&gt;dd&lt;/code&gt; to remove a line, &lt;code&gt;p&lt;/code&gt; to insert the line back in, and relevantly
for hierarchical bullet points, &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; and &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; to change indentation!
Using &lt;code&gt;V&lt;/code&gt;, I can select multiple lines, and then use &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, or &lt;code&gt;d&lt;/code&gt;
to change indentation or move them! Meanwhile, &lt;code&gt;j&lt;/code&gt;, and &lt;code&gt;k&lt;/code&gt;, right on the
home row, move down and up through the file, line by line, respectively.&lt;/p&gt;
&lt;p&gt;This equates to removing tasks (when they&amp;rsquo;re done or no longer wanted),
moving tasks between different places in the hierarchy (which I do shockingly
often), removing or adding levels of hierarchy, and other such common
operations on a hierarchical list.&lt;/p&gt;
&lt;p&gt;Now, you may wonder how, if typing &lt;code&gt;dd&lt;/code&gt; deletes a line, how I type a literal
&lt;code&gt;dd&lt;/code&gt;. Well, &lt;code&gt;dd&lt;/code&gt; deletes a line in &lt;em&gt;normal&lt;/em&gt; mode, but if you type &lt;code&gt;o&lt;/code&gt;, it
&lt;strong&gt;o&lt;/strong&gt;pens up a new line in &lt;em&gt;insert&lt;/em&gt; mode, so that your letters are interpreted
as letters again &amp;ndash; until you are done inserting what you had to insert,
and hit &lt;code&gt;[ESC]&lt;/code&gt; to return to normal mode.&lt;/p&gt;
&lt;p&gt;One of the ways you can tell you&amp;rsquo;re a proficient &lt;code&gt;vim&lt;/code&gt; user is if you keep
the system in normal mode any time you are not literally typing. Typing
tends to be bursty anyway, and evenly interspersed with editing and
navigating &amp;ndash; at least in programming, and in my use case, also with
writing.&lt;/p&gt;
&lt;p&gt;But it is hard for a newbie. Every once in a while, even I find myself
inserting an editing command as text by accident, or running random
commands trying to type text while I&amp;rsquo;m actually in normal mode. When
you&amp;rsquo;re new to &lt;code&gt;vim&lt;/code&gt; this happens all the time. It&amp;rsquo;s decidedly not
beginner-friendly.&lt;/p&gt;
&lt;p&gt;But most of your time at a text editor &amp;ndash; especially if you&amp;rsquo;re a programmer
&amp;ndash; you won&amp;rsquo;t be a beginner. And for me, I&amp;rsquo;m extremely used to it &amp;ndash; and
frustrated when I have to write text into a non-vim interface like
Google Docs, or an especially long Slack message. That, and, I do revise
just as often, if not more often, to how much additional text I type &amp;ndash;
I need those commands, and the ones I listed are only a brief sample.&lt;/p&gt;
&lt;h2 id=&#34;terminalcommand-line&#34;&gt;Terminal/Command Line&lt;/h2&gt;
&lt;p&gt;This is probably the most interesting thing to many of my readers.
Many readers my age or older remember DOS and the DOS prompt, and having
to use the computer from the command line. For some of them, the only
commands they knew were those to launch their games, or to launch other
tools from which they would do their real work &amp;ndash; the command line was
fundamentally just a launcher, a menu, albeit one that didn&amp;rsquo;t list the
options. Others may have simply used it to launch Microsoft Windows,
by typing the &lt;code&gt;win&lt;/code&gt; command, a usage pattern so common that Microsoft
made it the premise of Windows 95, and skipped the whole &amp;ldquo;DOS&amp;rdquo; step,
even though it was still present as a weird operating system layer and
as a boot stage until Windows XP finally rolled out a modern Windows.&lt;/p&gt;
&lt;p&gt;So I have some misconceptions to address about the command line that
come from that perspective.&lt;/p&gt;
&lt;p&gt;First, a modern command line is not DOS in a window. It&amp;rsquo;s certainly not on
Linux or macOS, where it&amp;rsquo;s more visibly different, but it isn&amp;rsquo;t even
DOS in modern Windows. The Windows command line might look like the DOS
command line, with its famous prompt &lt;code&gt;C:\&amp;gt;&lt;/code&gt;, but it is a modern Windows
application that is used to launch modern Windows applications. No DOS
involved, just a different interface mode.&lt;/p&gt;
&lt;p&gt;On a related note, the command line, even on Windows but especially
on macOS or Linux, is a modern user interface. It can do things that
involve the Internet. It can make web requests, download and send e-mail,
synchronize files, and do things that DOS couldn&amp;rsquo;t do.&lt;/p&gt;
&lt;p&gt;However, on the flip side, it is not true that the command line
can do everything a graphical user interface can do. It&amp;rsquo;s comparable,
but it&amp;rsquo;s simply not identical, as should be obvious if you realize that
it&amp;rsquo;s impossible to watch a video from the command line. You can use
the command line to &lt;em&gt;launch&lt;/em&gt; a video player, but the video player
remains graphical.&lt;/p&gt;
&lt;p&gt;And while it is true that the command line allows you more control over
the operating system settings and file system, this is more an accident of
graphical user interfaces trying to be &amp;ldquo;user friendly&amp;rdquo; or having limited
room for options, rather than anything intrinsic. You may have heard
of graphical user interfaces described as a layer or façade on top of
the &amp;ldquo;underlying&amp;rdquo; command line, but that is a misconception. Graphical
programs and command line programs have the same access to operating
system facilities, except for user interface.&lt;/p&gt;
&lt;p&gt;The command line does, however, have a more power user-friendly
aesthetic. Like &lt;code&gt;vim&lt;/code&gt;, it requires investment to use effectively &amp;ndash;
to use at all. And it is closer to the operating system in that by
convention, it exposes as much control of it as possible, and its
conventions were established in the 70s, before the modern concept of
user-friendliness was really invented. This has been written about at
length in many places, and one of my favorite (book-length) essays
about it is Neal Stephenson&amp;rsquo;s &lt;a href=&#34;http://project.cyberpunk.ru/lib/in_the_beginning_was_the_command_line/&#34;&gt;&amp;ldquo;In the Beginning was the Command
Line&amp;rdquo;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enough about what the command line &lt;em&gt;is&lt;/em&gt; (and isn&amp;rsquo;t)! What do I actually
use the command line &lt;em&gt;for&lt;/em&gt;, then?&lt;/p&gt;
&lt;p&gt;Well, the command line is an entire interface into the computer, used by
many programs and utilities as the way to interact with them. And I do
use it for basically all of the things I do on the computer that aren&amp;rsquo;t
web browsing, text editing, or viewing various graphical-only files
(like PDFs, images, or videos), and there&amp;rsquo;s some variety there.&lt;/p&gt;
&lt;p&gt;Primarily, I use the command line for file management. I use the classic Unix
tools for listing files (&lt;code&gt;ls&lt;/code&gt; for &lt;strong&gt;l&lt;/strong&gt;i&lt;strong&gt;s&lt;/strong&gt;t) and navigating directory
hierarchies (&lt;code&gt;cd&lt;/code&gt; for &lt;strong&gt;c&lt;/strong&gt;hange &lt;strong&gt;d&lt;/strong&gt;irectory). I use &lt;code&gt;git&lt;/code&gt; to sync code
and writing across computers and make sure it&amp;rsquo;s backed up somewhere.
I use &lt;code&gt;wc&lt;/code&gt; (for &lt;strong&gt;w&lt;/strong&gt;ord &lt;strong&gt;c&lt;/strong&gt;ount) to see how many lines of code or
words of writing I&amp;rsquo;ve written. I use &lt;code&gt;bc&lt;/code&gt; (&lt;strong&gt;b&lt;/strong&gt;asic &lt;strong&gt;c&lt;/strong&gt;alculator)
to do back-of-the-envelope math.&lt;/p&gt;
&lt;p&gt;I prefer this to graphical file managers. Not only do I not trust them &amp;ndash;
I&amp;rsquo;ve seen Finder crash relatively recently &amp;ndash; they change all the time.
And the changes are not good, and usually serve to hide the actual
directory hierarchy and instead impose an organizational system on
you. Instead of seeing directories inside your home directory, you see
stuff like &amp;ldquo;Music&amp;rdquo; and &amp;ldquo;Downloads,&amp;rdquo; &amp;ldquo;Documents and &amp;ldquo;Movies.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Usually, when I use a graphical file manager, I know where the directory
is in the file system, but then I have to translate it to their list of
commonly used directories, which assumes I keep loads of movies and photos
on my computer, but can have all my &amp;ldquo;documents,&amp;rdquo; whether legal documents
or writing projects, in one directory? Where is my home directory? What
if I want to organize my files in a different hierarchy? Can I just navigate
to it from my home directory, please? If you want to put fancy icons on
subdirectories of my home directory based on their names, that&amp;rsquo;s fine, but
please list &lt;em&gt;all&lt;/em&gt; the directories within my home directory, thank you
very much! Not just the pre-defined things you think I ought to have, like
&amp;ldquo;Music&amp;rdquo; &amp;ndash; this is my work computer, I listen to music on my phone.&lt;/p&gt;
&lt;p&gt;So you can see why I prefer the straight-forwardness of the command line
to Finder or Windows Explorer.&lt;/p&gt;
&lt;p&gt;I also use the command line to actually do writing and programming work,
not just launching &lt;code&gt;gvim&lt;/code&gt; &amp;ndash; once I&amp;rsquo;ve navigated to the file in my complicated
directory system &amp;ndash; but also running compilers and build scripts to
turn program source code into programs, and then running those programs,
almost all of which can be controlled entirely from the command line. I
log into other computers I maintain, both embedded devices and servers,
and do work on them. I run scripts that run &lt;code&gt;hugo&lt;/code&gt; to turn my Markdown
files into a website and post it on a server.&lt;/p&gt;
&lt;p&gt;I also use it for system administration: &lt;code&gt;apt&lt;/code&gt; for installing files (I
use Ubuntu &amp;ndash; I&amp;rsquo;m not trying to be a hero of sysadmin) and &lt;code&gt;systemctl&lt;/code&gt;
and all of those gnarly commands for other sysadmin stuff. But of course,
the most powerful system administration command is just the text editor &amp;ndash;
by editing configuraton files, you can accomplish a lot.&lt;/p&gt;
&lt;p&gt;All of this is easier and more focused than if I were using the graphical
equivalent. I write my command and I run it, without having to go through
all the tedious boring steps of a GUI wizard. It&amp;rsquo;s faster with fewer steps,
with the penalty of accumulated life expertise &amp;ndash; which is to say it&amp;rsquo;s
easy on my &lt;a href=&#34;https://www.thecodedmessage.com/posts/write-everything-down/&#34;&gt;perspective memory at the expense of my retrospective
memory&lt;/a&gt;, which is to say, aligned to how
my brain works.&lt;/p&gt;
&lt;p&gt;And yes, I do occasionally have to look up how to do things &amp;ndash; though
that&amp;rsquo;s more in programming than in writing. But having a graphical
user interface doesn&amp;rsquo;t save you from that, and if you think it does,
you&amp;rsquo;re fooling yourself. At least when I look up how to do things, I get
suggestions for commands I can directly type in, rather than having to
go through 10 screens and dialog boxes and search them for whatever it
is the poster&amp;rsquo;s talking about, only to find out I&amp;rsquo;m using a different
version of the GUI, and that the directions became obsolete in the 2022
edition of Windows 10, or some other such thing.&lt;/p&gt;
&lt;p&gt;To reiterate, it turns out that a deep enough hierarchy of dialog
boxes and settings pages is just as complicated as the command line &amp;ndash;
but usually less powerful, harder to document, and more subject to
arbitrary change. Just give me the command line!&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;If I were to summarize some themes of my user interface decisions,
it would be in these three inter-related points:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Don&amp;rsquo;t use condescending, corporatist concepts of &amp;ldquo;easy to use,&amp;rdquo; because
they&amp;rsquo;re more focused on the &lt;em&gt;appearance&lt;/em&gt; of ease of use, or most charitably
stated, not intimidating the user, rather than actually making it usable
for an expert user for a wide variety of actual tasks.&lt;/li&gt;
&lt;li&gt;Use systems that emphasize the long term power user over the short term
newbie. They will often have a learning curve, but it will pay off.&lt;/li&gt;
&lt;li&gt;Use systems that are customizable, so that I can use them my way.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;But this is &lt;em&gt;all&lt;/em&gt; for my work computer, where work is both writing/blogging
and programming. For goofing off, I have a MacBook Air M1, which I use
in macOS as a glorified tablet, and that is perfectly fine for watching
&lt;a href=&#34;https://www.thecodedmessage.com/posts/netflix-tech/&#34;&gt;Netflix&lt;/a&gt; and YouTube.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Rust Is Beyond Object-Oriented, Part 2: Polymorphism</title>
      <link href="https://www.thecodedmessage.com/posts/oop-2-polymorphism/" />
      <id>https://www.thecodedmessage.com/posts/oop-2-polymorphism/</id>
      <updated>2023-02-07T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;In this post, I continue &lt;a href=&#34;https://www.thecodedmessage.com/tags/beyond-oop/&#34;&gt;my series&lt;/a&gt; on how Rust
differs from the traditional object-oriented programming paradigm by
discussing the second of the three traditional pillars of OOP:
polymorphism.&lt;/p&gt;
&lt;p&gt;Polymorphism is an especially big topic in object-oriented programming,
perhaps the most important of its three pillars. Several books could be
(and have been) written on what polymorphism is, how various programming
languages have implemented it (both within the OOP world and outside of it
&amp;ndash; yes, polymorphism exists outside of OOP), how to use it effectively,
and when not to use it. Books could be written on how to use the Rust
version of it alone.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;In this post, I continue &lt;a href=&#34;https://www.thecodedmessage.com/tags/beyond-oop/&#34;&gt;my series&lt;/a&gt; on how Rust
differs from the traditional object-oriented programming paradigm by
discussing the second of the three traditional pillars of OOP:
polymorphism.&lt;/p&gt;
&lt;p&gt;Polymorphism is an especially big topic in object-oriented programming,
perhaps the most important of its three pillars. Several books could be
(and have been) written on what polymorphism is, how various programming
languages have implemented it (both within the OOP world and outside of it
&amp;ndash; yes, polymorphism exists outside of OOP), how to use it effectively,
and when not to use it. Books could be written on how to use the Rust
version of it alone.&lt;/p&gt;
&lt;p&gt;Unfortunately this is just a blog post, so I cannot cover polymorphism in
as much detail or variety as I want to. I shall instead focus specifically
on how Rust differs from the OOP conceptualization. I will start by
describing how it works in OOP, and then discuss how to accomplish the
same goals in Rust.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In OOP, polymorphism is everything. It tries to take all decision-making
(or as much decision-making as possible) and unite it in a common
narrow mechanism: run-time polymorphism. But unfortunately, it&amp;rsquo;s not
just any run-time polymorphism, but a specific, narrow form of run-time
polymorphism, constrained by OOP philosophy and by details of how the
implementations typically work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;It requires indirection:&lt;/strong&gt; Every object must typically be stored on
the heap for run-time polymorphism to work, as the different &amp;ldquo;run-time
types&amp;rdquo; have different sizes. This encourages the aliasing of mutable
objects. Not only that, but to actually call a method, it must go
through three layers of indirection: dereferencing the object reference,
then dereferencing the class pointer or &amp;ldquo;vtable&amp;rdquo; pointer, and then
doing an indirect function call.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It precludes optimization:&lt;/strong&gt; Beyond the intrinsic cost of an
indirect function call, the fact that the call is indirect means
that inlining is impossible. Often, the polymorphic methods are
small or even trivial, such as returning a constant, setting a field,
or re-arranging the parameters and calling another method, so inlining
would be useful. Inlining is also important to allow optimizations to
cross the inlining boundary.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It is polymorphic in one parameter only:&lt;/strong&gt; The special receiver
parameter, called &lt;code&gt;self&lt;/code&gt; or &lt;code&gt;this&lt;/code&gt;, is the only parameter through which
run-time polymorphism is typically possible. Polymorphism on other
parameters can be simulated with helper methods in those types, which
is awkward, and return-type polymorphism is impossible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Each value is independently polymorphic:&lt;/strong&gt; In run-time polymorphism,
there is often no way to say that all the elements of a collection are of
some type &lt;code&gt;T&lt;/code&gt; that all implement the same interface, or to say that
two parameters to a function are the same type but what that type is
should be determined at run-time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It is entangled with other OOP features:&lt;/strong&gt; In C++, runtime
polymorphism is tightly coupled with inheritance. In many OOP
programming languages, it is only available for class types, which
as I discussed in my &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation/&#34;&gt;previous post&lt;/a&gt;
are a constrained form of modules.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I could write an entire blog post about each of these constraints &amp;ndash;
perhaps I will someday.&lt;/p&gt;
&lt;p&gt;But in spite of all these constraints, it is seen as the preferred way of
doing decision-making in OOP languages, and as especially intuitive
and accesible. Programmers are trained to reach for this tool whenever
feasible, whether or not it is the best tool for the decision at hand,
even if there is no current need for it to be a run-time decision.
Some programming languages, such as Smalltalk, even collapsed &amp;ldquo;if-then&amp;rdquo;
logic and loops into this one oddly specific decision-making structure,
implementing them via polymorphic methods like &lt;code&gt;ifTrue:ifFalse&lt;/code&gt; that
would be implemented differently in the &lt;code&gt;True&lt;/code&gt; and &lt;code&gt;False&lt;/code&gt; classes
(and therefore on the &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; objects).&lt;/p&gt;
&lt;p&gt;To be clear, having a mechanism of vtable-based runtime polymorphism
isn&amp;rsquo;t a bad thing &lt;em&gt;per se&lt;/em&gt; &amp;ndash; Rust even has one (similar, but not quite
identical, to the OOP version described above). But the Rust version
is used in the relatively rare situations where that mechanism is the
best fit, among a whole palette of mechanisms. In OOP, the elevation of
this tightly constrained and unperformant form of decision making above
all others, and the philosophical assertion that using it is the best
way and most intuitive way to express program flow and business logic,
is a problem.&lt;/p&gt;
&lt;p&gt;It turns out that programming is much more ergonomic when you choose
the tool most appropriate for the situation at hand &amp;ndash; and OOP run-time
polymorphism is only occasionally the actual tool for the jobs it
is often asked to do.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s look at 4 alternatives in Rust that can be used when OOP
uses run-time polymorphism.&lt;/p&gt;
&lt;h1 id=&#34;alternative-0-enum&#34;&gt;Alternative #0: &lt;code&gt;enum&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;Not only are there other forms of polymorphism that have strictly
fewer constraints (such as Haskell&amp;rsquo;s typeclasses) or a different set of
trade-offs (such as Rust&amp;rsquo;s traits, heavily based on Haskell typeclasses),
there is another decision-making systems in Rust and Haskell, namely
algebraic data types (ADTs), or sum types, that also take over many of
the applications of OOP-style polymorphism.&lt;/p&gt;
&lt;p&gt;In Rust, these are known as &lt;code&gt;enum&lt;/code&gt;s. &lt;code&gt;enum&lt;/code&gt;s in many programming
language are lists of constants to be stored in integer-sized types,
sometimes implemented in a typesafe fashion (like in Java), sometimes
not (like in C), sometimes with either option available (like in C++
with the distinction between &lt;code&gt;enum&lt;/code&gt; and &lt;code&gt;enum class&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Rust &lt;code&gt;enum&lt;/code&gt;s support this familiar use case, with type-safety:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Visibility&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Visible,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Invisible,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But they also support additional fields associated with each option,
creating what in type theory is known as a &amp;ldquo;sum type,&amp;rdquo; but it is
better known among C or C++ programmers as a &amp;ldquo;tagged union&amp;rdquo; &amp;ndash;
the difference being that in Rust, the compiler is aware of and
enforces the tag. Here&amp;rsquo;s some examples of some &lt;code&gt;enum&lt;/code&gt; declarations:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserId&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Username(String),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Anonymous(IpAddress),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ^^ This isn&amp;#39;t supposed to be a real network type,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// just an example.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; user1 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; UserId::Username(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;.to_string());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; user2 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; UserId::Anonymous(parse_ip(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;?&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;HostIdentifier&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Dns(DomainName),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ipv4Addr(Ipv4Addr),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ipv6Addr(Ipv6Addr),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Location&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Nowhere,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Address(Address),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Coordinates {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        lat: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        long: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; loc1 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Location::Nowhere;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; loc2 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Location::Coordinates {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lat: &lt;span style=&#34;color:#ae81ff&#34;&gt;80.0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    long: &lt;span style=&#34;color:#ae81ff&#34;&gt;40.0&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What do these tagged unions have to do with polymorphism, you may ask?
Well, most OOP languages don&amp;rsquo;t have good syntax for these sum types,
but they do have powerful mechanisms for run-time polymorphism, and so
you&amp;rsquo;ll see run-time polymorphism used for situations where Rust &lt;code&gt;enum&lt;/code&gt;s
would actually be just as well-suited (and I will argue, better suited):
when there&amp;rsquo;s a few options for how to store a value, but those options
contain different details.&lt;/p&gt;
&lt;p&gt;For example, here&amp;rsquo;s one way to represent the &lt;code&gt;UserId&lt;/code&gt; type in Java using
inheritance and run-time polymorphism &amp;ndash; how I would&amp;rsquo;ve done it when I
was a student (putting each class in a different file):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserId&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Username&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; UserId {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; String username;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Username&lt;/span&gt;(String username) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;username&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; username;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ... getters, setters, etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AnonymousUser&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; UserId {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; Ipv4Address ipAddress;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ... constructor, getters, setters, etc.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;UserId user1 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Username(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;UserId user2 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; AnonymousUser(&lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; Ipv4Address(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Importantly, just as in the &lt;code&gt;enum&lt;/code&gt; example, we can put &lt;code&gt;user1&lt;/code&gt;
and &lt;code&gt;user2&lt;/code&gt; in variables of the same type, and can pass them to
the same kinds of functions, and in general do the same operations
on them.&lt;/p&gt;
&lt;p&gt;Now, these OOP-style classes look super-light to the point of being
silly, but that&amp;rsquo;s mostly because we haven&amp;rsquo;t added any real operational
code to this situation &amp;ndash; just data and structure and a bit of variable
definitions and boilerplate. Let&amp;rsquo;s consider what happens if we actually
do anything with user IDs.&lt;/p&gt;
&lt;p&gt;For example, we might want to determine whether they&amp;rsquo;re an administrator.
In our hypothetical, let&amp;rsquo;s say anonymous users are never administrators,
and users with usernames are only administrators if the username begins
with the string &lt;code&gt;admin_&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The doctrinally approved object-oriented way of doing that is to
add a method, e.g. &lt;code&gt;isAdministrator&lt;/code&gt;. In order for this method to
work, we have to add it to all three classes, the base class and
the two child classes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserId&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;abstract&lt;/span&gt; bool &lt;span style=&#34;color:#a6e22e&#34;&gt;isAdministrator&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Username&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; UserId {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; bool &lt;span style=&#34;color:#a6e22e&#34;&gt;isAdministrator&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; username.&lt;span style=&#34;color:#a6e22e&#34;&gt;startsWith&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;admin_&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AnonymousUser&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; UserId {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; bool &lt;span style=&#34;color:#a6e22e&#34;&gt;isAdminstrator&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, in order to add this simple operation, this simple capability
to this type in Java, we have to go to three classes, which will be
stored in three files. Each of them contains a method that does
something simple, but nowhere can the entire logic be seen of
who is and isn&amp;rsquo;t an administrator &amp;ndash; something that someone might
naturally ask.&lt;/p&gt;
&lt;p&gt;Rust would use &lt;code&gt;match&lt;/code&gt; for such an operation, putting all the
information about it in one place:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;is_administrator&lt;/span&gt;(user: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;UserId&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;match&lt;/span&gt; user {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        UserId::Username(name) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; name.starts_with(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;admin_&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        UserId::AnonymousUser(_) &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This yields a more complicated individual function, but it has all the
logic explicitly right there. Having the logic be explicit, instead of
implicit in an inheritance hierarchy, cuts against an OOP precept where
methods should be simple and polymorphism used to express the logic
implicitly. But that doesn&amp;rsquo;t help guarantee anything, just sweeps it
under the rug: It turns out that hiding the complexity makes it harder
to grapple with, not easier.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s go through another example. We&amp;rsquo;ve had this &lt;code&gt;UserId&lt;/code&gt; code for a while,
and you&amp;rsquo;re tasked with writing a new web front-end for this system. You
need some way of displaying the user information in HTML, either a link
to a user profile (in the case of a named user) or a stringification of
the IP address in red (in the case of an anonymous user). So you decide
to add a new operation for this small family of types, &lt;code&gt;toHTML&lt;/code&gt;, which
outputs your new front-end&amp;rsquo;s specialized DOM type. (Maybe the Java&amp;rsquo;s
compiled to WebAssembly, I&amp;rsquo;m not sure. The details don&amp;rsquo;t matter.)&lt;/p&gt;
&lt;p&gt;You submit a pull request to the maintainer of the &lt;code&gt;UserId&lt;/code&gt; class
hierarchy, deep in a core library of the backend. And then they reject
it.&lt;/p&gt;
&lt;p&gt;They have pretty good reasons, actually, you grudgingly admit. They&amp;rsquo;re
saying it&amp;rsquo;s an absurd separation of concerns. Besides, the company can&amp;rsquo;t
have this core library handling types from your front-end.&lt;/p&gt;
&lt;p&gt;So, you sigh, and write the equivalent of a Rust &lt;code&gt;match&lt;/code&gt; expression,
but in Java (please pardon my absurd hypothetical HTML
library):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Html &lt;span style=&#34;color:#a6e22e&#34;&gt;userIdToHtml&lt;/span&gt;(UserId userId) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (userId &lt;span style=&#34;color:#66d9ef&#34;&gt;instanceof&lt;/span&gt; Username) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Username username &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (Username)userId;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        String usernameString &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; username.&lt;span style=&#34;color:#a6e22e&#34;&gt;getUsername&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Url url &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; ProfileHandler.&lt;span style=&#34;color:#a6e22e&#34;&gt;getProfileForUsername&lt;/span&gt;(usernameString);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; Link.&lt;span style=&#34;color:#a6e22e&#34;&gt;createTextLink&lt;/span&gt;(url, username.&lt;span style=&#34;color:#a6e22e&#34;&gt;getUsername&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (userId &lt;span style=&#34;color:#66d9ef&#34;&gt;instanceof&lt;/span&gt; AnonymousUser) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        AnonymousUser anonymousUser &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (AnonymousUser)userId;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; Span.&lt;span style=&#34;color:#a6e22e&#34;&gt;createColoredText&lt;/span&gt;(anonymousUser.&lt;span style=&#34;color:#a6e22e&#34;&gt;getIp&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;formatString&lt;/span&gt;(), &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;red&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; RuntimeException(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;IDK, man&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this code your boss rejects upon code review, saying you used
the &lt;code&gt;instanceof&lt;/code&gt; anti-pattern, but then later they grudgingly
accept it after you make them argue with the maintainer of the core
library that wouldn&amp;rsquo;t accept your other patch.&lt;/p&gt;
&lt;p&gt;But look at how ugly that &lt;code&gt;instanceof&lt;/code&gt; code is! No wonder Java programmers
consider it an anti-pattern! But in this situation, it&amp;rsquo;s the most
reasonable thing, really the only possible thing besides implementing
the observer pattern or the visitor pattern or something else that
just amounts to infrastructure to fake an &lt;code&gt;instanceof&lt;/code&gt; with inversion
of control.&lt;/p&gt;
&lt;p&gt;Having operations implemented by adding a method to every subclass makes
sense when the set of operations is bounded (or close to it) and the
number of subclasses of the class might grow in unanticipated ways. But
just as often, the number of operations will grow in unanticipated ways,
while the number of subclasses is bounded (or close to it).&lt;/p&gt;
&lt;p&gt;For the latter situation, which is more common than OOP advocates would
imagine, Rust &lt;code&gt;enum&lt;/code&gt;s &amp;ndash; and sum types in general &amp;ndash; are perfect. Once
you&amp;rsquo;ve gotten used to them, you find yourself using them all the time.&lt;/p&gt;
&lt;p&gt;I will say for the record that it isn&amp;rsquo;t this bad in all object-oriented
programming languages. In some, you can write arbitrary class-method
combinations in any order, and so you could write all three
implementations in one place if you so chose. Smalltalk traditionally
lets you navigate the codebase in a special browser, where you can see
either a list of methods implemented by a class, or a list of classes
that accept a given &amp;ldquo;message,&amp;rdquo; as Smalltalk calls it, so you can have
your cake and eat it too.&lt;/p&gt;
&lt;h1 id=&#34;alternative-1-closures&#34;&gt;Alternative #1: Closures&lt;/h1&gt;
&lt;p&gt;Sometimes, an OOP interface or polymorphic decision only involves one
actual operation. In such a situation, a closure can just be used instead.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t want to spend too much time on this, because most OOP programmers
are already aware of this, and have been since their OOP languages have
caught up with functional languages and gotten syntax for lambdas &amp;ndash;
Java in Java 8, C++ in C++11. Silly one-method interfaces like Java&amp;rsquo;s
&lt;a href=&#34;https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html&#34;&gt;&lt;code&gt;Comparator&lt;/code&gt;&lt;/a&gt;
are therefore &amp;ndash; fortunately &amp;ndash; mostly a thing of the past.&lt;/p&gt;
&lt;p&gt;Also, closures in Rust technically involve traits, and so are implemented
using the same mechanism as the next two alternatives, so one could also
argue that this isn&amp;rsquo;t really a separate option in Rust. In my mind,
however, lambdas, closures, and the &lt;code&gt;FnMut&lt;/code&gt;/&lt;code&gt;FnOnce&lt;/code&gt;/&lt;code&gt;Fn&lt;/code&gt; traits are
special enough aesthetically and situationally that it deserved a little
bit of time.&lt;/p&gt;
&lt;p&gt;And so I&amp;rsquo;ll take the little bit of time to just say this: If you find
yourself writing a trait (or a Java interface or a C++ class) with
exactly one method, please consider whether you should instead be using
some sort of closure or lambda type. Only you can prevent overengineering.&lt;/p&gt;
&lt;h1 id=&#34;alternative-2-polymorphism-with-traits&#34;&gt;Alternative #2: Polymorphism with Traits&lt;/h1&gt;
&lt;p&gt;Just like Rust has a version of encapsulation more flexible and more
powerful than the OOP notion of classes, as I discuss in the &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation&#34;&gt;previous
post&lt;/a&gt;, Rust has a more powerful version of
polymorphism than OOP posits: traits.&lt;/p&gt;
&lt;p&gt;Traits are like interfaces from Java (or an all-abstract superclass
in C++), but without most of the constraints that I discuss at the
beginning of the blog post. They have neither the semantic constraints
or the performance constraints. Traits are heavily inspired in semantics
and principle by Haskell&amp;rsquo;s typeclasses, and in syntax and implementation
by C++&amp;rsquo;s templates. C++ programmers can think of them as templates with
concepts (except done right, baked into the programming language from the
get-go, and without having to deal with all the code that doesn&amp;rsquo;t use it).&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start with the semantics: What can you do with traits that
you can&amp;rsquo;t do with pure OOP, even if you throw all the indirection
in the world at it? Well, in pure OOP terms, there&amp;rsquo;s no way
you can write an interface like Rust &lt;code&gt;Eq&lt;/code&gt; and &lt;code&gt;Ord&lt;/code&gt;, given
greatly oversimplified definitions here (the real definitions
of &lt;a href=&#34;https://doc.rust-lang.org/std/cmp/trait.Eq.html&#34;&gt;&lt;code&gt;Eq&lt;/code&gt;&lt;/a&gt; and
&lt;a href=&#34;https://doc.rust-lang.org/std/cmp/trait.Ord.html&#34;&gt;&lt;code&gt;Ord&lt;/code&gt;&lt;/a&gt; extend other
classes that allow partial equivalence and orderings between different
types, but like these simplified definitions, the Rust standard library
version of non-partial &lt;code&gt;Eq&lt;/code&gt; and &lt;code&gt;Ord&lt;/code&gt; do cover equivalence and ordering
between values of the same type):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;trait&lt;/span&gt; Eq {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;eq&lt;/span&gt;(self, other: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Ordering&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Less,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Equal,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Greater,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;trait&lt;/span&gt; Ord: Eq {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;cmp&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;self, other: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Ordering&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;See what&amp;rsquo;s happening? Like in an OOP-style interface, the methods take a
&amp;ldquo;receiver&amp;rdquo; type, a &lt;code&gt;self&lt;/code&gt; parameter, of the &lt;code&gt;Self&lt;/code&gt; type &amp;ndash; that is, of
whatever concrete type implements the trait (technically here a reference
to &lt;code&gt;Self&lt;/code&gt; or &lt;code&gt;&amp;amp;Self&lt;/code&gt;). But unlike in an OOP-style interface, they also
take another argument of &lt;code&gt;&amp;amp;Self&lt;/code&gt; type. In order to implement &lt;code&gt;Eq&lt;/code&gt; and
&lt;code&gt;Ord&lt;/code&gt;, a type &lt;code&gt;T&lt;/code&gt; provides a function that takes two references to &lt;code&gt;T&lt;/code&gt;.
That&amp;rsquo;s meant literally: two references to &lt;code&gt;T&lt;/code&gt;, not one reference to &lt;code&gt;T&lt;/code&gt;
and one reference to &lt;code&gt;T&lt;/code&gt; or any subclass (such a thing doesn&amp;rsquo;t exist
in Rust), not one reference to &lt;code&gt;T&lt;/code&gt; and one reference to any other value
that implements &lt;code&gt;Eq&lt;/code&gt;, but two bona-fide non-heterogeneous references to
the same concrete type, that the function can then compare for equality
(or ordering).&lt;/p&gt;
&lt;p&gt;This is important, because we want to use this to implement methods
like &lt;code&gt;sort&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; Vec&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self) &lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; T: Ord {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OOP-style polymorphism is ideal for heterogeneous containers, where
each element has its own runtime type and its own implementation of
the interfaces. But sort doesn&amp;rsquo;t work like that. You can&amp;rsquo;t sort a
collection like &lt;code&gt;[3, &amp;quot;Hello&amp;quot;, true]&lt;/code&gt;; there&amp;rsquo;s no reasonable ordering
across all types.&lt;/p&gt;
&lt;p&gt;Instead, &lt;code&gt;sort&lt;/code&gt; operates on homogeneous containers. All the elements
have to match in type, so that they can be mutually compared. They
don&amp;rsquo;t each need to have different implementations of the operations.&lt;/p&gt;
&lt;p&gt;Nevertheless, &lt;code&gt;sort&lt;/code&gt; is still polymorphic. A sorting algorithm is
the same for integers or strings, but comparing integers is a completely
different operation than comparing strings. The sorting algorithm needs
a way of invoking an operation on its items &amp;ndash; the comparison operation &amp;ndash;
differently for different types, while still having the same overall
structure of code.&lt;/p&gt;
&lt;p&gt;This can be done by injecting a comparison function, but many types
have an intrinsic, default ordering, and &lt;code&gt;sort&lt;/code&gt; should default to it.
Thus, polymorphism &amp;ndash; but not an OOP-friendly variety.&lt;/p&gt;
&lt;p&gt;See the contrivance Java goes through to define &lt;code&gt;sort&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; Comparable&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;super&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sort&lt;/span&gt;(List&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; list)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There is no simple trait that can require &lt;code&gt;T&lt;/code&gt; to be comparable to other
&lt;code&gt;T&lt;/code&gt;s, for &lt;code&gt;T&lt;/code&gt; to be ordered. Instead, as far as the programming language
is concerned, the idea that &lt;code&gt;T&lt;/code&gt; is comparable to itself, rather than
to any other random type, is only articulated as an accident to this
method. Nothing is stopping someone from implementing the &lt;code&gt;Comparable&lt;/code&gt;
interface in an inconsistent way, like having &lt;code&gt;Integer&lt;/code&gt; implement
&lt;code&gt;Comparable&amp;lt;String&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Additionally, when it actually looks up the implementation of
&lt;code&gt;Comparable&lt;/code&gt;, it decides what implementation to use based on the first
argument of any comparison, not based on the type. Normally, they
will all be the same type, but theoretically, this list could be
heterogeneous, as long as all the objects &amp;ldquo;extend&amp;rdquo; &lt;code&gt;T&lt;/code&gt;, and they
could implement &lt;code&gt;Comparable&lt;/code&gt; differently. The computer has to do
extra work to indulge this possibility, even though it would
certainly be a mistake.&lt;/p&gt;
&lt;p&gt;As we&amp;rsquo;re now drifting outside of the realm of semantics, and into
the realm of performance, let&amp;rsquo;s discuss the performance implementations
of this fully.&lt;/p&gt;
&lt;p&gt;The Java &lt;code&gt;sort&lt;/code&gt; method, as we mentioned, requires every item in the
collection to be a full object type, which means that instead of storing
the values directly in the array, the values are stored in the heap, and
references are stored in the array. This is unnecessary with a traits-based
approach &amp;ndash; the values can live directly in the array.&lt;/p&gt;
&lt;p&gt;This means that different arrays will have different element sizes, so
this has to be handled by a trait as well. And it is: The size of the
values is also parameterized via the &lt;code&gt;Sized&lt;/code&gt; trait. The size does have to
be consistent among all the items of the array, but this is enforceable
because we can express that all the elements are actually the exact same
type &amp;ndash; unlike Java&amp;rsquo;s &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; which only expresses that they&amp;rsquo;re of type
&lt;code&gt;T&lt;/code&gt; or some subtype of &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Rust&amp;rsquo;s &lt;code&gt;sort&lt;/code&gt; method could have been implemented by passing the size
information (from the &lt;code&gt;Sized&lt;/code&gt; trait) and the ordering function (from
the &lt;code&gt;Ord&lt;/code&gt; trait) at runtime as an integer value and a function pointer.
This is how typeclasses work in Haskell, which was the inspiration
for Rust traits. This would still be more efficient than the Java,
as there would be a single ordering function, rather than a different
indirect lookup for every left side of the comparison, allowing indirect
branch prediction to work in the processor.&lt;/p&gt;
&lt;p&gt;But Rust goes even further than that, and implements its traits instead
via monomorphization. This is similar to C++ template instantiation,
but semantically better constrained. The premise is that while &lt;code&gt;sort&lt;/code&gt;
is only one method semantically, in the outputted, compiled code, a
different version of &lt;code&gt;sort&lt;/code&gt; is outputted for every type &lt;code&gt;T&lt;/code&gt; that it
is called with.&lt;/p&gt;
&lt;p&gt;C++ templates create infamously bad error messages and are difficult to
reason about, because they are essentially macros, and awkward ones.
Even Rust cannot create great error messages with its macro system.
But also, writing them requires expertise, and means that the programmer
is forgoing many of the benefits of the type system &amp;ndash; templates are often
called, in my opinion rightly so, a form of compile time duck-typing. For
these reasons, template programming in C++ is often considered more
advanced (read as harder and less convenient rather than more powerful)
than OOP-style polymorphism.&lt;/p&gt;
&lt;p&gt;In Rust, however, traits provide an organized and more coherent
way of accessing similar technology, getting the performance benefits
of templates while still giving the structure of a solid type system.&lt;/p&gt;
&lt;h1 id=&#34;alternative-3-dynamic-trait-objects&#34;&gt;Alternative #3: Dynamic Trait Objects&lt;/h1&gt;
&lt;p&gt;Sometimes, however, you do need full run-time polymorphism. You have
the opposite of the scenario with the &lt;code&gt;enum&lt;/code&gt;: You have a closed set of
operations that can be performed on a value, but what those operations
actually do will change dynamically in a way that cannot be bounded
ahead of time.&lt;/p&gt;
&lt;p&gt;In such situations, Rust has you covered with the &lt;code&gt;dyn&lt;/code&gt; keyword.
Please don&amp;rsquo;t overuse it, though. In almost all situations where
I&amp;rsquo;ve thought it might be appropriate, static polymorphism combined
with other design elements have worked out better.&lt;/p&gt;
&lt;p&gt;Legitimate use cases for &lt;code&gt;dyn&lt;/code&gt; tend to come up in situations involving
inversion of control, where a framework library takes on a main loop, and
the client code says how to handle various events. In network programming,
the framework library says how to juggle all the sockets and register
them with the operating system, but the application needs to say what to
actually do with the data. In GUI programming, the framework code can
say what widget was being clicked on, but very different things happen
if that widget is a button versus a text box versus a custom widget you
invented for this particular app.&lt;/p&gt;
&lt;p&gt;Now, you don&amp;rsquo;t strictly need run-time polymorphism for this. You could
use closures (or even raw function pointers) instead, creating &lt;code&gt;struct&lt;/code&gt; of
closures (or function pointers) if multiple operations are called for &amp;ndash;
which amounts to basically doing what &lt;code&gt;dyn&lt;/code&gt; does the hard way by hand. For
example, I fully expected &lt;code&gt;tokio&lt;/code&gt; to use Rust&amp;rsquo;s run-time polymorphism
feature internally to handle this inversion of control in task
scheduling. Instead, for what I imagine are performance reasons, &lt;code&gt;tokio&lt;/code&gt;
implements &lt;code&gt;dyn&lt;/code&gt; by hand, even calling its &lt;code&gt;struct&lt;/code&gt; of function pointers
&lt;a href=&#34;https://github.com/tokio-rs/tokio/blob/a7945b469d634cf205094d8a1661720358622cc0/tokio/src/runtime/task/raw.rs#L13-L43&#34;&gt;&lt;code&gt;Vtable&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;dyn&lt;/code&gt; does all of this work for you, for your trait. The
only requirement is that your trait be object-safe, and the &lt;a href=&#34;https://doc.rust-lang.org/reference/items/traits.html#object-safety&#34;&gt;list of
requirements&lt;/a&gt;
may seem familiar, especially when it comes to the requirements for
an associated function (e.g. a method) to be &amp;ldquo;dispatchable&amp;rdquo;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Not have any type parameters (although lifetime parameters are allowed),&lt;/li&gt;
&lt;li&gt;Be a method that does not use &lt;code&gt;Self&lt;/code&gt; except in the type of the receiver.&lt;/li&gt;
&lt;li&gt;Have a receiver with one of the following types:
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;Self&lt;/code&gt; (i.e. &lt;code&gt;&amp;amp;self&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;mut Self&lt;/code&gt; (i.e &lt;code&gt;&amp;amp;mut self&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Box&amp;lt;Self&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Rc&amp;lt;Self&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Arc&amp;lt;Self&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Pin&amp;lt;P&amp;gt;&lt;/code&gt; where &lt;code&gt;P&lt;/code&gt; is one of the types above&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Does not have a where &lt;code&gt;Self: Sized&lt;/code&gt; bound (receiver type of &lt;code&gt;Self&lt;/code&gt; (i.e. &lt;code&gt;self&lt;/code&gt;) implies this).&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is to say, it can be polymorphic in exactly one parameter, and that
parameter must be by reference &amp;ndash; more or less the exact requirements for
methods to support run-time polymorphism in OOP.&lt;/p&gt;
&lt;p&gt;This is of course because &lt;code&gt;dyn&lt;/code&gt; uses almost exactly the same mechanism
as OOP to implement run-time polymorphism: the &amp;ldquo;vtable.&amp;rdquo; &lt;code&gt;Box&amp;lt;dyn Foo&amp;gt;&lt;/code&gt;
really contains two pointers rather than one, one to the object in
question, and the pointer to the &amp;ldquo;vtable,&amp;rdquo; the automatically-generated
structure of function pointers for that type. The one-parameter
requirement is because that is the parameter whose vtable is used to
look up which concrete implementation of a method to call, and the
indirection requirement is because the concrete type might be different
sizes, with the size only known at run-time.&lt;/p&gt;
&lt;p&gt;To be clear, these are limitations on one particular implementation
strategy for run-time polymorphism. Alternative strategies exist that
fully decouple the vtable from individual values of the type, as in
Haskell.&lt;/p&gt;
&lt;p&gt;There are still a few advantages of Rust&amp;rsquo;s version of run-time polymorphism
with traits as opposed to OOP-style interfaces.&lt;/p&gt;
&lt;p&gt;Performance-wise, it&amp;rsquo;s something done alongside a type, rather than
intrinsic to the type. Normal values don&amp;rsquo;t store a vtable, spreading the
cost of this throughout the program, but rather, the vtables are only
referenced when a &lt;code&gt;dyn&lt;/code&gt; pointer is created. If you never create a &lt;code&gt;dyn&lt;/code&gt;
pointer to a value of a given type, that type&amp;rsquo;s vtable doesn&amp;rsquo;t even have
to be created. Certainly, you don&amp;rsquo;t have 8 bytes of extra gunk in every
allocation for all the vtable pointers! This also means there&amp;rsquo;s one
fewer level of indirection.&lt;/p&gt;
&lt;p&gt;Semantically, it&amp;rsquo;s also a good thing that it&amp;rsquo;s just one option among
many, and that it&amp;rsquo;s not the strongly preferred option that the entire
programming language is trying to push you towards. Often, even usually,
static polymorphism, enums, or even just good old-fashioned closures
more accurately represent the problem at hand, and should be used
instead.&lt;/p&gt;
&lt;p&gt;Finally, the fact that run-time and static polymorphism in Rust both
use traits makes it easier to transition from one system to another.
If you find yourself using &lt;code&gt;dyn&lt;/code&gt; for a trait, you don&amp;rsquo;t have to use
it everywhere that trait is used. You can use the mechanisms of
static polymorphism (like type parameters and &lt;code&gt;impl Trait&lt;/code&gt;) instead,
freely mixing and matching with the same traits.&lt;/p&gt;
&lt;p&gt;Unlike in C++, you don&amp;rsquo;t have to learn two completely different sets
of syntax for concepts vs parent classes, and vastly different semantics.
Really, in Rust, dynamic polymorphism is just a special case of static
polymorphism, and the only differences are the things that actually
are different.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>My Reaction to Dr. Stroustrup&#39;s Recent Memory Safety Comments</title>
      <link href="https://www.thecodedmessage.com/posts/stroustrup-response/" />
      <id>https://www.thecodedmessage.com/posts/stroustrup-response/</id>
      <updated>2023-01-30T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;The NSA recently published a &lt;a href=&#34;https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF&#34;&gt;Cybersecurity Information
Sheet&lt;/a&gt;
about the importance of memory safety, where they recommended
moving from memory-unsafe programming languages (like C and
C++) to memory-safe ones (like Rust). Dr. Bjarne Stroustrup, the
original creator of C++, has made some
&lt;a href=&#34;https://developers.slashdot.org/story/23/01/21/0526236/rust-safety-is-not-superior-to-c-bjarne-stroustrup-says&#34;&gt;waves&lt;/a&gt;
with his
&lt;a href=&#34;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2739r0.pdf&#34;&gt;response&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To be honest, I was disappointed. As a current die-hard Rustacean
and former die-hard C++ programmer, I have thought (and
&lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;blogged&lt;/a&gt;) quite a bit about the topic of Rust vs
C++. Unfortunately, I feel that in spite of the exhortation in his title
to &amp;ldquo;think seriously about safety,&amp;rdquo; Dr. Stroustrup was not in fact thinking
seriously himself. Instead of engaging conceptually with the article,
he seems to have reflexively thrown together some talking points &amp;ndash;
some of them very stale &amp;ndash; not realizing that they mostly are not even
relevant to the NSA&amp;rsquo;s Cybersecurity Information Sheet, let alone a
thoughtful rebuttal of it.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;The NSA recently published a &lt;a href=&#34;https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF&#34;&gt;Cybersecurity Information
Sheet&lt;/a&gt;
about the importance of memory safety, where they recommended
moving from memory-unsafe programming languages (like C and
C++) to memory-safe ones (like Rust). Dr. Bjarne Stroustrup, the
original creator of C++, has made some
&lt;a href=&#34;https://developers.slashdot.org/story/23/01/21/0526236/rust-safety-is-not-superior-to-c-bjarne-stroustrup-says&#34;&gt;waves&lt;/a&gt;
with his
&lt;a href=&#34;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2739r0.pdf&#34;&gt;response&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To be honest, I was disappointed. As a current die-hard Rustacean
and former die-hard C++ programmer, I have thought (and
&lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;blogged&lt;/a&gt;) quite a bit about the topic of Rust vs
C++. Unfortunately, I feel that in spite of the exhortation in his title
to &amp;ldquo;think seriously about safety,&amp;rdquo; Dr. Stroustrup was not in fact thinking
seriously himself. Instead of engaging conceptually with the article,
he seems to have reflexively thrown together some talking points &amp;ndash;
some of them very stale &amp;ndash; not realizing that they mostly are not even
relevant to the NSA&amp;rsquo;s Cybersecurity Information Sheet, let alone a
thoughtful rebuttal of it.&lt;/p&gt;
&lt;p&gt;Fortunately, he does eventually discuss his own ideas of how to make C++
memory safe &amp;ndash; in the future. If these ideas are implemented well, it
will make C++ a safe programming language as the NSA&amp;rsquo;s Cybersecurity
Information Sheet has defined it. But given that they are currently
just proposals in an early stage, it&amp;rsquo;s unfair of him to expect the NSA
to mention them when advising people on what programming language to
use. C++ has been an unsafe language for a long time. Maybe someday that
will change, but we&amp;rsquo;ll believe it when we actually see it.&lt;/p&gt;
&lt;p&gt;But before I discuss that, I&amp;rsquo;d like to rebut and discuss my disappointment
at the talking points he uses earlier in his response, because I think
they unfairly frame the debate, shield C++ from legitimate and important
criticism, and slander memory-safe programming languages and downplay
memory safety as a concept, even though it&amp;rsquo;s very important.&lt;/p&gt;
&lt;h1 id=&#34;multiple-types-of-safety&#34;&gt;Multiple Types of Safety?&lt;/h1&gt;
&lt;p&gt;One of the most interesting and conceptually relevant points that
Dr. Stroustrup harps on is that memory safety is not the only
type of safety:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Also, as described, “safe” is limited to memory safety, leaving
out on the order of a dozen other ways that a language could (and will)
be used to violate some form of safety and security.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This might technically be true &amp;ndash; it&amp;rsquo;s not entirely clear what other
forms of &amp;ldquo;safety&amp;rdquo; he&amp;rsquo;s talking about &amp;ndash; but it&amp;rsquo;s misleading. Memory
unsafety is not just one of a dozen equally important
forms of &amp;ldquo;unsafety.&amp;rdquo;  Rather, memory unsafety is by far the
biggest source of security vulnerabilities and instability
in memory unsafe programming languages &amp;ndash; estimates as high as &lt;a href=&#34;https://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/&#34;&gt;70
percent&lt;/a&gt; in some contexts.&lt;/p&gt;
&lt;p&gt;A 70% decrease in security vulnerabilities is worth committing
significant resources towards. Memory safety on its own is worth writing
a Cybersecurity Information Sheet about, and it is the area where C++ has
the most serious deficits. Given that, this feels like a car manufacturer
whose cars do not provide air bags responding to a government advisory
not to buy the C++ cars by saying &amp;ldquo;What about other types of safety?
By talking just about air bags, the government is clearly not thinking
seriously about safety.&amp;rdquo; Sure, there&amp;rsquo;s other types of safety features
besides air bags (or memory safety), but air bags are still important!&lt;/p&gt;
&lt;p&gt;So, Dr. Stroustrup, what about memory safety in C++? Shouldn&amp;rsquo;t C++
have memory safety? Are you saying it&amp;rsquo;s not important, especially when
all of these other programming languages have it?&lt;/p&gt;
&lt;p&gt;Of course, he doesn&amp;rsquo;t go into detail about other types of safety,
which is telling. Of course, it&amp;rsquo;s because C++ doesn&amp;rsquo;t really have the
advantage in any of them. For example, Rust also has a lot of mechanisms
for thread safety and type safety, intimately connected with its memory
safety mechanisms, and baked into the design of Rust in a way that would
be next to impossible to retrofit into another programming language.&lt;/p&gt;
&lt;p&gt;And, when you read later on about the &amp;ldquo;safety profiles&amp;rdquo; in the C++ Core
Guidelines that he makes such a big deal about, most of the focus there
is also about memory safety.&lt;/p&gt;
&lt;h1 id=&#34;petty-irrelevancies&#34;&gt;Petty Irrelevancies&lt;/h1&gt;
&lt;p&gt;Let&amp;rsquo;s look at some of the other points he makes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;That specifically and explicitly excludes C and C++ as unsafe.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C++ does not enforce memory safety as a feature of the programming
language. This may change in the future (as Dr. Stroustrup discusses),
but is the current state of things. Dr. Stroustrup tries to downplay this,
but is not convincing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As is far too common, it lumps C and C++ into the single category C/C++,
ignoring 30+ years of progress.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Writing &amp;ldquo;C/C++&amp;rdquo; to mean &amp;ldquo;C and C++&amp;rdquo; is considered a &lt;em&gt;faux pas&lt;/em&gt; among C++
programmers, and among C programmers as well, because it is seen
as asserting that these two programming languages are near-identical
when there are in fact major differences between them. By pointing out
that the NSA does this, Dr. Stroustrup is trying to make them look
like they don&amp;rsquo;t know what they&amp;rsquo;re talking about, just because they used
a &amp;ldquo;/&amp;rdquo; character instead of the word &amp;ldquo;and.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;He&amp;rsquo;s reading too much into the orthography and the NSA&amp;rsquo;s failure to use
insider &lt;em&gt;shibboleths&lt;/em&gt; of the programming languages they&amp;rsquo;re trying to
criticize. Outside of the &amp;ldquo;C&amp;rdquo; and &amp;ldquo;C++&amp;rdquo; communities, &amp;ldquo;C/C++&amp;rdquo; is a fairly
common way to refer to the two related programming languages.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s the most relevant thing here: C and C++ are indeed related
programming languages, and they have a lot in common: They are both
compiled programming languages with a focus on performance, and they are
(very relevantly) both not particularly focused on guaranteeing memory
safety. C and C++ have a substantial common subset, with many memory
unsafe features that are popular with programmers, perhaps even more
popular because they work similarly in both programming languages. For
the purposes of this document, it&amp;rsquo;s often the features that C and C++
have in common that are the problematic ones, so it makes sense for the
NSA to lump them together.&lt;/p&gt;
&lt;p&gt;While there might be 30+ years of divergence between C and C++, none
of C++&amp;rsquo;s so-called &amp;ldquo;progress&amp;rdquo; involved removing memory-unsafe C features
from C++, many of which are still in common use, and many of which still
make memory safety in C++ near intractible. Sure, new features in C++
have been added that (in some but by no means all cases) do not make it
as easy to corrupt memory, but the bad old features are not in any real
way being phased out: They are not guarded by any special opt-in syntax,
nor in many cases do they result in warnings. Given that, the combined
set of features is as strong as its weakest link.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Unfortunately, much C++ use is also stuck in the distant past, ignoring
improvements, including ways of dramatically improving safety.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a common C++ talking point, but it doesn&amp;rsquo;t help Dr. Stroustrup&amp;rsquo;s
position as much as he thinks it does.&lt;/p&gt;
&lt;p&gt;He&amp;rsquo;s trying to talk up how much C++ has improved, especially in the last
11 years &amp;ndash; and it has indeed improved. New ways of writing C++, emphasizing
relatively new features, can indeed result in more reliable C++ code with
less memory corruption.&lt;/p&gt;
&lt;p&gt;But unfortunately, this talking point just serves to remind us that these
old memory-unsafe features are still in common use. When someone says
their project is written in Rust, we can guess that it likely uses only
the safe features (including using standard library functions that use
&lt;code&gt;unsafe&lt;/code&gt; internally &amp;ndash; that truly doesn&amp;rsquo;t count as unsafe), or maybe
uses the unsafe features when absolutely necessary. But when someone
says their project is written in C++, by Dr. Stroustrup&amp;rsquo;s own admission,
there&amp;rsquo;s a high likelihood that it uses old features &amp;ldquo;stuck in the distant
past, ignoring &amp;hellip; ways of dramatically improving safety.&amp;rdquo; This is also
a reason to avoid C++.&lt;/p&gt;
&lt;p&gt;However, I would also contest his claim about these new features.
Memory safety isn&amp;rsquo;t just an absence of memory corruption, but a reliable
method for ensuring the absence of memory corruption. &amp;ldquo;Using new features&amp;rdquo;
isn&amp;rsquo;t good enough. Even if using the new features in preference to the
old ones were a guarantee of memory safety &amp;ndash; which it isn&amp;rsquo;t, they&amp;rsquo;re
less memory corrupting but not truly memory safe &amp;ndash; the presence of the
old ones would still cause problems. You would need some mechanism to
ensure that the new features were only used safely, and that the old
features were not used, and no such mechanism exists, at least not in
the programming language itself. Someone who remembers the old features
can always still slip up and use one by accident.&lt;/p&gt;
&lt;h1 id=&#34;static-analysis-not-good-enough&#34;&gt;Static Analysis: Not Good Enough&lt;/h1&gt;
&lt;p&gt;Dr. Stroustrup points out that he&amp;rsquo;s been working very hard on improving
memory safety in C++, for a very long time:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After all, I have worked for decades to make it possible to write better,
safer, and more efficient C++. In particular, the work on the C++ Core
Guidelines specifically aims at delivering statically guaranteed type-safe
and resource-safe C++ for people who need that without disrupting code
bases that can manage without such strong guarantees or introducing
additional tool chains.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Unfortunately, it&amp;rsquo;s not done. The key word here is, of course, &amp;ldquo;aims.&amp;rdquo; The
next sentences admit that this feature is not in fact available:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For example, the Microsoft Visual Studio analyzer and its memory-safety
profile deliver much of the CG support today and any good static analyzer
(e.g., Clang tidy, that has some CG support) could be made to completely
deliver those guarantees&amp;hellip;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For memory safety, &amp;ldquo;much of&amp;rdquo; is not really good enough, and &amp;ldquo;could
be made&amp;rdquo; is practically worthless. Fundamentally, the point is that
memory safety in C++ is a project being actively worked on, and close
to existing. Meanwhile, Rust (and Swift, C#, Java, and others) already
implements memory safety.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s worse than that, though. What Dr. Stroustrup is trying to downplay
is that this involves using static analyzers, considered separate from
the programming language, something the NSA&amp;rsquo;s original article also
discusses. Theoretically, if a static analyzer could be used to guarantee
memory safety, that could be just as reliable as a programming language
that does it. An engineering team could have a policy that all code must
pass this static analysis before being put into production.&lt;/p&gt;
&lt;p&gt;But unfortunately, human nature is more fickle than that. If it&amp;rsquo;s not
built into the programming language, it&amp;rsquo;s going to get skipped. If a
vendor says their software is written in C++, or if an engineer takes a
job in C++, how will they know that these static analyzers will in fact
be used? A programming language that takes memory safety seriously doesn&amp;rsquo;t
provide it as an optional add-on that most people will simply ignore.&lt;/p&gt;
&lt;h1 id=&#34;but-all-the-c-code&#34;&gt;But All The C++ Code!&lt;/h1&gt;
&lt;p&gt;The end of the last quote provides a common talking point in Rust vs
C++ arguments:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[Static analyzers] could be made to completely deliver those guarantees
at a fraction of the cost of a change to a variety of novel “safe”
languages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Besides the laughably condescending matter of calling Java (which first
appeared in 1995), C# (first appeared in 2000), and Ruby (first appeared
in 1995) &amp;ldquo;novel,&amp;rdquo; this is a jab at a common trope that (some immature)
Rust programmers go around demanding that people rewrite their projects
in Rust (please don&amp;rsquo;t do this!), and an attack on the idea that all code
can be written in safe programming languages, given the large body of
existing work in unsafe programming languages.&lt;/p&gt;
&lt;p&gt;This is a bit of a straw man in this context. The NSA article that
Stroustrup is responding to addresses that switching existing codebases
might be expensive, even prohibitively so, saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is not trivial to shift a mature software development infrastructure
from one computer language to another. Skilled programmers need to be
trained in a new language and there is an efficiency hit when using a
new language. Programmers must endure a learning curve and work their
way through any “newbie” mistakes. While another approach is to
hire programmers skilled in a memory safe language, they too will have
their own learning curve for understanding the existing code base and
the domain in which the software will function.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It then follows this up immediately with an explanation of how tools
like static analyzers can be used as a back-up plan for improving
memory safety in memory unsafe programming languages &amp;ndash; exactly what
Dr. Stroustrup discusses. He&amp;rsquo;s criticizing this NSA document, implying
it is not thinking &amp;ldquo;seriously,&amp;rdquo; while fundamentally making a point
that they already made for him.&lt;/p&gt;
&lt;p&gt;Of course, this is a terrible endorsement of C++. It&amp;rsquo;s far from ideal
to have to use add-on tools to work around a language&amp;rsquo;s flaws. Coming
from Dr. Stroustrup, it reads more like a brag that his programming
language has locked everyone in than a defense of why C++ is good.
Or else, it&amp;rsquo;s an admission that other programming languages should
be used for new projects, and that C++&amp;rsquo;s fate is now to gradually
fade like the elves from Middle Earth.&lt;/p&gt;
&lt;p&gt;But he&amp;rsquo;s also overstating his case. As I mention before, safe programming
languages have existed for a long time. Many programming projects that
in the early 90&amp;rsquo;s would have been done in C or C++ &lt;em&gt;have&lt;/em&gt; in fact been
done in safe programming languages instead, and according to the NSA&amp;rsquo;s
recommendation, that was a good idea. As computers have gotten faster
and programming language technology has improved, there has been
fewer and fewer reasons to settle for languages like C or C++ that
don&amp;rsquo;t have memory safety as a feature.&lt;/p&gt;
&lt;p&gt;When I was a professional C++ programmer as early as 2013, some people
&amp;ndash; even some programmers &amp;ndash; already thought that C++ was a legacy
programming language like COBOL or Fortran. And outside of narrow
niches like systems programming (e.g. web browsers, operating systems,
and lower-level libraries), video games, or high performance programming,
it kind of has become one.  The former application niches of C++ have
been taken over by Java and C#, or more recently by Go.  If you have an
application program written in C++, chances are that it&amp;rsquo;s a relatively
old codebase, or written at a shop that has reasons to write a lot of C++
(such as a high-frequency trading firm).&lt;/p&gt;
&lt;p&gt;Now, even C++&amp;rsquo;s systems niche is under threat, with Rust, a powerful
memory-safe programming language that avoids many of C++&amp;rsquo;s problems. Now,
even the niches where C++ isn&amp;rsquo;t at all &amp;ldquo;legacy&amp;rdquo; have a viable, memory-safe
alternative without a lot of the technical debt that C++ has.  Rust is
even allowed in the Linux kernel, a project that has only previously
accepted C, and whose chief maintainer has always &lt;a href=&#34;http://harmful.cat-v.org/software/c++/linus&#34;&gt;explicitly hated
C++&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;a-memory-safe-c&#34;&gt;A Memory-Safe C++&lt;/h1&gt;
&lt;p&gt;Fortunately, after all of these ill-thought out, tired talking points,
Dr. Stroustrup subtly changes his perspective. After his distractions,
after bashing memory safe programming languages as &amp;ldquo;novel,&amp;rdquo; bragging about
how C++ is too entrenched to be removable, pretending memory safety is
just one of many equally important safety issues, and promising optional
add-on tools that will eventually be standardized, he finally begins to
tackle the question of how C++ could be made memory safe, in an opt-in
fashion:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There is not just one definition of “safety”, and we can achieve a
variety of kinds of safety through a combination of programming styles,
support libraries, and enforcement through static analysis. P2410r0
gives a brief summary of the approach. I envision compiler options
and code annotations for requesting rules to be enforced. The most
obvious would be to request guaranteed full type-and-resource safety.
P2687R0 is a start on how the standard can support this, R1 will be more
specific. Naturally, comments and suggestions are most welcome.&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;For example, in application domains where performance is the main
concern, the P2687R0 approach lets you apply the safety guarantees
only where required and use your favorite tuning techniques where
needed. Partial adoption of some of the rules (e.g., rules for
range checking and initialization) is likely to be important. Gradual
adoption of safety rules and adoption of differing safety rules will be
important. If for no other reason than the billions of lines of C++ code
will not magically disappear, and even “safe” code (in any language)
will have to call traditional C or C++ code or be called by traditional
code that does not offer specific safety guarantees.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a lot closer to what the NSA document actually specifies for
memory safe programming languages than he gives the document credit
for. For example, the document already provides for opting out of memory
safety via annotation, paired with an observation that that will
focus scrutiny on the code that opts out.&lt;/p&gt;
&lt;p&gt;Dr. Stroustrup did not need to criticize the document for not thinking
&amp;ldquo;seriously&amp;rdquo; to reach this conclusion, but simply acknowledge that it&amp;rsquo;s
true that C++ is not a memory safe programming language yet, but that
based on his work, it might soon become one. Maybe the next version
of the NSA document will endorse using C++, but only if it&amp;rsquo;s C++&lt;em&gt;ZZ&lt;/em&gt; &amp;ndash;
where &lt;em&gt;ZZ&lt;/em&gt; is some future version of the C++ standard.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m glad comments and suggestions are welcome, however, because
I have a huge one.&lt;/p&gt;
&lt;p&gt;Opt-in for memory safety is unacceptable, and is almost as bad as having
a separate static analysis tool to enforce safety. Opt-out is fine &amp;ndash;
Rust has a way to opt out of memory safety with the &lt;code&gt;unsafe&lt;/code&gt; keyword, and
this concept is discussed and defended in the NSA&amp;rsquo;s original document. But
the default should be to enforce memory safety unless otherwise specified.&lt;/p&gt;
&lt;p&gt;For C++, this means that if these safety features are added in C++&lt;em&gt;ZZ&lt;/em&gt;,
&lt;code&gt;--std=c++ZZ&lt;/code&gt; should cause unsafe constructs to be rejected &amp;ndash; and the
C++ standard should require that these constructs be rejected for an
implementation to be a conforming implementation of C++&lt;em&gt;ZZ&lt;/em&gt;.  Perhaps (but
only perhaps) other command line arguments could be added to override
this constraint on a file-by-file basis. Ideally, a new compiler command
(e.g. &lt;code&gt;g++ZZ&lt;/code&gt;) should be created for each implementation that defaults
to this stricter behavior.&lt;/p&gt;
&lt;p&gt;Parts of the codebase that use legacy features should have to
have at least a file-level annotation that that file is a legacy file &amp;ndash;
and then this annotation could gradually be moved to the function level.
As a side benefit, this could also be used to phase out and deprecate
weird points of C++ syntax, similar to the Rust edition system: Anyone
using, for example, 0 literals to mean &lt;code&gt;nullptr&lt;/code&gt; would have to declare
some sort of a legacy annotation on their file or in their build system.&lt;/p&gt;
&lt;p&gt;Only with this sort of opt-out memory-safety system would I consider
C++ a memory safe programming language. I&amp;rsquo;d be very happy to see a
memory-safe C++. I earnestly hope Dr. Stroustrup is successful in his
endeavors. I&amp;rsquo;m not holding my breath, though, and in the meantime,
I will continue to use other programming languages, that are already
memory-safe, for my new projects, as will the majority of programmers.&lt;/p&gt;
&lt;p&gt;In the meantime, it is unfair for Dr. Stroustrup to call safe programming
languages novelties or to pretend that C++ isn&amp;rsquo;t already far behind the
times on this. This was already an important criticism of C++ decades ago,
when Java first came out in the 90&amp;rsquo;s and was referred to as a &amp;ldquo;managed
programming language.&amp;rdquo;  This was discussed in detail in my classes when
I was a college student in the late aughts. To read Dr. Stroustrup&amp;rsquo;s writing,
C++ is being criticized by &amp;ldquo;novel&amp;rdquo; upstarts when it is well on its way to
getting the feature, but in actuality, the time to act was 1996.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Rust and Default Parameters</title>
      <link href="https://www.thecodedmessage.com/posts/default-params/" />
      <id>https://www.thecodedmessage.com/posts/default-params/</id>
      <updated>2023-01-11T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Rust doesn&amp;rsquo;t support default parameters in function signatures.
And unlike in many languages, there&amp;rsquo;s no way to simulate them
with function overloading. This is frustrating for many new Rustaceans
coming from other programming languages, so I want to explain
why this is actually a good thing, and how to use the &lt;a href=&#34;https://doc.rust-lang.org/std/default/trait.Default.html&#34;&gt;&lt;code&gt;Default&lt;/code&gt;
trait&lt;/a&gt;
and &lt;a href=&#34;https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax&#34;&gt;struct update
syntax&lt;/a&gt;
to achieve similar results.&lt;/p&gt;
&lt;p&gt;Default parameters (and function overloading) are not part of
object-oriented programming, but they are a common feature of a lot
of the programming languages new Rustaceans are coming from. This
post therefore fits in some ways with my &lt;a href=&#34;https://www.thecodedmessage.com/tags/beyond-oop/&#34;&gt;on-going series on how Rust
is not object-oriented&lt;/a&gt;, and so it is tagged with
that series.  It was also inspired by Reddit responses to &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation&#34;&gt;my first OOP
post&lt;/a&gt;.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Rust doesn&amp;rsquo;t support default parameters in function signatures.
And unlike in many languages, there&amp;rsquo;s no way to simulate them
with function overloading. This is frustrating for many new Rustaceans
coming from other programming languages, so I want to explain
why this is actually a good thing, and how to use the &lt;a href=&#34;https://doc.rust-lang.org/std/default/trait.Default.html&#34;&gt;&lt;code&gt;Default&lt;/code&gt;
trait&lt;/a&gt;
and &lt;a href=&#34;https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax&#34;&gt;struct update
syntax&lt;/a&gt;
to achieve similar results.&lt;/p&gt;
&lt;p&gt;Default parameters (and function overloading) are not part of
object-oriented programming, but they are a common feature of a lot
of the programming languages new Rustaceans are coming from. This
post therefore fits in some ways with my &lt;a href=&#34;https://www.thecodedmessage.com/tags/beyond-oop/&#34;&gt;on-going series on how Rust
is not object-oriented&lt;/a&gt;, and so it is tagged with
that series.  It was also inspired by Reddit responses to &lt;a href=&#34;https://www.thecodedmessage.com/posts/oop-1-encapsulation&#34;&gt;my first OOP
post&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;how-default-parameters-work-in-eg-c&#34;&gt;How Default Parameters Work (in e.g. C++)&lt;/h1&gt;
&lt;p&gt;So before I talk about why Rust doesn&amp;rsquo;t have default parameters
and what you can do instead, let&amp;rsquo;s talk a bit about what default
parameters are and the situations in which they are useful.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say you have a function that takes many parameters, perhaps
(to take an example from the Reddit response) one that creates a window
in a GUI:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WindowHandle &lt;span style=&#34;color:#a6e22e&#34;&gt;createWindow&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; width, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; height, &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; visible)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;auto&lt;/span&gt; handle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;, false); &lt;span style=&#34;color:#75715e&#34;&gt;// Create invisible window
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;auto&lt;/span&gt; handle2 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;, true); &lt;span style=&#34;color:#75715e&#34;&gt;// Create visible window
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, let&amp;rsquo;s say that you assume that most windows that are created
are intended to be visible, and you don&amp;rsquo;t want to burden the programmer
with having to specify whether the window is visible &amp;ndash; or even think
about it explicitly &amp;ndash; in that normal case. In a programming language
that supported default parameters, you could then provide
a default for &lt;code&gt;visible&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WindowHandle &lt;span style=&#34;color:#a6e22e&#34;&gt;createWindow&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; width, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; height, &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; visible &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;auto&lt;/span&gt; handle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;, false); &lt;span style=&#34;color:#75715e&#34;&gt;// Create invisible window!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;auto&lt;/span&gt; handle2 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;, true); &lt;span style=&#34;color:#75715e&#34;&gt;// Create visible window!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;auto&lt;/span&gt; handle3 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// Also create visible window!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;auto&lt;/span&gt; handle4 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// Most of the time, that&amp;#39;s what
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;auto&lt;/span&gt; handle5 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// you want, so why have to say it?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Default parameters can also be simulated with function overloading
for programming languages where function overloading is available
but default parameters are not:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WindowHandle &lt;span style=&#34;color:#a6e22e&#34;&gt;createWindow&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; width, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; height, &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; visible);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WindowHandle &lt;span style=&#34;color:#a6e22e&#34;&gt;createWindow&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; width, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; height) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; createWindow(width, height, true);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rust also does not have function overloading, and that&amp;rsquo;s a much more
complicated issue, but many of the same arguments apply to this idiom.&lt;/p&gt;
&lt;h2 id=&#34;benefits-and-detriments-of-default-parameters&#34;&gt;Benefits (and Detriments) of Default Parameters&lt;/h2&gt;
&lt;p&gt;Defaults are good, and default parameters in this style are
one way to implement them and reap their benefits.&lt;/p&gt;
&lt;p&gt;Defaults are good because they uphold the DRY principle &amp;ndash; Don&amp;rsquo;t Repeat
Yourself. If we didn&amp;rsquo;t have defaults, we&amp;rsquo;d have to repeat parameters
that don&amp;rsquo;t actually contribute to understanding of the goals of the code.
And if the best default parameters changed in such a way that the best way
to update the code was to continue using the default &amp;ndash; perhaps because
of a change of best practices &amp;ndash; we&amp;rsquo;d have to update every call rather
than just changing it once, where the default parameter is defined.&lt;/p&gt;
&lt;p&gt;Defaults are also good because they decrease the programmer&amp;rsquo;s cognitive
load. Programmers have to keep a lot of information in their brain at
a time, and defaults help programmers by not forcing them to think about
extra details when they don&amp;rsquo;t matter &amp;ndash; which is the usual situation for
most defaults.&lt;/p&gt;
&lt;p&gt;Default parameters also make the code more concise, and are popular for
that reason. But this isn&amp;rsquo;t a particular value that I have. I believe
the DRY principle is important, and that often amounts to more concise
code, but given modern editors and IDE, and modern expectations of typing
and reading speed, a moderate amount of verbosity in exchange for other
benefits (such as clarity and explicitness) is completely acceptable to me.
I believe that default parameters, as they are implemented in C++ and Python,
have a substantial cost in clarity and explicitness, and therefore conciseness
isn&amp;rsquo;t a good enough reason to justify them.&lt;/p&gt;
&lt;p&gt;In this case, what particularly bothers me about the lack of clarity
is that the reader of the code doesn&amp;rsquo;t know that there are potentially
more parameters; there is no hint that there might be other parameters.
If a maintenance programmer wants to change one of these calls to make
invisible windows instead, they might not realize they should check the
documentation for &lt;code&gt;create_window&lt;/code&gt;: after all, it only seems to take
two parameters, and neither of them have anything remotely to do with
invisible windows.&lt;/p&gt;
&lt;p&gt;Fortunately, Rust has alternative features that allow us to reap the
benefits for cognitive load and DRY without sacrificing explicitness
and clarity.&lt;/p&gt;
&lt;h1 id=&#34;defaults-in-rust-the-default-trait&#34;&gt;Defaults in Rust: the &lt;code&gt;Default&lt;/code&gt; trait&lt;/h1&gt;
&lt;p&gt;Rather than allowing default parameters, Rust allows you to optionally
specify default values for your types using the &lt;a href=&#34;https://doc.rust-lang.org/std/default/trait.Default.html&#34;&gt;&lt;code&gt;Default&lt;/code&gt;
trait&lt;/a&gt;. Here&amp;rsquo;s
how it works:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Bar,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Baz,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; Default &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; Foo {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;default&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Foo::Bar
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or, written using the more concise &lt;code&gt;derive&lt;/code&gt; syntax:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[derive(Default)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Foo&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#[default]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Bar,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Baz,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once this default is defined, &lt;code&gt;Foo::default()&lt;/code&gt; or even (in a context
where the type is clear) &lt;code&gt;Default::default()&lt;/code&gt; can stand in for &lt;code&gt;Foo::Bar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you are used to re-using existing types for your function
parameters, this might seem worse than useless. After
all, the parameter we defaulted was of type &lt;code&gt;bool&lt;/code&gt;,
and the orphan rule (explained in the Rust book&amp;rsquo;s &lt;a href=&#34;https://doc.rust-lang.org/book/ch10-02-traits.html#implementing-a-trait-on-a-type&#34;&gt;chapter on
traits&lt;/a&gt;)
forbids us from defining the &lt;code&gt;Default&lt;/code&gt; trait on &lt;code&gt;bool&lt;/code&gt; &amp;ndash; as I alluded
to above, &lt;code&gt;Default&lt;/code&gt; allows you to define default values for &lt;em&gt;your&lt;/em&gt; types.
And even if we could, setting a default on booleans is way too overpowered
a thing to do just to give this one function parameter have a default!
After all, some other function might also have a boolean parameter with
a different default.&lt;/p&gt;
&lt;p&gt;But this makes more sense if you consider that in Rust, it is common &amp;ndash;
even idiomatic and preferred &amp;ndash; to create custom types for things like
configuration and function parameters.  After all, if you&amp;rsquo;re not looking
at the documentation, it can be unclear what &lt;code&gt;true&lt;/code&gt; means. It&amp;rsquo;s not even
clear that it has anything to do with visibility, let alone that &lt;code&gt;true&lt;/code&gt;
means that the window is to be visible when the parameter could just as
easily be called &lt;code&gt;invisible&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In Rust, we would prefer to define a new type for this situation, an
&lt;code&gt;enum&lt;/code&gt; listing the visibility options &amp;ndash; which will also help if a new
visibility option is created. And on this &lt;code&gt;enum&lt;/code&gt;, it would be reasonable
to declare a default:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#[derive(Default)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;WindowVisibility&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;#[default]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Visible,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Invisible,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes, this is more verbosity, but it is more clear, and no less DRY, than
our original code. Conciseness is again not a value in and of itself.
Explicitly listing the options is preferred to leaving them implicit.&lt;/p&gt;
&lt;p&gt;Then, when we call the function, we can use this default:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;create_window&lt;/span&gt;(width: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;, height: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;, visibility: &lt;span style=&#34;color:#a6e22e&#34;&gt;WindowVisibility&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;WindowHandle&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; create_window(&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;, WindowVisibility::Invisible);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle2 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; create_window(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;, WindowVisibility::Visible);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle3 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; create_window(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;, WindowVisibility::default());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle4 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; create_window(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;, WindowVisibility::default());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle5 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; create_window(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;, Default::default()); &lt;span style=&#34;color:#75715e&#34;&gt;// Also permitted
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is, as promised, more verbose, but equally DRY, and much more explicit
and clear.&lt;/p&gt;
&lt;p&gt;NB: I&amp;rsquo;m using free-standing functions for example purposes
only. In reality, this particular function is just as likely to be part
of a type&amp;rsquo;s intrinsic methods, something like &lt;code&gt;WindowHandle::new&lt;/code&gt; or
&lt;code&gt;WindowHandle::create_window&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;scaling-defaults-in-rust-struct-update-syntax&#34;&gt;Scaling defaults in Rust: Struct update syntax&lt;/h2&gt;
&lt;p&gt;So this is all well and good for one default. But it doesn&amp;rsquo;t
scale that well. What if we want to add another 3 parameters to our
window creation function? In a language like C++, we can give them
defaults, and the callers don&amp;rsquo;t even need to be updated
(parameters are for example purposes only and do not represent
a well-thought out list of what you might want to specify in creating
a window):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WindowHandle &lt;span style=&#34;color:#a6e22e&#34;&gt;createWindow&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; width, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; height, &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; visible &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; true,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          WindowStyle windowStyle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; WindowStyle&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;Standard,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; z_position &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; autoclose &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; false);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// Still works identically
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;, false); &lt;span style=&#34;color:#75715e&#34;&gt;// Also still works
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;createWindow(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;, false, WindowStyle&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;Standard, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, true); &lt;span style=&#34;color:#75715e&#34;&gt;// Specify everything
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a useful feature. In Rust, with the techniques we&amp;rsquo;ve discussed
so far, we&amp;rsquo;d have to write &lt;code&gt;Default::default()&lt;/code&gt; repeatedly for however
many parameters there are. This is a DRY violation, and interferes with
the ability to add new parameters.&lt;/p&gt;
&lt;p&gt;There is a flaw with this feature, however.  You&amp;rsquo;ve now constrained
yourself to specifying parameters to the left in order to specify
parameters on the right. In the last example call to &lt;code&gt;createWindow&lt;/code&gt;, we
violate DRY by explicitly specifying a value when we probably wanted to
use the default, but that wasn&amp;rsquo;t available because we wanted to override
the default for a later parameter.&lt;/p&gt;
&lt;p&gt;Fortunately, Rust has a version of this too. Just as we created an
&lt;code&gt;enum&lt;/code&gt; just for the purposes of this function call, it is idiomatic
in Rust to create structures for configuration parameters like this.
The structure would look something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;WindowConfig&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; width: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; height: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; visibility: &lt;span style=&#34;color:#a6e22e&#34;&gt;WindowVisibility&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; window_style: &lt;span style=&#34;color:#a6e22e&#34;&gt;WindowStyle&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; z_position: &lt;span style=&#34;color:#66d9ef&#34;&gt;i32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; autoclose: &lt;span style=&#34;color:#a6e22e&#34;&gt;AutoclosePolicy&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, we can implement &lt;code&gt;Default&lt;/code&gt; for that entire &lt;code&gt;struct&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; Default &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; WindowConfig {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;default&lt;/span&gt;() -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Self {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            width: &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            height: &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            visibility: &lt;span style=&#34;color:#a6e22e&#34;&gt;WindowVisibility&lt;/span&gt;::Visible,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            window_style: &lt;span style=&#34;color:#a6e22e&#34;&gt;WindowStyle&lt;/span&gt;::Standard,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            z_position: &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            autoclose: &lt;span style=&#34;color:#a6e22e&#34;&gt;AutoclosePolicy&lt;/span&gt;::Disable,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, this might seem to be extremely tedious to use. You might imagine
using it something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; config &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; WindowConfig::default();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;config.width &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;config.z_position &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;config.autoclose &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; AutoclosePolicy::Enable;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; create_window(config);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I would argue that even this is preferable to default parameters,
because again, it is explicit. However, Rust has a syntactic construct
designed exactly for situations like this, &lt;a href=&#34;https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax&#34;&gt;struct update
syntax&lt;/a&gt;.
With it, we get something very similar to default parameters, but
a little more verbose, a lot more explicit, and a lot more flexible:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; create_window(WindowConfig {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    width: &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    z_position: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    autoclose: &lt;span style=&#34;color:#a6e22e&#34;&gt;AutoclosePolicy&lt;/span&gt;::Enable,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;Default::default()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unlike C++-style default parameters, we can override exactly the
defaults we want to. It is also explicitly clear that there are
other parameters we could modify if we wanted to, without forcing
the maintenance programmer to check the documentation.&lt;/p&gt;
&lt;p&gt;But beyond that, this allows there to be other sets of defaults
defined. In addition to &lt;code&gt;WindowConfig::default&lt;/code&gt;, there might be
another set of configuration parameters for creating dialog boxes,
like &lt;code&gt;WindowConfig::dialog()&lt;/code&gt; or &lt;code&gt;WindowConfig::default_dialog&lt;/code&gt;.
An app where the programmer usually creates invisible windows, or
windows all of the same height, might define its own default set,
&lt;code&gt;config::app_local_default_window_config()&lt;/code&gt;. These wouldn&amp;rsquo;t be mediated
through the &lt;code&gt;Default&lt;/code&gt; trait, but &lt;code&gt;Default&lt;/code&gt; is just a trait, and
&lt;code&gt;Default::default()&lt;/code&gt; is just a method call. You can call your own
methods instead, and still use this struct update syntax.&lt;/p&gt;
&lt;p&gt;So now, we have a system of idioms in Rust to replace default parameters.
It&amp;rsquo;s just as DRY, and decreases the cognitive load just as much. More
importantly, it does so without sacrificing explicitness and clarity as to
exactly what&amp;rsquo;s going on &amp;ndash; a given function always takes the same number
of parameters, which is an invariant that Rust maintenance programmers
can (and do) rely on.&lt;/p&gt;
&lt;h2 id=&#34;the-builder-pattern&#34;&gt;The Builder Pattern&lt;/h2&gt;
&lt;p&gt;At this point, the old-hand Rustaceans in the audience will
note that I haven&amp;rsquo;t discussed one common Rust approach
to designing these configuration structs, &lt;a href=&#34;https://rust-unofficial.github.io/patterns/patterns/creational/builder.html&#34;&gt;the builder
pattern&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s for a reason: I don&amp;rsquo;t like it. I personally prefer to use
&lt;code&gt;Default&lt;/code&gt; and struct update syntax where others might reach for
the builder pattern. I think it&amp;rsquo;s less explicit, and since I
have a lot of experience in non-OOP programming languages,
it feels to me like a solution without a problem, the primary
upshot of which is to make the code look more object-oriented.&lt;/p&gt;
&lt;p&gt;But it is a commonly used pattern in Rust, and you will use crates
that use the builder pattern, so it&amp;rsquo;s worth being familiar with it.
It&amp;rsquo;s the same concept as before: using a struct full of parameters
to send configuration to a constructor or to a function call.
It&amp;rsquo;s probably going to be called something like &lt;code&gt;WindowBuilder&lt;/code&gt;
instead of &lt;code&gt;WindowConfig&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, instead of using the struct update syntax directly,
a bunch of helper methods are added to do the
struct update:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; WindowBuilder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;height&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self, height: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.height &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; height;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or, as I would notate it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; WindowBuilder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;height&lt;/span&gt;(self, height: &lt;span style=&#34;color:#66d9ef&#34;&gt;u32&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Self {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            height,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;..&lt;/span&gt;self
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sometimes, enumerations are split into multiple update methods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; WindowBuilder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;autoclose_enable&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.autoclose &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; AutoclosePolicy::Enable;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;autoclose_disable&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;mut&lt;/span&gt; self) -&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Self&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.autoclose &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; AutoclosePolicy::Disable;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, normally, instead of calling e.g. the window constructor, you call
a &lt;code&gt;build&lt;/code&gt; method defined on the builder (and at this point I cringe
at the gratuitous OOP philosophy influencing the design):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;impl&lt;/span&gt; WindowBuilder {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;(self) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        window_create(self)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, instead of using struct update syntax, you chain together
calls to these methods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; handle &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; WindowBuilder::new()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .width(&lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .z_position(&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .autoclose_enable()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    .build();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I still prefer this to default parameters, but I also find it tacky.
I don&amp;rsquo;t like being forced to think in terms of abstract &amp;ldquo;objects&amp;rdquo; like
builders, and I don&amp;rsquo;t like the presumption that this style is more
intuitive. Why is a &amp;ldquo;builder&amp;rdquo; an object that does something? Why is
that prefered to a structure that is &amp;ldquo;configuration&amp;rdquo;? Are OOP programmers
aware that in real life, the vast majority of objects literally don&amp;rsquo;t do
things, and certainly don&amp;rsquo;t build other objects?&lt;/p&gt;
&lt;p&gt;But for people familiar with the idioms of object-oriented programming,
this might be preferable. It is a commonly chosen option, so it&amp;rsquo;s important
at least to recognize it.&lt;/p&gt;
&lt;h1 id=&#34;conclusion-and-application&#34;&gt;Conclusion and Application&lt;/h1&gt;
&lt;p&gt;Rust has a lot of idioms that are different from those in other
programming languages. I often see proposals from new Rustaceans
to add default parameters &amp;ndash; and other similar features &amp;ndash; to Rust,
and these new Rustaceans are confused that the strong demand they
feel is not as widely felt in the greater Rust community.&lt;/p&gt;
&lt;p&gt;And normally, it&amp;rsquo;s similar to this situation with default parameters.
There are alternative idioms that accomplish the same goals, to the
extent that those goals are in line with Rust&amp;rsquo;s values: in this case,
DRYness, and reducing developers&amp;rsquo; cognitive loads. They are also better
solutions in some other ways, according to Rusty values: the additional
explicitness is worth a little more verbosity.&lt;/p&gt;
&lt;p&gt;But often, the new Rustaceans making these proposals are unaware of
the Rusty way of doing things. And if they are aware of it, they
are approaching it from the goals of other programming languages,
and don&amp;rsquo;t see how the solution measures up.&lt;/p&gt;
&lt;p&gt;So I hope this can serve as a case study to help people understand
that there often are Rusty ways of accomplishing the goals of
popular features from OOP land, and why Rustaceans prefer these
solutions to blind accumulation of features.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Rust Is Beyond Object-Oriented, Part 1: Intro and Encapsulation</title>
      <link href="https://www.thecodedmessage.com/posts/oop-1-encapsulation/" />
      <id>https://www.thecodedmessage.com/posts/oop-1-encapsulation/</id>
      <updated>2022-12-12T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Rust is not an object oriented programming language.&lt;/p&gt;
&lt;p&gt;Rust may look like an object-oriented programming language: Types can be
associated with &amp;ldquo;methods,&amp;rdquo; either &amp;ldquo;intrinsic&amp;rdquo; or through &amp;ldquo;traits.&amp;rdquo; Methods
can often be invoked with C++ or Java-style OOP syntax: &lt;code&gt;map.insert(key, value)&lt;/code&gt; or &lt;code&gt;foo.clone()&lt;/code&gt;. Just like in an OOP language, this syntax
involves a &amp;ldquo;receiver&amp;rdquo; argument placed before a &lt;code&gt;.&lt;/code&gt; in the caller,
called &lt;code&gt;self&lt;/code&gt; in the callee.&lt;/p&gt;
&lt;p&gt;But make no mistake: Though it may borrow some of the trappings, some of
the terminology and syntax, Rust is not an object-oriented programming
language. There are three pillars of object-oriented programming:
encapsulation, polymorphism, and inheritance. Of these, Rust nixes
inheritance entirely, so it can never be a &amp;ldquo;true&amp;rdquo; object-oriented
programming language. But even for encapsulation and polymorphism,
Rust implements them differently than OOP languages do &amp;ndash; which we
will go into in more detail later.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Rust is not an object oriented programming language.&lt;/p&gt;
&lt;p&gt;Rust may look like an object-oriented programming language: Types can be
associated with &amp;ldquo;methods,&amp;rdquo; either &amp;ldquo;intrinsic&amp;rdquo; or through &amp;ldquo;traits.&amp;rdquo; Methods
can often be invoked with C++ or Java-style OOP syntax: &lt;code&gt;map.insert(key, value)&lt;/code&gt; or &lt;code&gt;foo.clone()&lt;/code&gt;. Just like in an OOP language, this syntax
involves a &amp;ldquo;receiver&amp;rdquo; argument placed before a &lt;code&gt;.&lt;/code&gt; in the caller,
called &lt;code&gt;self&lt;/code&gt; in the callee.&lt;/p&gt;
&lt;p&gt;But make no mistake: Though it may borrow some of the trappings, some of
the terminology and syntax, Rust is not an object-oriented programming
language. There are three pillars of object-oriented programming:
encapsulation, polymorphism, and inheritance. Of these, Rust nixes
inheritance entirely, so it can never be a &amp;ldquo;true&amp;rdquo; object-oriented
programming language. But even for encapsulation and polymorphism,
Rust implements them differently than OOP languages do &amp;ndash; which we
will go into in more detail later.&lt;/p&gt;
&lt;p&gt;This all comes as a surprise and an adjustment to a lot of programmers. I
see Rust newbies on Reddit asking how to implement OOP design patterns
literally, trying to get &amp;ldquo;class hierarchies&amp;rdquo; like &amp;ldquo;shapes&amp;rdquo; or &amp;ldquo;vehicles&amp;rdquo;
working with traits standing in as &amp;ldquo;the Rust version of inheritance&amp;rdquo; &amp;ndash;
in other words, trying to solve problems they only have because they&amp;rsquo;re
committed to the OOP approach, and doing contrived OOP examples to try
to learn what they expect to be just another version of it.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a stumbling block for many. I regularly see &amp;ldquo;lack of OOP&amp;rdquo; mentioned
on the Internet by Rust newbies and sceptics as a reason Rust is hard to
adjust to, or not a good fit for them, or even why it will never catch
on. For people who learned to program in the height of OOP as a trend &amp;ndash;
when perfectly good languages like C and ML had to become object-oriented
as Objective-C and OCaML &amp;ndash; the amount of hype about a non-OOP language
just feels off.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not an easy adjustment either. So many programmers learned
software design and architecture in an explicitly object-oriented
way. I see question after question where a beginning or intermediate
Rust programmer wants to do an object-oriented thing, and want
a literal Rust equivalent. Often, these are examples of the &lt;a href=&#34;https://xyproblem.info/&#34;&gt;XY
problem&lt;/a&gt;, and they have trouble backtracking
and approaching the problem in a more Rusty way.&lt;/p&gt;
&lt;p&gt;But that isn&amp;rsquo;t Rust&amp;rsquo;s fault. The answer is still for us to adjust, even
if it isn&amp;rsquo;t easy; being proficient in not only multiple languages but
also different programming paradigms makes us better programmers.&lt;/p&gt;
&lt;p&gt;And, as a paradigm, OOP is actually thoroughly mediocre &amp;ndash; so much
so that I&amp;rsquo;m writing a whole blog series to explain why, and why
Rust&amp;rsquo;s approach is better.&lt;/p&gt;
&lt;h1 id=&#34;oop-ideology&#34;&gt;OOP Ideology&lt;/h1&gt;
&lt;p&gt;Look, I get it. I used to drink the OOP Kool-Aid myself. I
remember how it was billed to us: not as just a set of code
organization practices, but a revolution in programming. The OOP
way was held up as more intuitive, especially to non-programmers,
because it would align better with how we think of the
natural world.&lt;/p&gt;
&lt;p&gt;For an archetypical example of this marketing, here is an
excerpt from the first public article about OOP in a popular
magazine (&lt;em&gt;Byte Magazine&lt;/em&gt;, in 1981):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Many people who have no idea how a computer works find the idea of
object-oriented programming quite natural. In contrast, many people
who have experience with computers initially think there is something
strange about object oriented systems.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It was pretty easy to buy into, as well. Of course, our everyday life
doesn&amp;rsquo;t have anything like subroutines or variables &amp;ndash; or, to the
extent that it does, we don&amp;rsquo;t think about them explicitly! But
it does have objects that we can interact with, each with its
own capabilities. How could it not be more intuitive?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s very compelling pseudo-cognitive science, light on research, heavy on
really persuasive rationales. The objects can be thought of as &amp;ldquo;agents,&amp;rdquo;
almost as people, and so you could leverage your social skills towards it
instead of just analytical thinking (never mind that objects act
nothing like people, and actually substantially dumber in a way that
still requires analytical thinking). Or, you can think of objects and
classes as an almost-platonic representation of the world of forms itself,
making it philosophically compelling.&lt;/p&gt;
&lt;p&gt;And oh, how I bought in, especially in my wanton and reckless youth. I
personally soaked up the connection between OOP and Platonic philosophy. I
delved deep into meta-object protocols, and the fact that in Smalltalk
every class had to have a metaclass. The concept of the Smalltalk code
&lt;code&gt;Metaclass class&lt;/code&gt; felt almost mystical to me, as the notion that any
value could be organized in the same hierarchy, with &lt;code&gt;Object&lt;/code&gt; at its root.&lt;/p&gt;
&lt;p&gt;I remember reading in a book that OOP-style polymorphism made &lt;code&gt;if&lt;/code&gt;-&lt;code&gt;else&lt;/code&gt;
statements redundant, and therefore we should strive to ultimately only
use OOP-style polymorphism. Somehow, instead of putting me off, this
excited me at the time. I was even more excited when I learned
that Smalltalk in fact does this (if you ignored implementation details
that optimize away some of this abstraction): In Smalltalk, the concept of
&lt;code&gt;if&lt;/code&gt;-&lt;code&gt;then&lt;/code&gt;-&lt;code&gt;else&lt;/code&gt; is implemented via methods like &lt;code&gt;ifTrue:&lt;/code&gt; and &lt;code&gt;ifFalse:&lt;/code&gt;
and &lt;code&gt;ifTrue:ifFalse:&lt;/code&gt; on the single-instance &lt;code&gt;True&lt;/code&gt; and &lt;code&gt;False&lt;/code&gt; classes,
with their global objects, &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As a more mature programmer, exposed to the less ideological OOP of C++
and the alternative of functional programming in Haskell, my positions
softened, and then shifted dramatically, and now I am barely a fan
of OOP at all, especially as its best ideas have been carried on to
a newer synthesis in Haskell and Rust. I&amp;rsquo;ve realized that this hype
about new programmers is typical for any paradigm; any new programming
paradigm is more intuitive for a newbie than it is for someone who&amp;rsquo;s a
veteran programmer in a different paradigm. The same thing is said for
functional programming. The same thing is even said for Rust. It really
doesn&amp;rsquo;t have that much to do with whether a paradigm is better.&lt;/p&gt;
&lt;p&gt;As for &lt;code&gt;if&lt;/code&gt; statements being fully replaceable by polymorphism, well,
it&amp;rsquo;s easy to come up with a set of primitives that are Turing-complete.
You can simulate if statements with polymorphism, true. You can also
simulate while loops with recursion, or recursion with while loops
and an explicit stack. You can simulate if statements with while loops.&lt;/p&gt;
&lt;p&gt;None of these facts make such substitutions a good idea. Different
features exist in a programming language for different situations,
and making them distinct is actually a good thing, in moderation.&lt;/p&gt;
&lt;p&gt;After all, the point of programming is to write programs, not to make
proofs about Turing-completeness, do philosophy, or write conceptual
poetry.&lt;/p&gt;
&lt;h1 id=&#34;practicality&#34;&gt;Practicality&lt;/h1&gt;
&lt;p&gt;So, in this blog series, I intend to evaluate OOP in practical terms,
as a programmer with experience in what makes programming languages
cognitively more manageable or easy to do abstraction in. I will do it
in terms of my experience solving actual programming problems &amp;ndash; I see
it as a bad sign that many examples of how OOP abstractions work only
make sense in really advanced programs or with contrived examples about
different types of shapes or animals in a zoo.&lt;/p&gt;
&lt;p&gt;And unlike most introductions to OOP, I will not primarily be focusing
on how OOP compares to pre-OOP programming languages. I will instead
be comparing to Rust, which takes many of the good ideas from OOP,
and perhaps also to functional programming languages like Haskell. These
programming languages have taken some of OOP&amp;rsquo;s good ideas, but transformed
them in a way that fixes some of their flaws and moves them beyond what
can reasonably be called OOP.&lt;/p&gt;
&lt;p&gt;I will organize this comparison according to the three traditional
pillars of object-oriented programming: encapsulation, polymorphism,
and inheritance, with this first article focusing on encapsulation. For
each pillar, I will discuss how OOP defines it, what equivalents or
substitutes exist outside of the OOP world, and how these compare for
practical ease and power of programming.&lt;/p&gt;
&lt;p&gt;But before I jump in, I want to talk a second about a use case that turns
much of this on its head: graphical user interfaces or GUIs. Especially
before the era of the browser, writing GUI programs to run directly on
desktop (or laptop) computers was a huge part of what programmers did. A
lot of early development of OOP was done in tandem with research into
graphical user interfaces at Xerox PARC, and OOP is uniquely well-suited
for that use case. For this reason, the GUI deserves special consideration.&lt;/p&gt;
&lt;p&gt;For example, it is common for people to emulate OOP in other programming
languages. &lt;code&gt;Gtk+&lt;/code&gt; is a huge example of this, implementing OOP as a
series of macros and conventions in C. This is done for many reasons,
including familiarity with OOP designs and a desire to create some kind
of run-time polymorphism. But in my experience, this is most common
when implementing a GUI framework.&lt;/p&gt;
&lt;p&gt;In this series of articles, we will primarily focus on applying OOP
to other use cases, but we will also discuss GUIs as appropriate.
In this introductory section, I will just point out that GUI
frameworks are clearly possible outside traditional OOP designs
and programming languages, and even in Rust. Sometimes, they work
by completely different mechanisms, like the &lt;a href=&#34;https://reflex-frp.org/&#34;&gt;functional-reactive
programming&lt;/a&gt; mostly pioneered in Haskell, which
I personally prefer to traditional OOP-based programming and for which
traditional OOP features would not be helpful.&lt;/p&gt;
&lt;p&gt;Now, without further ado, let us compare OOP to Rust and other
post-OOP programming languages, pillar by pillar, from a pragmatic
perspective. For the rest of this first post, we will focus on
encapsulation.&lt;/p&gt;
&lt;h1 id=&#34;first-pillar-encapsulation&#34;&gt;First Pillar: Encapsulation&lt;/h1&gt;
&lt;p&gt;In object-oriented programming, &lt;strong&gt;encapsulation&lt;/strong&gt; is bound up with
the idea of a &lt;strong&gt;class&lt;/strong&gt;, the fundamental layer of abstraction in
object-oriented programming. Each class contains a layout for some data in
a record format, that is, a data structure where each instance contains a
set number of fields. Individual instances of the record type are known
as &amp;ldquo;objects.&amp;rdquo; Each class also contains code that is tightly paired to
that record type, organized into procedures called &lt;strong&gt;methods&lt;/strong&gt;. The idea
is then that all of the fields will only be accessible from inside the
methods, either by the conventions of OOP ideology or by the enforced
rules of the programming language.&lt;/p&gt;
&lt;p&gt;The fundamental benefit here is that the &lt;strong&gt;interface&lt;/strong&gt;, which is how
the code interacts with other code, or what you have to understand to
use the code, is much simpler than the &lt;strong&gt;implementation&lt;/strong&gt;, which are
the more fluidly changing details of how the code actually accomplishes
its job.&lt;/p&gt;
&lt;p&gt;But of course, lots of programming languages have abstractions like this.
Any program longer than a dozen lines has too many parts to keep in your
brain all at once, and so all remotely modern programming languages have
ways of dividing a program into smaller components, as a way to manage
the complexity, so that the interface is simpler than the implementation,
whether enforced by the programming language or a matter of the &amp;ldquo;honor
system.&amp;rdquo; So in a broader sense of the word, all modern programming languages
have some version of encapsulation.&lt;/p&gt;
&lt;p&gt;One simple form of encapsulation &amp;ndash; one that most object-oriented
programming languages maintain as a layer within the class &amp;ndash; is
&lt;strong&gt;procedures&lt;/strong&gt;, also known as functions, subroutines, or (as OOP calls them)
methods. Rather than allow any line of code to jump to any other line
of code, modern programming languages tend to group blocks of code
together into procedures, and you can then change the contents of the
procedure without affecting the outside code, and change the outside
code without affecting the procedure, as long as they follow the same
interface and contract.&lt;/p&gt;
&lt;p&gt;The contract is usually at least partially a human-level
convention. There&amp;rsquo;s not usually much stopping you from taking a procedure
that is supposed to process some data and instead making it instead loop
indefinitely or crash the program.  But some of it, like the separation of
the procedure from the rest of the program, and in many cases the number
and types of values it is allowed to accept and return in an invocation,
will be enforced by the programming language.&lt;/p&gt;
&lt;p&gt;For example, variables declared inside the procedure are usually &lt;em&gt;local&lt;/em&gt;,
and there&amp;rsquo;s generally no way to reference them outside the procedure.
The inputs and outputs are usually listed in a signature at the top of
the procedure. Normally, outside code can only enter the procedure on its
first line, rather than on an arbitrary line half-way through. In some
programming languages &amp;ndash; including Rust &amp;ndash; procedures can even contain
other procedures, which can only be called within the outer procedure.&lt;/p&gt;
&lt;p&gt;But of course, modern programs are often more complicated than a mere
handful of procedures. And so, modern programming languages (and again,
the word &amp;ldquo;modern&amp;rdquo; here is being used in a very loose way) have another
layer of encapsulated abstraction: &lt;strong&gt;modules&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Modules will generally contain a group of procedures, some externally
accessible, and some not. And in non-duck typed languages, they will
generally define a number of aggregate types, again some externally
accessible, and some not. It is generally even possible to expose these
types abstractly, so the existence of a type is accessible to the rest
of the program, but not the record fields, or even the fact that it
is a record type. Even C has this ability in its module system &amp;ndash; C++
did not introduce it, just added an additional, orthogonal level of
field-by-field access controls.&lt;/p&gt;
&lt;p&gt;Seen from my pragmatic point of view, class-based encapsulation is not
some special insight of OOP, but a specialized &amp;ndash; or rather, tightly
restricted &amp;ndash; form of module. In an OOP programming language, we have
this notion of a class, which is a special form of module (sometimes the
only supported form, or sometimes even layered underneath a completely
different, more traditional notion of module, for extra confusion). It&amp;rsquo;s
just that, for a &amp;ldquo;class,&amp;rdquo; there can only generally be one primary type
defined, which shares a name with the module itself, and where the fields
of that type are given special protection against access by code outside
the class.&lt;/p&gt;
&lt;p&gt;Of course, there are other differences between a class and a module,
but these have to do with the other pillars, and we will get to them
later. For right now, we will just discuss the idea of a &amp;ldquo;class&amp;rdquo;
as it relates to encapsulation &amp;ndash; where a class is just a special
module with one privileged, abstracted type.&lt;/p&gt;
&lt;p&gt;And this is a reasonable way to write a module, but it&amp;rsquo;s not as special
as object-oriented programming makes it out to be (especially once we
discuss alternative approaches to the other pillars, but again, more
later). There are some situations where a module doesn&amp;rsquo;t have any record
type that it defines, which is awkward in programming languages like Java,
where you have to define an empty record type anyway and still make a
&amp;ldquo;class.&amp;rdquo; There are also situations in which a module defines multiple
publically accessible types that are tightly entangled &amp;ndash; and where the
encapsulation between those types that OOP style would encourage you to
do is more of a hinderance than a help.&lt;/p&gt;
&lt;p&gt;Fundamentally, being able to hide the fields of a record from other
modules is important, which is why even C supports it. It is even
essential for implementing safe abstractions over unsafe features in
Rust, such as for collections, where raw pointers have invariants in
combination with other fields in the same record. But it is not new to
OOP, and it is simply not the best choice for every possible type.&lt;/p&gt;
&lt;p&gt;As evidence of this, in Java and Smalltalk, and to a lesser extent
even in C++ or Python, the insistence on a one-type-per-class style of
encapsulation means that you get these boilerplate methods like &lt;code&gt;setFoo&lt;/code&gt;
and &lt;code&gt;getFoo&lt;/code&gt;.  These methods do nothing but serve as field accessors for
something that is fundamentally a dumb record type. In theory, this helps
you if you want to change what happens when these fields are set or read,
but in practice, the fact that they are raw field accessors is part of
the contract. If they, for example, instead made a network call rather
than just returning a value, that would strongly value the principle of
surprise for such simply named methods.&lt;/p&gt;
&lt;p&gt;It is far simpler to say:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Point&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; x: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; y: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;pub&lt;/span&gt; z: &lt;span style=&#34;color:#66d9ef&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&amp;hellip; than the Java idiomatic &amp;ldquo;JavaBean&amp;rdquo; equivalent from when I was a
Java programmer (Java has apparently changed since then, but this is
representative of many OOP programming languages including Smalltalk
and many books on how to program):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Point&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; x;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; y;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; z;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getX&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; x;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setX&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; x) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; x;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getY&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; y;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setY&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; y) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;y&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; y;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getZ&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; z;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setZ&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; z) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;z&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; z;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Such data types generally don&amp;rsquo;t use any of the other features that OOP
classes get, such as polymorphism or inheritance. To use such features
in such &amp;ldquo;JavaBean&amp;rdquo; classes would also violate the principle of least
surprise. The &amp;ldquo;class&amp;rdquo; concept is overkill for these record types.&lt;/p&gt;
&lt;p&gt;And of course, a Java developer (or Smalltalk, or C#) will say that by
accessing the fields indirectly through these getter and setter methods,
that they are future-proofing the class, in case the design changes (and
in fact I was reminded to add this paragraph when someone on Reddit made
exactly this point). But I find this disingenuous, or at least misguided
&amp;ndash; it is often used for structures internal to a portion of the program,
where the far more reasonable thing to do would be to change the fields
openly to all users of the structure. It is also extremely difficult to
think of an unsurprising thing for these methods to do besides literally
set or get a field, as the method name implies &amp;ndash; making a network call,
for example, would be a shocking surprise for a &lt;code&gt;get&lt;/code&gt; or &lt;code&gt;set&lt;/code&gt; method
and therefore a violation of at least the implicit contract. In my time
programming object-oriented programming languages, I never once saw a
situation where it was appropriate for a getter or setter to do anything
but literally get or set the field.&lt;/p&gt;
&lt;p&gt;If code does change to require the getter or setter to do something
else, I would rather change the name of the method to reflect what
else it does, rather than pretend that&amp;rsquo;s somehow not a breaking
change. &lt;code&gt;fetchZFromNetwork&lt;/code&gt; or &lt;code&gt;setAndValidateZ&lt;/code&gt; seem more appropriate
than a &lt;code&gt;getZ&lt;/code&gt; or &lt;code&gt;setZ&lt;/code&gt; that does something more than the simple field
access that we assume a setter or getter does. OOP&amp;rsquo;s insistence that
every type should be its own code abstraction boundary is often absurd
when applied to these lightweight aggregate types. These sorts of getters
and setters are used to protect an abstraction boundary that shouldn&amp;rsquo;t
exist and just gets in the way, and future-proof against implementation
changes that shouldn&amp;rsquo;t be made without also changing the interface.&lt;/p&gt;
&lt;p&gt;Setters and getters, in short, are an anti-pattern. If you intend to
create an abstraction besides &amp;ldquo;data structure,&amp;rdquo; where validation or
network calls or anything else beyond raw field accesses would be appropriate,
then these &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; names are the wrong names for that abstraction.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Edit 2023-02-13 to add this paragraph:&lt;/strong&gt;&lt;/em&gt; To be clear, these objections
apply to properties as well. It&amp;rsquo;s not the syntactic inconvenience that
I object to, but the entire notion that replacing field accesses with
code transparently is a good thing to strive for, or an important
possibility to leave open. I should hope that &lt;code&gt;foo.bar = 3&lt;/code&gt; would
never make a network call in Rust! And what if it had to be &lt;code&gt;async&lt;/code&gt;?
It should be clear if I&amp;rsquo;m calling a function. Rust is about explicitness.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; functions, in reality, are only used as wrappers to
satisfy the constraints of object-oriented ideology. The future-proofing
they purportedly provide is an illusion. If you provide &amp;ldquo;JavaBean&amp;rdquo; style
types, or types with properties, over an abstraction boundary, you are in
practice just as locked in as if you&amp;rsquo;d provided raw field access &amp;ndash; the
changes you are most likely to want to make to those structures would not
allow shifting the getters and setters to maintain compatibility. Leveraging
this future-proofing is likely to be completely impossible for the changes
you&amp;rsquo;d want to make, and at best it would involve a horrendous hack.&lt;/p&gt;
&lt;p&gt;Rust might seem to be the same as OOP languages in all of this; it
superficially looks like it has something very similar to classes. You
can define functions associated with a given type &amp;ndash; and they are even
called methods! Like OOP methods, they syntactically privilege taking
values of that type (or references to those values) as the first argument,
called the special name &lt;code&gt;self&lt;/code&gt;.  You even mark fields of a record type
(called &lt;code&gt;struct&lt;/code&gt; in Rust) as public or (by default) private, encouraging
private fields just like in an object-oriented programming language.&lt;/p&gt;
&lt;p&gt;According to this pillar, Rust seems pretty close to being OOP. And
that&amp;rsquo;s a fair assessment, for this pillar, and an intentional choice
to make Rust programming more comfortable to people used to the everyday syntax
of OOP programming in C++ (or Java, or JavaScript).&lt;/p&gt;
&lt;p&gt;But the similarity is only skin-deep. Encapsulation is the least distinct
pillar of OOP (after all, all modern programming languages have some
form of it), and the implementation in Rust is not bound with the type.
When you declare a field private in Rust (by not specifying &lt;code&gt;pub&lt;/code&gt;),
that doesn&amp;rsquo;t mean private to its methods, that means private to the
module. A module can provide multiple types, and any function in that
module, whether a &amp;ldquo;method&amp;rdquo; of that type or not, can access all of the
fields defined in that type. Passing around records is encouraged when
appropriate, rather than discouraged to the point that accessors are
forced instead, even in tightly-bound related code.&lt;/p&gt;
&lt;p&gt;This is the first sign we see that Rust, in spite of its superficial
syntax, is not an OOP programming language.&lt;/p&gt;
&lt;h1 id=&#34;future-posts&#34;&gt;Future Posts&lt;/h1&gt;
&lt;p&gt;And at this point I&amp;rsquo;m going to have to pause for today.&lt;/p&gt;
&lt;p&gt;Of course, encapsulation isn&amp;rsquo;t the only fancy thing OOP-style classes
can do. If it were, classes wouldn&amp;rsquo;t have enamored so many people: it
would simply be obvious to everyone that classes were nothing more than
glorified modules, and methods nothing more than glorified procedures.&lt;/p&gt;
&lt;p&gt;In the next posts of this series, we will discuss the other features
associated with OOP, the two remaining traditional pillars of OOP,
polymorphism and inheritance, analyze them from a practical point of view,
and see how Rust compares with OOP as it comes to those pillars.&lt;/p&gt;
&lt;p&gt;Next up will be polymorphism!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>How to Write a JIRA Ticket in ... Relatively Few Steps</title>
      <link href="https://www.thecodedmessage.com/posts/jira/" />
      <id>https://www.thecodedmessage.com/posts/jira/</id>
      <updated>2022-10-31T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;If you&amp;rsquo;re confused by how to use JIRA effectively, do not worry!
If you learn this process, which is
&lt;del&gt;very simple&lt;/del&gt; not literally impossible, you too can become
&lt;del&gt;good at JIRA&lt;/del&gt; &lt;del&gt;passingly competent at JIRA&lt;/del&gt; not liable to being
fired for being bad at JIRA.&lt;/p&gt;
&lt;p&gt;Here are the steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create personal TODO item to write JIRA ticket
&lt;ul&gt;
&lt;li&gt;Accumulate requirements for JIRA ticket in personal notes
&lt;ul&gt;
&lt;li&gt;Often more complicated than the feature itself
&lt;ul&gt;
&lt;li&gt;This is the System Working™&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Write TODO items strategizing how to:
&lt;ul&gt;
&lt;li&gt;Share the JIRA ticket with other people&lt;/li&gt;
&lt;li&gt;Connect it properly with other JIRA tickets
&lt;ul&gt;
&lt;li&gt;Advanced: Also epics, projects, or other meta-JIRA constructs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Write JIRA ticket
&lt;ul&gt;
&lt;li&gt;Fail to understand what any of the fields are for
&lt;ul&gt;
&lt;li&gt;Oh, they&amp;rsquo;re required?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ask random people for appropriate values for required fields
&lt;ul&gt;
&lt;li&gt;Sometimes they never get back to you&lt;/li&gt;
&lt;li&gt;Or they get back two days from then&lt;/li&gt;
&lt;li&gt;In the meantime, forget you were writing a JIRA ticket
&lt;ul&gt;
&lt;li&gt;And then get reminded only by personal TODO list item
&lt;ul&gt;
&lt;li&gt;You did write one of those, right?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Curse the names of whoever designed the schema
&lt;ul&gt;
&lt;li&gt;Find out it&amp;rsquo;s someone you actually liked
&lt;ul&gt;
&lt;li&gt;It made sense at the time
&lt;ul&gt;
&lt;li&gt;No, it cannot be changed now&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Do follow up connecting JIRA ticket to other people&amp;rsquo;s JIRA
&lt;ul&gt;
&lt;li&gt;Argue with people about whether JIRA set-up appropriate&lt;/li&gt;
&lt;li&gt;Reconcile said arguments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Relitigate everything at next stand-up meeting
&lt;ul&gt;
&lt;li&gt;Potentially go back to beginning to write JIRA ticket again&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Be too tired to code anymore
&lt;ul&gt;
&lt;li&gt;What even is code?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</summary>
      <content type="html">&lt;p&gt;If you&amp;rsquo;re confused by how to use JIRA effectively, do not worry!
If you learn this process, which is
&lt;del&gt;very simple&lt;/del&gt; not literally impossible, you too can become
&lt;del&gt;good at JIRA&lt;/del&gt; &lt;del&gt;passingly competent at JIRA&lt;/del&gt; not liable to being
fired for being bad at JIRA.&lt;/p&gt;
&lt;p&gt;Here are the steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create personal TODO item to write JIRA ticket
&lt;ul&gt;
&lt;li&gt;Accumulate requirements for JIRA ticket in personal notes
&lt;ul&gt;
&lt;li&gt;Often more complicated than the feature itself
&lt;ul&gt;
&lt;li&gt;This is the System Working™&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Write TODO items strategizing how to:
&lt;ul&gt;
&lt;li&gt;Share the JIRA ticket with other people&lt;/li&gt;
&lt;li&gt;Connect it properly with other JIRA tickets
&lt;ul&gt;
&lt;li&gt;Advanced: Also epics, projects, or other meta-JIRA constructs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Write JIRA ticket
&lt;ul&gt;
&lt;li&gt;Fail to understand what any of the fields are for
&lt;ul&gt;
&lt;li&gt;Oh, they&amp;rsquo;re required?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ask random people for appropriate values for required fields
&lt;ul&gt;
&lt;li&gt;Sometimes they never get back to you&lt;/li&gt;
&lt;li&gt;Or they get back two days from then&lt;/li&gt;
&lt;li&gt;In the meantime, forget you were writing a JIRA ticket
&lt;ul&gt;
&lt;li&gt;And then get reminded only by personal TODO list item
&lt;ul&gt;
&lt;li&gt;You did write one of those, right?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Curse the names of whoever designed the schema
&lt;ul&gt;
&lt;li&gt;Find out it&amp;rsquo;s someone you actually liked
&lt;ul&gt;
&lt;li&gt;It made sense at the time
&lt;ul&gt;
&lt;li&gt;No, it cannot be changed now&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Do follow up connecting JIRA ticket to other people&amp;rsquo;s JIRA
&lt;ul&gt;
&lt;li&gt;Argue with people about whether JIRA set-up appropriate&lt;/li&gt;
&lt;li&gt;Reconcile said arguments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Relitigate everything at next stand-up meeting
&lt;ul&gt;
&lt;li&gt;Potentially go back to beginning to write JIRA ticket again&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Be too tired to code anymore
&lt;ul&gt;
&lt;li&gt;What even is code?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
    </entry>
    
    <entry>
      <title>First Impressions of Asahi Linux</title>
      <link href="https://www.thecodedmessage.com/posts/first-impressions-asahi-linux/" />
      <id>https://www.thecodedmessage.com/posts/first-impressions-asahi-linux/</id>
      <updated>2022-10-24T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I bought my M1 Mac over a year ago with the intention of installing Asahi
Linux on it, but I never got around to it until now. I am still thrilled
to be using an ARM workstation made by a major computer manufacturer,
and it&amp;rsquo;s good to be able to run the operating system of my choice on it
(though macOS is acceptable for entertainment and video calls, Linux
is what I work and do my &lt;a href=&#34;https://www.thecodedmessage.com/tags/organization/&#34;&gt;organization&lt;/a&gt; in). And I
don&amp;rsquo;t particularly do GPU-intensive things in my day to day computing &amp;ndash;
I run XMonad, of all things! &amp;ndash; so I don&amp;rsquo;t really feel like I&amp;rsquo;m missing
out by not having a &amp;ldquo;proper&amp;rdquo; graphics driver.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I bought my M1 Mac over a year ago with the intention of installing Asahi
Linux on it, but I never got around to it until now. I am still thrilled
to be using an ARM workstation made by a major computer manufacturer,
and it&amp;rsquo;s good to be able to run the operating system of my choice on it
(though macOS is acceptable for entertainment and video calls, Linux
is what I work and do my &lt;a href=&#34;https://www.thecodedmessage.com/tags/organization/&#34;&gt;organization&lt;/a&gt; in). And I
don&amp;rsquo;t particularly do GPU-intensive things in my day to day computing &amp;ndash;
I run XMonad, of all things! &amp;ndash; so I don&amp;rsquo;t really feel like I&amp;rsquo;m missing
out by not having a &amp;ldquo;proper&amp;rdquo; graphics driver.&lt;/p&gt;
&lt;h1 id=&#34;installation&#34;&gt;Installation&lt;/h1&gt;
&lt;p&gt;The Asahi Linux installation process, in spite of some dire
warnings, was relatively friendly. It was a &amp;ldquo;wizard&amp;rdquo; process
rather than a series of instructions to run individual commands that
I would have to read off a website.
Wizard is definitely better, because those instruction series almost
always contain mistakes, assumptions of things you&amp;rsquo;d &amp;ldquo;obviously&amp;rdquo; do,
or un-fleshed-out untested alternatives;
&lt;a href=&#34;https://nixos.org/manual/nixos/stable/index.html#sec-installation&#34;&gt;NixOS&lt;/a&gt;
in particular has stolen from me many hours of frustration I&amp;rsquo;ll never
get back (and hours later of fixing configuration issues that resulted
just from me following instructions from official materials).&lt;/p&gt;
&lt;p&gt;So, I guess simply because I&amp;rsquo;m comparing it to NixOS, Asahi Linux
felt extremely easy to install! I didn&amp;rsquo;t even mind that there wasn&amp;rsquo;t a
concrete recommendation for how much space to give each operating system
(although I would have appreciated it).  The installer did, however,
do two things that annoyed me.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;first thing&lt;/strong&gt; was that it asked me if I wanted to enter some sort of
an expert mode. It said that the questions it would ask in that mode were
only interesting to developers, and while normally that would be &amp;ldquo;yes,
absolutely me,&amp;rdquo; in this case I think they meant &amp;ldquo;developers &lt;em&gt;of&lt;/em&gt; Asahi
Linux&amp;rdquo; &amp;ndash; so, not me. I wanted to say &lt;code&gt;y&lt;/code&gt; out of curiosity, but I didn&amp;rsquo;t
want to actually choose any wrong option and risk bricking my laptop &amp;ndash;
which I don&amp;rsquo;t think were the actual stakes, but I wasn&amp;rsquo;t entirely sure.&lt;/p&gt;
&lt;p&gt;I really hope that if I&amp;rsquo;d said &lt;code&gt;y&lt;/code&gt;, it would have been okay.  I would
hope that the default option in each &amp;ldquo;advanced&amp;rdquo; prompt would be the same
as what I&amp;rsquo;d get if I didn&amp;rsquo;t do advanced options, but I didn&amp;rsquo;t really
trust them to do that, and it was intimidating.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d much rather they said what the advanced options actually did,
and reassured me that you could always go with the pre-set defaults
if you were unsure, rather than just ask me if I wanted to do &amp;ldquo;expert
mode.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So that was a little annoying.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;second thing&lt;/strong&gt; that annoyed me was something that the designers
have definitely put some thought into, and I&amp;rsquo;m befuddled how they arrived
where they did.&lt;/p&gt;
&lt;p&gt;So, there is one point where the computer is turned off, and
you must follow the instructions on how to turn the computer
back on very carefully and particularly, or else there be dragons,
because if you don&amp;rsquo;t boot it into recovery mode for the first boot,
then Linux will never install.&lt;/p&gt;
&lt;p&gt;That isn&amp;rsquo;t the problem. I appreciate them communicating the stakes,
and communicating how it works. I&amp;rsquo;m sure it&amp;rsquo;s not their fault that
you have to do this extra step, but rather something to do with
how the M1&amp;rsquo;s firmware work. However, I am befuddled why they provide the
instructions in the most detail on the laptop where you&amp;rsquo;re currently
installing it &amp;ndash; you know, a screen that&amp;rsquo;s immediately going to
disappear as soon as you turn the computer off. There were 7 steps!&lt;/p&gt;
&lt;p&gt;It appears that I was expected to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read all 7 steps very carefully&lt;/li&gt;
&lt;li&gt;Memorize them (carefully!) and remember them when I turned the computer
back on&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, I have ADHD, so my short-term prospective memory is &lt;em&gt;very&lt;/em&gt; poor.
There&amp;rsquo;s also a high chance that I&amp;rsquo;ll get distracted while the computer&amp;rsquo;s
off, and will have to come back to the turning-it-on step later.
But even a neurotypical person can&amp;rsquo;t be expected to reliably remember
how to do &lt;em&gt;7&lt;/em&gt; steps &lt;em&gt;carefully&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I took a picture of the instructions with my phone. I think they
should have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Suggested writing down or taking a picture of the instructions, because
&amp;ldquo;careful&amp;rdquo; is likely not good enough for many people.&lt;/li&gt;
&lt;li&gt;Included all 7 instructions in detail on the website, so if you fail
to write it down, you get more than this condensced summary:&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Once the first stage of the installation is done, you will have to reboot
into 1TR mode (One True recoveryOS) in order to finish the install. Read
the instructions that the installer prints carefully! Simply rebooting
into the new OS won’t work until this is done. You need to fully shut
down your machine, then boot by holding down the power button until
you see “Entering startup options”, choose your new OS in the boot
selector menu, and follow the prompts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The website references the transient &amp;ldquo;instructions that the installer
prints.&amp;rdquo; If anything, the installer should direct you to the website,
which should give the instructions in equal detail to how the
installer gives them:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/instructions.jpg&#34; alt=&#34;Reboot Instructions&#34;&gt;&lt;/p&gt;
&lt;p&gt;In any case, what I actually did was panic, close the laptop,
panic again, open it again, realize that made it turn on, and held
down the power button &amp;ndash; which worked, in spite of blatantly violating
the instructions. So maybe warn people not to close and then re-open
the laptop, while you&amp;rsquo;re at it?&lt;/p&gt;
&lt;p&gt;&amp;hellip; Perhaps it&amp;rsquo;s moves like this that prevented me from installing
NixOS correctly, where they just kind of assume you wouldn&amp;rsquo;t do
something that dumb.&lt;/p&gt;
&lt;h1 id=&#34;first-boot&#34;&gt;First Boot&lt;/h1&gt;
&lt;p&gt;I haven&amp;rsquo;t dual booted a computer since I lived with my parents, and either
had to share a computer with them (my Linux partition and their Windows)
or later when I only had one computer that I could use in full privacy,
but needed both Linux and a more &amp;ldquo;normal&amp;rdquo; OS &amp;ndash; thus an iBook which ran
Mac OS and a PowerPC version of Ubuntu.  Even when I ran FreeBSD and other
out-there OSes, I had a dedicated (old) full-tower desktop to run it from.&lt;/p&gt;
&lt;p&gt;So the idea of dual-booting a &amp;ldquo;normal&amp;rdquo; OS that comes with the computer
and the more &amp;ldquo;edgy&amp;rdquo; programmer-friendly OS that is Linux is quite
nostalgic for me. I wondered whether there was any way to refer to macOS
with capitalism-criticizing character substitutions a la Mi¢ro$oft:
maybe macO$?  And to be honest, I was even a little nervous that my
IT/sysadmin skills had rotted a little bit since I was a kid. Even though
this installer was bending over backwards to make everything easy,
this was an alpha operating system unsupported by the workstation
vendor.&lt;/p&gt;
&lt;p&gt;But all went well.&lt;/p&gt;
&lt;p&gt;Once you have it installed, the computer boots into Asahi Linux. You have to
hold down the power button to get the boot menu &amp;ndash; it uses a firmware-based
boot manager to distinguish macOS and Linux. This is a little annoying,
as I prefer being asked what operating system I want to boot every time
in a dual boot set up, but I can deal with it.&lt;/p&gt;
&lt;p&gt;The first boot requires a few remaining set up steps to select keyboard
layout, language, and time zone, and also to name the computer and set up
a default user. I named the computer &lt;code&gt;protectorate&lt;/code&gt; as part of my
forms-of-government naming scheme (my Dell laptop is &lt;code&gt;palatinate&lt;/code&gt;),
and in reference to that this is Linux acting in somewhat foreign territory,
claimed by another Unix.&lt;/p&gt;
&lt;p&gt;Once this set-up had been complete, I turned on Wi-Fi, which to my mild
surprise worked immediately and like a charm, from the KDE-based graphical
WiFi menu.&lt;/p&gt;
&lt;p&gt;I mean, in all honesty, I kind of knew it would work the first time &amp;ndash;
that was the point &amp;ndash; but I was still viscerally surprised.  I guess I
am used to the idea of getting Linux to run on a &amp;ldquo;new&amp;rdquo; or &amp;ldquo;odd&amp;rdquo; platform
being an issue of chasing down driver after driver, so I&amp;rsquo;m happy that
I have a distribution designed for basically exactly the computer that
I have, even if it&amp;rsquo;s not a computer particularly associated with Linux.&lt;/p&gt;
&lt;p&gt;Then, as soon as I&amp;rsquo;d verified that Linux worked, I very nervously
rebooted the whole thing into macOS &amp;ndash; which also worked. Yay!&lt;/p&gt;
&lt;h1 id=&#34;next-steps&#34;&gt;Next Steps&lt;/h1&gt;
&lt;p&gt;So that&amp;rsquo;s where I am now.&lt;/p&gt;
&lt;p&gt;To get my normal Linux workflow set up, I&amp;rsquo;m going to need XMonad and
Dropbox. This should be interesting, as I understand neither of those
things are Arch Linux packages on ARM, and Dropbox isn&amp;rsquo;t supported
on Linux ARM at all (though you can maybe use their APIs directly to
implement a janky home version?)&lt;/p&gt;
&lt;p&gt;So, when I get that all set up, I will let you know in another post!&lt;/p&gt;
&lt;p&gt;Pictures will come with the next blog post.&lt;/p&gt;
&lt;p&gt;I make no promises as to schedule.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>RAII: Compile-Time Memory Management in C&#43;&#43; and Rust</title>
      <link href="https://www.thecodedmessage.com/posts/raii/" />
      <id>https://www.thecodedmessage.com/posts/raii/</id>
      <updated>2022-10-11T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I don&amp;rsquo;t want you to think of me as a hater of C++. In spite of the fact
that I&amp;rsquo;ve been writing a &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;Rust vs C++ blog series&lt;/a&gt;
in Rust&amp;rsquo;s favor (in which this post is the latest installment), I am very
aware that Rust as it exists would never have been possible without C++.
Like all new technology and science, Rust stands on the shoulders of
giants, and many of those giants contributed to C++.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I don&amp;rsquo;t want you to think of me as a hater of C++. In spite of the fact
that I&amp;rsquo;ve been writing a &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;Rust vs C++ blog series&lt;/a&gt;
in Rust&amp;rsquo;s favor (in which this post is the latest installment), I am very
aware that Rust as it exists would never have been possible without C++.
Like all new technology and science, Rust stands on the shoulders of
giants, and many of those giants contributed to C++.&lt;/p&gt;
&lt;p&gt;And this makes sense if you think about it. Rust and C++ have very similar
goals. The C++ community has done a lot over all these years to pioneer
new programming language features in line with those goals. C++ has then
given these features years to mature in its humongous ecosystem. And
because Rust also doesn&amp;rsquo;t have to be compatible with C++, it can then
steal those features without some of the caveats they come with in C++.&lt;/p&gt;
&lt;p&gt;One of the biggest such features &amp;ndash; perhaps the biggest one &amp;ndash; is
RAII, C++&amp;rsquo;s and now Rust&amp;rsquo;s (somewhat oddly-named) scope-based feature
for resource management. And while RAII is for managing all kinds of
resources, its biggest use case is as part of a compile-time alternative
to run-time garbage collection and reference counting.&lt;/p&gt;
&lt;p&gt;As an alternative to garbage collection, RAII has deficits.
While many allocations are created and freed neatly in line with
variables coming in and out of scope, sometimes that&amp;rsquo;s not
possible. To fully compete with garbage collection and
capture the diverse ways programs use the heap, RAII
needs to be combined with other features.&lt;/p&gt;
&lt;p&gt;And C++ has done a lot of this. C++ added move semantics in C++11,
which Rust also has &amp;ndash; though cleaner in Rust because Rust was
designed with them from the start and so it can pull off &lt;a href=&#34;https://www.thecodedmessage.com/tags/cpp-move/&#34;&gt;destructive
moves&lt;/a&gt;. C++ also has opt-in reference counting, which,
again, Rust also has.&lt;/p&gt;
&lt;p&gt;But C++ still doesn&amp;rsquo;t have lifetimes (Rust got that from
&lt;a href=&#34;https://homes.cs.washington.edu/~djg/papers/cyclone.pdf&#34;&gt;Cyclone&lt;/a&gt;,
which called them &amp;ldquo;regions&amp;rdquo;), nor the infamous borrow checker that goes
along with them in Rust. And even though the borrow checker is perhaps
the most hated part of Rust, in this post, I will argue that it brings
Rust&amp;rsquo;s RAII-centric compile-time memory management system much closer
to feature-parity with run-time reference counting and other run-time
garbage-collection technologies.&lt;/p&gt;
&lt;p&gt;I will start by talking about the problem that RAII was originally
designed to solve. Then, I will re-hash the basics of how RAII works,
and work through memory usage patterns where RAII needs to be combined
with these other features, especially the borrow checker. Finally, I will
discuss the downsides of these memory management techniques, especially
performance implications and handling of cyclic data structures.&lt;/p&gt;
&lt;p&gt;But before I get into the weeds, I have some important caveats:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Caveat&lt;/em&gt;: No Turing-complete programming language can completely
prevent memory leaks. Even in fully-GC&amp;rsquo;d languages, you can still
leak memory by filling up a data structure with increasing
amounts of unnecessary data. This can be done by accident,
especially when sophisticated callback systems are combined
with closures. This is out of the scope of this post, which
only concerns memory management issues that automated GC
can actually help with.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Caveat #2&lt;/em&gt;: Rust allows you to &lt;a href=&#34;https://doc.rust-lang.org/std/boxed/struct.Box.html#method.leak&#34;&gt;leak memory on
purpose&lt;/a&gt;,
even when a garbage collector would have reclaimed it. In extreme
circumstances, the reference counting system can be abused to leak
memory as well. This fact has been used in anti-Rust rhetoric to
imply its memory safety system is somehow worthless.&lt;/p&gt;
&lt;p&gt;For the purposes of this post, we assume a programmer who is
trying to get actual work done and needs help not leaking memory
or causing memory corruption, not an adversarial programmer
trying to make the system leak on purpose.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Caveat #3&lt;/em&gt;: RAII is a terrible name. OBRM (Ownership-Based Resource
Management) is used in Rust sometimes, and is a much better name.
I call it RAII in this article though, because that&amp;rsquo;s what most people
call it, even in Rust.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&#34;the-problem-manual-memory-management-is-hard-gc-is-slow&#34;&gt;The Problem: Manual Memory Management is Hard, GC is &amp;ldquo;Slow&amp;rdquo;&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Caveat: To be clear, &amp;ldquo;slow&amp;rdquo; here is an oversimplification, and I address
that more later. I mean it as a tongue-in-cheek way of saying that
it has performance costs, whereas Rust and C++ try to adhere
to a &lt;em&gt;zero&lt;/em&gt;-cost principle.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So. C-style manual memory management &amp;ndash; &amp;ldquo;just call &lt;code&gt;free&lt;/code&gt; when you&amp;rsquo;re
done with the allocation&amp;rdquo; &amp;ndash; is error prone.&lt;/p&gt;
&lt;p&gt;It is error prone when it is easy and tedious, because programmers can
make stupid mistakes and just forget to write &lt;code&gt;free&lt;/code&gt; and it isn’t
immediately broken. It is error prone when multiple programmers work
together, because they might make different assumptions about who is
supposed to free something. It is error prone when multiple parts of the
code need to use the same data, especially when that usage changes with
new requirements and new features.&lt;/p&gt;
&lt;p&gt;And the consequences of doing it wrong are not just memory
leaks. Use-after-free can lead to memory corruption, and bugs in one
part of the program can abruptly show up when allocation patterns change
somewhere else entirely.&lt;/p&gt;
&lt;p&gt;This is a problem that can be solved with discipline, but like many
tedious clerical disciplines, it can also be solved by computer.&lt;/p&gt;
&lt;p&gt;It can be solved at run-time, which is what garbage collection and
reference counting do. These systems do two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They keep allocations from lasting too long. When memory becomes
unreachable, it can be reclaimed. This prevents memory leaks.&lt;/li&gt;
&lt;li&gt;They keep allocations from being freed early. If memory is still
reachable, it will still be valid. This prevents memory corruption.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And for most programmers and applications, this is good enough. And so
for almost all modern programming languages, this run-time cost is well
worth not troubling the programmer with the error-prone tedious tasks
of C-style manual memory management, enabling memory safety and resource
efficiency at the same time.&lt;/p&gt;
&lt;h2 id=&#34;gc-including-rc-has-costs&#34;&gt;GC (including RC) Has Costs&lt;/h2&gt;
&lt;p&gt;But there are costs to having the computer do memory management at
run-time.&lt;/p&gt;
&lt;p&gt;I lump mark-sweep garbage collection and reference counting together here.
Both mark-sweep garbage collection and reference counting have costs above
C-style manual memory management that make them unacceptable according to
the zero-cost principle. GC comes with pauses, and additional threads,
in the best case. RC comes with myriad increments and decrements to a
reference count. These costs might be small enough to be okay for your
application &amp;ndash; and that&amp;rsquo;s well and good &amp;ndash; but they are costs, and
therefore they can&amp;rsquo;t be the main memory management model in C++ or Rust.&lt;/p&gt;
&lt;p&gt;This is a complicated issue, and so before continuing, here comes
another caveat:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Caveat: GC is not &lt;em&gt;necessarily&lt;/em&gt; slower, but it does have performance
implications that are often unacceptable for situations where C++
(or Rust) is used. To achieve its full performance, it needs to be
enabled for the entire heap, and that has costs associated with it.
For these reasons, C++ and Rust do not use GC. The details of these
performance trade-offs are beyond the scope of this blog post.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;a-dilemma&#34;&gt;A Dilemma&lt;/h2&gt;
&lt;p&gt;But C++ and Rust are not most programming languages. They face a dilemma:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On the one hand, manual memory management
is unacceptably error prone for a high level language, a detail the
computer should be able to handle for you.&lt;/li&gt;
&lt;li&gt;On the other hand, run-time garbage collection violates a fundamental
goal that C++ and Rust share: the zero-cost principle. Code written
in these languages is supposed to be as performant as the equivalent
manually-written C. To conform to that principle, reference counting
(or GC) have to be opt-in (because, after all, sometimes manually written
C code does use these technologies).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, for the vast majority of situations, where a C programmer wouldn&amp;rsquo;t
use reference counting (or mark-sweep), Rust and C++ need something more
sophisticated.  They need tools to prevent memory management mistakes &amp;ndash;
that is, to at least partially automate this tedious and error-prone
task &amp;ndash; without sacrificing any run-time performance.&lt;/p&gt;
&lt;p&gt;And this is the reason C++ invented (and Rust appropriated) RAII. Instead
of addressing the problem at run-time, RAII automates memory management
at compile-time. Analogous to how templates and trait monomorphization
can bring some but not all of the power of polymorphism without many of
the run-time costs, RAII brings some but not all of the power of garbage
collection without constant reference count updates or GC pauses.&lt;/p&gt;
&lt;p&gt;But as we will see, RAII as C++ implements it only solves one of the
two problems addressed by garbage collection: leaks. It cannot address
memory corruption; it cannot keep allocations alive long enough for all
the code that could possibly need to use it.&lt;/p&gt;
&lt;h1 id=&#34;raw-raii-how-raii-works-on-its-own&#34;&gt;Raw RAII: How RAII Works on its Own&lt;/h1&gt;
&lt;p&gt;The simplest use case for RAII is underwhelming: it automatically inserts
calls to free up heap allocations at the end of the block where
we made the allocation. It replaces a &lt;code&gt;malloc&lt;/code&gt;/&lt;code&gt;free&lt;/code&gt; sandwich
from C with simply the allocation side, by inserting an
implicit (and unwritten) call to a destructor, which in its
simplest version is an equivalent of &lt;code&gt;free&lt;/code&gt;. And if that
was all RAII did, it wouldn&amp;rsquo;t be that interesting.&lt;/p&gt;
&lt;p&gt;For example, take this C-style (no RAII) code:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;void print_int_little_endian_decimal(int foo) {
    // Little endian decimal print of `foo`
    // i.e. backwards from how we normally write decimal numbers
    // e.g. 831 prints out as &amp;#34;138&amp;#34;

    // Big endian would be too hard
    // Little endian is as always actually simpler platonically,
    // if somehow not for humans.

    // Yes, this only works for positive ints. It&amp;#39;s an example.

    char *buffer = malloc(11);
    for(char *it = buffer; it &amp;lt; buffer + 10; ++it) {
        *it = &amp;#39;0&amp;#39; + foo % 10;
        foo /= 10;
        if (foo == 0) {
            it[1] = &amp;#39;\0&amp;#39;;
            break;
        }
    }
    puts(buffer); // put-string, not the 3sg verb form &amp;#34;puts&amp;#34;
    free(buffer); // Don&amp;#39;t forget to do this!
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Just using RAII (and &lt;code&gt;unique_ptr&lt;/code&gt;s, which are an essential part of
the RAII model), but using no other features of C++, we get this very
unidiomatic and unimpressive version:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;void print_int_little_endian_decimal(int foo) {
    std::unique_ptr&amp;lt;char[]&amp;gt; buffer{new char[11]};
    for(char *it = &amp;amp;buffer[0]; it &amp;lt; &amp;amp;buffer[10]; ++it) {
        *it = &amp;#39;0&amp;#39; + foo % 10;
        foo /= 10;
        if (foo == 0) {
            it[1] = &amp;#39;\0&amp;#39;;
            break;
        }
    }
    puts(&amp;amp;buffer[0]);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It doesn&amp;rsquo;t help us with our random guess of an appropriate buffer
size, our awkward redundant attempts to avoid a buffer-overflow, or
with any abstraction over the fact that we&amp;rsquo;re trying to implement
a collection.&lt;/p&gt;
&lt;p&gt;In fact, it makes the code more awkward, for a benefit that seems hardly
worth it, to just automatically call &lt;code&gt;free&lt;/code&gt; at the end of the block &amp;ndash;
which might not even be where we want to call free! We could instead
have wanted to return the data to the caller, or inserted it into
a bigger, greater data structure, or similar.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a bit less ugly when you use C++&amp;rsquo;s abstractions. Destructors
don&amp;rsquo;t have to just call &lt;code&gt;free&lt;/code&gt; (or rather its C++ analogue &lt;code&gt;delete&lt;/code&gt;) as
&lt;code&gt;unique_ptr&lt;/code&gt;&amp;rsquo;s does. Any C programmer can tell you that idiomatic
C code is rife with custom free functions to free all of the allocations
of a data structure, and C++ (and Rust) will choose which destructor
to call for you based on the type of the data. Calling &lt;code&gt;free&lt;/code&gt; when
a custom destructor must be called is a common careless mistake in C.
This is true especially among beginners, and (hot take!) making
programming languages less needlessly tricky for beginners is a good
thing for everybody.&lt;/p&gt;
&lt;p&gt;We can combine RAII with other features of C++ to get this more
idiomatic code, with the first &lt;code&gt;do&lt;/code&gt;-&lt;code&gt;while&lt;/code&gt; loop I&amp;rsquo;ve written
in years:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;void print_int_little_endian_decimal(int foo) {
    std::string res;
    do {
        res += &amp;#39;0&amp;#39; + foo % 10;
        foo /= 10;
    } while (foo != 0);
    std::cout &amp;lt;&amp;lt; res &amp;lt;&amp;lt; std::endl;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Does &lt;code&gt;std::string&lt;/code&gt; allocate memory on the heap? Maybe it only does
if the string goes above a certain size. But the custom destructor,
&lt;code&gt;~std::string&lt;/code&gt;, will call &lt;code&gt;delete[]&lt;/code&gt; only when the allocation was actually
made, abstracting that question away, along with handling terminating
nuls and avoiding overruns in a cleaner way.&lt;/p&gt;
&lt;p&gt;This ability of RAII &amp;ndash; to call custom destructors that abstract away
allocation decisions &amp;ndash; gets more impressive when we consider that
many data structures don&amp;rsquo;t make just 0 or 1 heap allocations, but whole
complicated trees of complicated heap allocations. In many cases, C++
(and Rust) will write your destructors for you, even for complicated
types like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;struct PersonRecord {
    std::string name;
    uint64_t salary;
};

std::unordered_map&amp;lt;std::string, std::vector&amp;lt;PersonRecord&amp;gt;&amp;gt; thing;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To destroy &lt;code&gt;thing&lt;/code&gt; in C, you&amp;rsquo;d have to loop through the hash map, free
all the keys, and then free all the values, which then requires freeing
all the strings in each &lt;code&gt;PersonRecord&lt;/code&gt; before freeing the backing for
each vector. Only then could you free the actual allocations backing the
hash map.&lt;/p&gt;
&lt;p&gt;And perhaps a C-based hash map library could do this for you, but only
by assuming that the keys are strings, and then taking a function
pointer to know how to free the values, which would ironically
be a form of dynamic polymorphism and therefore a performance hit. And
the function to free the values would then still have to manually free the
string, knowing which field of the &lt;code&gt;PersonRecord&lt;/code&gt; was a pointer and
duplicating that information between the structure and the manually-written
&amp;ldquo;free&amp;rdquo; function, and still likely not supporting the small-string
optimization that C++ enables.&lt;/p&gt;
&lt;p&gt;In C++, this freeing code is all automatically generated. &lt;code&gt;PersonRecord&lt;/code&gt;
gets an automatic destructor that calls the destructor of each
field (&lt;code&gt;int&lt;/code&gt;&amp;rsquo;s destructor is trivial), and the destructors of
&lt;code&gt;std::unordered_map&lt;/code&gt; and &lt;code&gt;std::vector&lt;/code&gt; are templated so that, at compile
time, a fresh destructor is built from those templates that handles all
of this, all without any indirect function calls or run-time cost beyond
what manually would be written for exactly this data structure in C.&lt;/p&gt;
&lt;p&gt;See, with RAII, a destructor isn&amp;rsquo;t just automatically and implicitly
called at the end of a scope in a function, but also in the destructors
of values (&amp;ldquo;objects&amp;rdquo; in C++) that &lt;em&gt;own&lt;/em&gt; other values. Even if you
do write a custom destructor for aggregate types, that just specifies
what the computer should do on destruction &lt;em&gt;beyond&lt;/em&gt; the automatic
calls to the destructors of the fields, which are still implicit.&lt;/p&gt;
&lt;h1 id=&#34;ownership-and-its-limitations&#34;&gt;Ownership and its limitations&lt;/h1&gt;
&lt;p&gt;This is all possible based on the concept of &amp;ldquo;ownership,&amp;rdquo; one of the key
principles of RAII. The key assumption is that every allocation has one
owner at any given time. Allocations can own each other (forming a tree
of allocations), or a scope can own an allocation (forming the root of
such a tree). RAII then can make sure the allocation ends when its owner
does &amp;ndash; by the scope exiting, or when the owning object is destroyed.&lt;/p&gt;
&lt;p&gt;But what if the allocation needs to outlive its parent, or its scope?
It&amp;rsquo;s not always the case that a function has primitive types as its
arguments and return value, and then only constructs trees of allocations
privately. We need to take these sophisticated collections and pass
them as arguments to functions. We need to have them be returned from
functions.&lt;/p&gt;
&lt;p&gt;This becomes apparent if we try to refactor our
big-endian integer decimalizer to allow us to do other things with
the resultant string besides print it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;std::string render_int_little_endian_decimal(int foo) {
    std::string res;
    do {
        res += &amp;#39;0&amp;#39; + foo % 10;
        foo /= 10;
    } while (foo != 0);
    return res;
}

int main() {
    std::cout &amp;lt;&amp;lt; render_int_little_endian_decimal(3781) &amp;lt;&amp;lt; std::endl;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Based on our previous discussion of RAII, you might assume that
the &lt;code&gt;~std::string&lt;/code&gt; destructor is called on the end of its scope,
rendering the allocation unusable for later printing, but instead
this code &amp;ldquo;Just Works.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve hit one of many mitigations against the limitations of raw
RAII that are necessary for it to work. This mitigation is the &amp;ldquo;Named
Return Value Optimization (NRVO),&amp;rdquo; which stipulates that if a named
variable is used in all of the &lt;code&gt;return&lt;/code&gt; statements in a function, it is
actually constructed (and destructed) in the context of the caller. It is
misnamed an &amp;ldquo;optimization&amp;rdquo; because it&amp;rsquo;s actually part of the semantics:
It eliminates entirely the call to the destructor at the end of the scope,
even if that destructor call would have side effects.&lt;/p&gt;
&lt;p&gt;This is just one of many ways RAII is made competitive with run-time
garbage collection, and we can have values that live outside of
a certain scope of a function. This one is narrow and peculiar to C++,
but many of the others lead to interesting comparisons. In the next
section, we discuss the others.&lt;/p&gt;
&lt;h1 id=&#34;filling-the-gaps-in-raii&#34;&gt;Filling the Gaps in RAII&lt;/h1&gt;
&lt;h2 id=&#34;copyingcloning&#34;&gt;Copying/Cloning&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;re going to start with one of the oldest of these: copying.
When C++ was designed, the intention was that the programmer would
not see a difference between types that don&amp;rsquo;t involve allocation
(like &lt;code&gt;int&lt;/code&gt; or &lt;code&gt;double&lt;/code&gt;) and types that do (like &lt;code&gt;std::string&lt;/code&gt; or
&lt;code&gt;std::unordered_map&amp;lt;std::string, std::vector&amp;lt;std::string&amp;gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When a function takes an &lt;code&gt;int&lt;/code&gt; argument, as in
&lt;code&gt;print_int_little_endian_decimal&lt;/code&gt;, that integer is copied.
Similarly, if we take a &lt;code&gt;std::string&lt;/code&gt; argument without additional
annotation, C++ will also make a copy:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int parse_int_le(std::string foo) {
    int res = 0;
    int pos = 1;
    for (char c: foo) {
        res += (c - &amp;#39;0&amp;#39;) * pos; // No input validation -- example!
        pos *= 10;
    }
    return res;
}

int main(int argc, char **argv) {
    std::string s = argv[1];
    std::cout &amp;lt;&amp;lt; parse_int_le(s) &amp;lt;&amp;lt; std::endl;
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is indeed consistent. Treating &lt;code&gt;int&lt;/code&gt;s and &lt;code&gt;std::string&lt;/code&gt; objects
in parallel ways is also in line with how higher-level programming
languages sometimes work: a string is a value, an &lt;code&gt;int&lt;/code&gt; is a value,
why not give them the same semantics? Aliasing is confusing, why not
avoid it with copying?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s made to work by an implicit function call. Just like destructor
calls are implicit in C++, copying also calls a function in the types
implementation. Here, it calls &lt;code&gt;std::string&lt;/code&gt;&amp;rsquo;s &amp;ldquo;copy constructor.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The problem here is that this is slow. Not only is an unnecessary
copy made, but an unnecessary allocation and deallocation creep in.
There is no reason not to use the same allocation the caller already
has, here in &lt;code&gt;s&lt;/code&gt; from the &lt;code&gt;main&lt;/code&gt; function. A C programmer would never
write this copying version.&lt;/p&gt;
&lt;p&gt;The only reason this feature is allowed under C++&amp;rsquo;s zero-cost
principle is because it is optional. It may be the default &amp;ndash; and
making it the default is one of the most questionable decisions C++
ever made &amp;ndash; but we can still alias if we want to. It just takes
more work.&lt;/p&gt;
&lt;p&gt;Rust, as you can guess by my tone, requires explicit annotation to
copy types that have an allocation. In fact, Rust doesn&amp;rsquo;t even use the
term &amp;ldquo;copy,&amp;rdquo; which is reserved for types that can be copied without
allocations. It calls this cloning, and requires use of the &lt;code&gt;clone()&lt;/code&gt;
method to accomplish it.&lt;/p&gt;
&lt;p&gt;Some types don&amp;rsquo;t use an allocation, and &amp;ldquo;copying&amp;rdquo; them is just a simple
memory copy. Some types do use an allocation, and &amp;ldquo;cloning&amp;rdquo; them requires
allocating. This distinction is important and fundamental to how computers
work. It&amp;rsquo;s relevant and visible in Java and even Python, and pretending
it doesn&amp;rsquo;t exist is unbecoming for a systems programming language like
C++.&lt;/p&gt;
&lt;h2 id=&#34;moves&#34;&gt;Moves&lt;/h2&gt;
&lt;p&gt;Returning an allocation from a function can&amp;rsquo;t always use NRVO. So if
you want your value to outlast your function, but it&amp;rsquo;s created inside
the function (and therefore &amp;ldquo;owned&amp;rdquo; by the function scope), what you
really need is a way for the value to change owners. You need to
be able to move the value from the scope into the caller&amp;rsquo;s scope.
Similarly, if you have a value in a vector, and need to remove the
last value, you can move it.&lt;/p&gt;
&lt;p&gt;This is distinct from copying, because, well, no copy is made &amp;ndash;
the allocation just stays the same. The allocation is &amp;ldquo;moved&amp;rdquo; because
the previous scope no longer has responsibility for destroying the allocation,
and the new scope gains the responsibility.&lt;/p&gt;
&lt;p&gt;Move semantics fix the most serious issue with RAII: your allocation
might not live exactly as long as its owner. The root of an allocation
tree might outlive the stack-based scope it&amp;rsquo;s in, such as when you want to
return a collection from a function. The other nodes of an allocation tree
might leave that tree and be owned by another stack frame, or by another
part of the same allocation tree, or by a different allocation tree. In
general, &amp;ldquo;each allocation has a unique owner&amp;rdquo; becomes &amp;ldquo;each allocation
has a unique owner at any given time,&amp;rdquo; which is much more flexible.&lt;/p&gt;
&lt;p&gt;In Rust, this is done via &amp;ldquo;destructive moves,&amp;rdquo; which oddly enough
means &lt;em&gt;not&lt;/em&gt; calling the destructor on the moved-from value. In fact,
the moved-from value ceases to be a value when it&amp;rsquo;s moved from, and
accessing that variable is no longer permitted.  The destructor is
then called as normal in the place where the value is moved to. This
is tracked statically at compile-time in the vast majority of situations,
and when it cannot be, an extra boolean is inserted as a &lt;a href=&#34;https://doc.rust-lang.org/nomicon/drop-flags.html&#34;&gt;&amp;ldquo;drop
flag&amp;rdquo;&lt;/a&gt; (&amp;ldquo;drop&amp;rdquo; is
how Rust refers to its destructors).&lt;/p&gt;
&lt;p&gt;C++ didn&amp;rsquo;t add move semantics until C++11; it was not part of the
original RAII scheme. This is surprising given
how essential moves are to RAII. Returning collections
from functions is super important, and you can&amp;rsquo;t copy every time.
But before C++, there were only poor man&amp;rsquo;s special cases for move,
like NRVO and the related RVO for objects constructed in the return
statement itself. These have completely different semantics than C++
move semantics &amp;ndash; they&amp;rsquo;re still more efficient than C++ moves in
many cases.&lt;/p&gt;
&lt;p&gt;When C++ did eventually add moves, the other established semantics of C++
forced it to add moves in a weird and deeply confusing way: it added
&amp;ldquo;non-destructive&amp;rdquo; moves. In C++, rather than the drop flag being a flag
inserted by the compiler, it is internal to the value. Every type that
supports moves must have a special &amp;ldquo;empty state,&amp;rdquo; because the destructor
is called on the moved-from value. If the allocation had moved to
another value, there would be no allocation to free, and this had
to be handled by the destructor at run-time, which can amount to
a violation of the zero-cost principle in some situations.&lt;/p&gt;
&lt;p&gt;C++ justifies this by making moves a special case of copy. Moves
are said to be like copies, but make no promises of preserving the
initial value.  In exchange, you might get the optimization of being
able to use the original allocation, but then the initial value will
not have an allocation, and will be forced to be different. This
definition is very different than what moves are actually used for
(cf. the name of the operation), and therefore, even though it is
&lt;a href=&#34;https://herbsutter.com/2020/02/17/move-simply/&#34;&gt;technically simple&lt;/a&gt;,
claiming that focusing on that definition (as Herb Sutter does) will
simplify things for the programmer is disingenuous, as I discuss in my
post on &lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;move semantics&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In practice, this means that all types support the operation of moving &amp;ndash;
even &lt;code&gt;int&lt;/code&gt;s &amp;ndash; but even some types that manage an allocation might fall
back on copying if moves haven&amp;rsquo;t been implemented for them. This
inconsistency, like all inconsistencies, is bad for programmers.&lt;/p&gt;
&lt;p&gt;In practice, this also means that moved-from objects are a problem.
A moved-from object might stay the same, if no moving was done. It
might also change in value, if the move caused an allocation
(or other resource) to move into the new object. This forces
C++ smart pointers to choose between movability and non-nullability &amp;ndash;
no moveable, non-nullable pointer is possible in C++. Nulls &amp;ndash; and the
other &amp;ldquo;moved-from&amp;rdquo; empty collections that you get from C++ move
semantics &amp;ndash; can then be referenced later on in the function,
and though they must be &amp;ldquo;valid&amp;rdquo; values of the object, they are
probably not the values you expect, and in the case of null pointers,
they are famously difficult values to reason about.&lt;/p&gt;
&lt;p&gt;This is a consequence of the fact that C++ was a pioneer of RAII
semantics, and didn&amp;rsquo;t design RAII and moves together from the
start. Rust has the advantage of having included moves from
the beginning, and so Rust move semantics are much cleaner.&lt;/p&gt;
&lt;p&gt;In Rust also, all types can be moved. But in Rust, no resources or
allocations are ever copied. Instead, moves always have the same
implementation: copy the memory that is stored in-line in the value
itself, and then do not call the destructor. For copyable types like
&lt;code&gt;int&lt;/code&gt; that do not manage an allocation or other resource, this does
amount to a copy, but the original is still not usable. But no allocation
or resource is ever copied; for those types, the pointer or handle is
simply brought along bit-by-bit just like other data, and the old value
is never touched again, making this a safe operation.&lt;/p&gt;
&lt;p&gt;All types must then be written in such a way to assume that
values might not stay in the same place in memory. If some operations on
a type can&amp;rsquo;t be written that way, they can be defined on &amp;ldquo;pinned&amp;rdquo;
versions of that type. A pin is a type of reference or box that
promises that the pointed-to value will never move again. The underlying
type is still movable, but these particular values are not.&lt;/p&gt;
&lt;p&gt;This is a gnarly exception to Rust&amp;rsquo;s &amp;ldquo;all types can be moved&amp;rdquo; rule that
make it false in practice, though still true in pedantic, language-lawyery
theory. But that&amp;rsquo;s not important. What is important is that Rust&amp;rsquo;s
move semantics are consistent, and do not rely on move constructors
and manual implementations of Rust&amp;rsquo;s drop flags within the object. The
dangerous possibility of interacting with a moved-from object, whose value
is unpredictable and quite possibly a special &amp;ldquo;empty&amp;rdquo; state like null,
is not present in Rust.&lt;/p&gt;
&lt;h2 id=&#34;borrows-in-rust&#34;&gt;Borrows in Rust&lt;/h2&gt;
&lt;p&gt;While moves cover returning a collection (or other resource-managing
value) from a function, they don&amp;rsquo;t cover passing such a value into a
function, or at least not in the general case. Sometimes, when we pass
a value into a function, we want to move the value in, so that the
function can consume it or add it to an allocation tree (like inserting
into a collection). But most times, we want the function to be able
to see and perhaps mutate it, but then we want to give it back to
the owner.&lt;/p&gt;
&lt;p&gt;Enter the borrow.&lt;/p&gt;
&lt;p&gt;In Rust, borrows are commonly introduced as a sort of an improvement on
moves. Consider our example function that parses a string to an &lt;code&gt;int&lt;/code&gt;,
here implemented in C++ with copies:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int parse_int_le(std::string foo) {
    int res = 0;
    int pos = 1;
    for (char c: foo) {
        res += (c - &amp;#39;0&amp;#39;) * pos; // No input validation -- example!
        pos *= 10;
    }
    return res;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here is a Rust version, with moves, so that the function consumes
the string:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;use std::env::args;

fn parse_int_le(foo: String) -&amp;gt; u32 {
    let mut res = 0;
    let mut pos = 1;
    for c in foo.chars() {
        res += (c as u32 - &amp;#39;0&amp;#39; as u32) * pos;
        pos *= 10;
    }
    res
}

fn main() {
    let mut args: Vec&amp;lt;String&amp;gt; = args().collect();
    println!(&amp;#34;{}&amp;#34;, parse_int_le(args.remove(1)));
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As we can see with the &amp;ldquo;move&amp;rdquo; version of this, we are in the awkward
position of removing the string from the vector, so that &lt;code&gt;parse_int_le&lt;/code&gt;
can consume the string, so it doesn&amp;rsquo;t have multiple owners.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;parse_int_le&lt;/code&gt; doesn&amp;rsquo;t need to own the string. In fact, it could
be written so that it can give the string back when it&amp;rsquo;s done:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn parse_int_le(foo: String) -&amp;gt; (u32, String) {
    let mut res = 0;
    let mut pos = 1;
    for c in foo.chars() {
        res += (c as u32 - &amp;#39;0&amp;#39; as u32) * pos;
        pos *= 10;
    }
    (res, foo)
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;ldquo;Taking temporary ownership&amp;rdquo; in real life is also known as
borrowing, and Rust has such a feature built-in. It is more powerful
than the above code that literally takes temporary ownership, though.
That code would have to remove the string from the vector and then
put it back &amp;ndash; which is even more inefficient than just removing it.
Rust borrowing allows you to borrow it even while it&amp;rsquo;s inside
the vector, and stays inside the vector. This is implemented by
a Rust reference, which has this borrowing semantics, and is,
like most &amp;ldquo;references,&amp;rdquo; implemented as a pointer at the machine level.&lt;/p&gt;
&lt;p&gt;In order to accomplish these semantics, Rust has its infamous borrow
checker. While we are borrowing something inside the vector, we can&amp;rsquo;t
simultaneously be mutating the vector, which could cause the thing we&amp;rsquo;re
borrowing to move.  Rust statically ensures that this is impossible,
rejecting code that use a reference after a mutation, destruction,
or move somewhere else would invalidate it.&lt;/p&gt;
&lt;p&gt;This enables us to extend the RAII-based system and both prevent
leaks and maintain safety, just like a GC or RC-based system. The
borrow checker is essential to doing so.&lt;/p&gt;
&lt;p&gt;For completeness, here is the idiomatic way to handle the
parameter in &lt;code&gt;parse_int_le&lt;/code&gt;, with an actual borrow, using
&lt;code&gt;&amp;amp;str&lt;/code&gt;, the special borrowed form of &lt;code&gt;String&lt;/code&gt; that also allows
slices:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;use std::env::args;

fn parse_int_le(foo: &amp;amp;str) -&amp;gt; u32 {
    let mut res = 0;
    let mut pos = 1;
    for c in foo.chars() {
        res += (c as u32 - &amp;#39;0&amp;#39; as u32) * pos;
        pos *= 10;
    }
    res
}

fn main() {
    let args: Vec&amp;lt;String&amp;gt; = args().collect();
    println!(&amp;#34;{}&amp;#34;, parse_int_le(&amp;amp;args[1]));
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;dodging-memory-safety-in-c&#34;&gt;Dodging memory safety in C++&lt;/h2&gt;
&lt;p&gt;In C++, of course, there is no borrow checker. In the &lt;code&gt;parse_int_le&lt;/code&gt;
example, it&amp;rsquo;s still possible to use a pointer, or a reference, but then
you&amp;rsquo;re on your own. When RAII-based code frees your allocation, your
reference is invalidated, which means it&amp;rsquo;s undefined behavior to use it.
No coordination is performed by the compiler between the RAII/move
system and your references, which point into the ownership tree
with no guarantee that said tree won&amp;rsquo;t move underneath it.
This can lead to memory corruption bugs, with security implications.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not just pointers and references. Other types that contain
references, such as iterators, can also be invalidated. Sometimes
those are more insidious because intermediate C++ programmers might
know about pointer invalidation, but let their guard down with
iterators. If you add to a vector while looping through it,
you&amp;rsquo;ve just done undefined behavior, and that&amp;rsquo;s surprising because
no pointers or references even have to show up. Rust&amp;rsquo;s borrow
checker handles these as well.&lt;/p&gt;
&lt;p&gt;Even though the Rust borrow checker gets a bad reputation, its safety
guarantees often make it worth it. It&amp;rsquo;s hard to write correct C++ when
references and non-owning pointers are involved.  Maybe some of you
have that skill, and are unsympathetic to those who don&amp;rsquo;t yet have it,
but it is a specialized skill, and the compiler can do a lot of the work
for you, by checking your work. Automation is a good thing, and so is
making systems programming more accessible to beginners.&lt;/p&gt;
&lt;p&gt;And of course, many C++ programmers do make mistakes. Even if it&amp;rsquo;s not
you, it might be one of your colleagues, and then you&amp;rsquo;ll have to clean
up the mess. Rust addresses this, and limits this more difficult mode
of thinking to writing unsafe code, which can be contained in modules.&lt;/p&gt;
&lt;h2 id=&#34;multiple-ownership&#34;&gt;Multiple Ownership&lt;/h2&gt;
&lt;p&gt;In RAII, an allocation has one owner at a time, and if your owner is destroyed
before the allocation is moved to another owner, the allocation must be
destroyed along with it.&lt;/p&gt;
&lt;p&gt;Of course, sometimes this isn&amp;rsquo;t how your allocations work. Sometimes they need
to live until both of two parent allocations are destroyed, and sometimes
there is no way to predict which parent is destroyed first. Sometimes,
the only way to solve that situation &amp;ndash; even in C &amp;ndash; is to use runtime
information &amp;ndash; and so you can model &lt;em&gt;multiple ownership&lt;/em&gt; through reference
counting: &lt;code&gt;std::shared_ptr&lt;/code&gt; in C++, or &lt;code&gt;Rc&lt;/code&gt; and &lt;code&gt;Arc&lt;/code&gt; in Rust (depending
on whether it is shared between multiple threads).&lt;/p&gt;
&lt;p&gt;This is something that C programmers will sometimes do in the face
of complicated allocation DAGs, and end up implementing bespoke on a
framework-by-framework basis (cf. GTK+ and other C GUI frameworks).
C++ and Rust are just standardizing the implementation of this, but, in
line with the zero-cost rule, making it optional.&lt;/p&gt;
&lt;p&gt;Interestingly enough, reference counting is implemented in terms of
RAII and moves. The destructor for a reference-counted pointer decreases
the reference, and cloning/copying such a pointer increases it. Moves,
of course, don&amp;rsquo;t change it at all.&lt;/p&gt;
&lt;h1 id=&#34;raii-what-this-all-adds-up-to&#34;&gt;RAII+: What this all adds up to&lt;/h1&gt;
&lt;p&gt;Between RAII, moves, reference counting, and the borrow checker, we now
have the memory management system of safe Rust. Safe Rust is a powerful
programming language, and in it, you can write programs almost as easily
as in a traditionally GC&amp;rsquo;d programming language like Java, but
get the performance of manually written, manually memory managed C.&lt;/p&gt;
&lt;p&gt;The cost is annotation. In Java, there is no distinction between
&amp;ldquo;borrowing&amp;rdquo; and &amp;ldquo;owning&amp;rdquo;, even though sometimes the code follows
similar structures as if there were. In Rust, the compiler must
be informed about the chain of owners, and about borrowers.
Every time an allocation crosses scope boundaries or is referred
to inside another allocation, you must write different syntax
to tell Rust whether it&amp;rsquo;s a move or a borrow, and it must
comply with the rules of the borrow checker.&lt;/p&gt;
&lt;p&gt;But it turns out most code has a natural progression of owners,
and most borrows are valid in the borrow checker. When they&amp;rsquo;re not,
it&amp;rsquo;s usually straight-forward to rethink the code so that it can
work that way, and the resultant code is usually cleaner anyway.
And in situations where neither of them work, reference counting
is still an option.&lt;/p&gt;
&lt;p&gt;At the cost of this annotation, Rust gives you everything a GC
does: Allocations are freed when their handles go out of scope,
and memory safety is still guaranteed, because the annotations
are checked. Memory leaks are as difficult as in a reference
counting language, and the annotations are checked, which is
most of the benefit of automating them. It&amp;rsquo;s an excellent
happy medium between manual memory management and full run-time
GC with no run-time cost over a certain discipline of C memory
management.&lt;/p&gt;
&lt;p&gt;Of course, other disciplines of C memory management are
possible.  And using this Rust system takes away flexibility
that might be relevant to performance. Rust, like C++, allows
you to sidestep the &amp;ldquo;compile-time GC&amp;rdquo; and use raw pointers,
and that can often be better for performance. &lt;a href=&#34;https://matklad.github.io/2022/10/06/hard-mode-rust.html&#34;&gt;A recent blog
post&lt;/a&gt; I read
explores some of that in more detail; encouragingly, that blog
post also considers RAII to be in-between manual memory management
and run-time GC &amp;ndash; serendipitously, because I had already drafted
much of this post when it came out.&lt;/p&gt;
&lt;p&gt;But the standard memory management tools of Rust cover the common
cases well, and unsafe is available for when it&amp;rsquo;s inappropriate &amp;ndash;
and can be wrapped in abstractions for interfacing with code that
uses the RAII-based system.&lt;/p&gt;
&lt;p&gt;In C++, the annotations of &amp;ldquo;borrows&amp;rdquo; vs &amp;ldquo;moves&amp;rdquo; can easily result
in undefined behavior. Leaks are prevented, but memory corruption is
not. So the C++ system is a much worse replacement for garbage collection
&amp;ndash; RAII is only doing some of its job, as it is not paired with
a borrow checker.&lt;/p&gt;
&lt;h1 id=&#34;cycles&#34;&gt;Cycles&lt;/h1&gt;
&lt;p&gt;I leave the most awkward topic for the end. We&amp;rsquo;ve talked about allocation
trees and DAGs, but not general graphs. These require &lt;code&gt;unsafe&lt;/code&gt; in Rust,
even something as supposedly basic as doubly linked lists. It&amp;rsquo;s against
the borrow checker&amp;rsquo;s rules, and the compiler will statically prevent
you from making them using safe, borrowing references. They simply aren&amp;rsquo;t
borrows in the Rust sense, but are rather something else, something
about which Rust doesn&amp;rsquo;t know how to guarantee safety.&lt;/p&gt;
&lt;p&gt;This is not as bad as you might think, because cycles also form a hole in
reference counting, which is a popular run-time GC system. This is why
you can&amp;rsquo;t use &lt;code&gt;Rc&lt;/code&gt; or &lt;code&gt;Arc&lt;/code&gt; to implement a doubly-linked list correctly in
Rust either: You&amp;rsquo;ll get past the borrow checker and guarantee a memory
leak.. These systems generally can&amp;rsquo;t detect cycles at all, and leak them,
which is arguably worse than forbidding them to be created.&lt;/p&gt;
&lt;p&gt;In any case, the &lt;code&gt;unsafe&lt;/code&gt; keyword is not poison. For things that Rust
doesn&amp;rsquo;t know how to keep safe, you need to exercise extra responsibility,
but at least the programming language is making you aware of it &amp;ndash;
unlike C++, which is unsafe all the time.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>A Strong Typing Example</title>
      <link href="https://www.thecodedmessage.com/posts/strong-typing/" />
      <id>https://www.thecodedmessage.com/posts/strong-typing/</id>
      <updated>2022-09-15T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I&amp;rsquo;m a Rust programmer and in general a fan of strong typing over dynamic
or duck typing. But a lot of advocacy for strong typing doesn&amp;rsquo;t actually
give examples of the bugs it can prevent, or it gives overly simplistic
examples that don&amp;rsquo;t really ring true to actual experience.&lt;/p&gt;
&lt;p&gt;Today, I have a longer-form example of where static typing can help
prevent bugs before they happen.&lt;/p&gt;
&lt;h1 id=&#34;the-problem&#34;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;Imagine you have a process that receives messages and must respond
to them. In fact, imagine you have potentially many such processes,
and want to write a framework to handle it.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I&amp;rsquo;m a Rust programmer and in general a fan of strong typing over dynamic
or duck typing. But a lot of advocacy for strong typing doesn&amp;rsquo;t actually
give examples of the bugs it can prevent, or it gives overly simplistic
examples that don&amp;rsquo;t really ring true to actual experience.&lt;/p&gt;
&lt;p&gt;Today, I have a longer-form example of where static typing can help
prevent bugs before they happen.&lt;/p&gt;
&lt;h1 id=&#34;the-problem&#34;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;Imagine you have a process that receives messages and must respond
to them. In fact, imagine you have potentially many such processes,
and want to write a framework to handle it.&lt;/p&gt;
&lt;p&gt;The incoming messages are expected to be in JSON, and the responses
are also supposed to be in JSON. So your framework parses the incoming
messages from JSON before passing it to the application&amp;rsquo;s callback
function, and then serializes the results.&lt;/p&gt;
&lt;p&gt;In Rust, the interface for the callback would look something like this
(&lt;a href=&#34;https://docs.rs/serde_json/latest/serde_json/enum.Value.html&#34;&gt;&lt;code&gt;Value&lt;/code&gt;&lt;/a&gt;
is a parsed JSON type from
&lt;a href=&#34;https://docs.rs/serde_json/latest/serde_json/&#34;&gt;&lt;code&gt;serde_json&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;trait MessageHandler {
    fn handle_message(&amp;amp;self, input: Value) -&amp;gt; Value;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In a dynamically-typed language like Python, the callback function would
look more like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;def handle_message(self, input):
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The code in the callback would then (hopefully) validate the JSON to
make sure it meets the expect schema, and if it&amp;rsquo;s not, return some error
in the reply message.  In a programming language like Python (I make
no promises that my Python is idiomatic or accurate; it&amp;rsquo;s meant as an
example of a duck-typing language), it perhaps could be written like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if not self.is_valid_input(input):
    return {&amp;#34;error&amp;#34;: &amp;#34;Invalid input&amp;#34;, &amp;#34;input&amp;#34;: input}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the JSON is in a valid format, it would do some processing and
return a non-error result.&lt;/p&gt;
&lt;p&gt;The framework code, in order to do this, runs code that looks
something like this (in pseudo-Python):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;input = conn.recv_message()
input = json_parse(input)
output = handler.handle_message(input)
output = json_serialize(output)
conn.send_response(output)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And all of this will work just fine.&lt;/p&gt;
&lt;p&gt;Except&amp;hellip; what if the input isn&amp;rsquo;t valid JSON? And what if none
of our test cases considered this possibility, but it nevertheless
arises in production? What if we didn&amp;rsquo;t even write test cases?&lt;/p&gt;
&lt;h1 id=&#34;some-attempts-to-solve&#34;&gt;Some Attempts to Solve&lt;/h1&gt;
&lt;h2 id=&#34;making-sure-we-catch-the-error-at-all&#34;&gt;Making sure we catch the error at all&lt;/h2&gt;
&lt;p&gt;In Rust, we would already have a hint that there&amp;rsquo;s something wrong. JSON
parsing in Rust is a function that can fail, and that is reflected
in the type of the function to parse JSON, which looks something like
this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pub fn from_slice(v: &amp;amp;[u8]) -&amp;gt; Result&amp;lt;Value&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;Result&lt;/code&gt; means that this function can fail. We have to handle that
failure in some way before we can get the resultant type. We can
crash the whole program:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;let input = from_slice(&amp;amp;input).expect(&amp;#34;Invalid JSON&amp;#34;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;NB: Reusing the name &lt;code&gt;input&lt;/code&gt; like this with a different type is allowed
in Rust; this declares a new variable that shadows the old one. This is
idiomatic when the value is being transformed and we don&amp;rsquo;t need the old
form anymore.&lt;/p&gt;
&lt;p&gt;Or we can do what Python will likely do by default, and bubble the
error up to the caller of the current function:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;let input = from_slice(&amp;amp;input)?;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or we can handle the error. And in this case, we should handle the error
in some way, as we need to reply to the message whether it&amp;rsquo;s in JSON
or not, and so we don&amp;rsquo;t want to skip over the code that does the reply.&lt;/p&gt;
&lt;p&gt;Already, Rust&amp;rsquo;s typing discipline is helping us. In order to do what
Python does by default, we need to at least opt in with a &lt;code&gt;?&lt;/code&gt;. Admittedly,
the programmer may do that on autopilot, but it at least gives the
programmer a hint that there might be an issue worth spending a second
or two considering before moving onwards.&lt;/p&gt;
&lt;h2 id=&#34;what-to-do-with-the-error&#34;&gt;What to do with the error?&lt;/h2&gt;
&lt;p&gt;But let&amp;rsquo;s assume that the programmer did, in fact, realize that
these errors need to be handled. What should we do in case of
an error?&lt;/p&gt;
&lt;p&gt;One possibility is to handle it completely in the framework. If we
know all inputs must be valid JSON, we can take this burden off of
the application code:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;try:
    output = json_parse(input)
except JsonError:
    output = {&amp;#34;error&amp;#34;: &amp;#34;Invalid JSON&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But what if we want to give the application-writer more flexibility?
What if we envision a situation where the application-writer wants to
accept either JSON or non-JSON data?&lt;/p&gt;
&lt;p&gt;In a duck-typed programming language like Python, if the parsing fails,
we can simply pass the original input to the handler. This is really easy to do.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;try:
    input = json_parse(input)
except JsonError:
    pass
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, the handler function just needs to ensure that the passed-in
value is a dictionary in our validation:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;def is_valid_input(input):
    if type(input) is not dict:
        return False
    if &amp;#39;requiredField&amp;#39; not in input:
        return False
    return True
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Of course, we might forget to do that, and if we do, we might now
throw an exception when we run the &lt;code&gt;not in&lt;/code&gt; test, which throws an exception
if &lt;code&gt;input&lt;/code&gt; is not in fact a dictionary. This would be bad, as not even
all JSON parses to dictionaries, but it&amp;rsquo;s a mistake someone could make
if they&amp;rsquo;re not thinking about error handling.&lt;/p&gt;
&lt;p&gt;In Rust, we can&amp;rsquo;t pass the initial input directly to the handler, as
it would be a different type. So if we try to do the direct equivalent to the
Python, it gives us an error:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;let input = match from_slice(&amp;amp;input) {
    Ok(parsed_value) =&amp;gt; parsed_value, // This is the parsed value, type `Value`
    Err(_) =&amp;gt; input, // This is the raw `Vec&amp;lt;u8&amp;gt;` data... TYPE MISMATCH!
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We are then forced to brainstorm another solution, which might
raise ideas we didn&amp;rsquo;t otherwise consider, and force us to backtrack
in our design a little, which is actually a good thing because
this solution, while simple in Python, has some flaws.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s some solutions we might brainstorm:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Call a different callback in handler for unparsed data
&lt;ul&gt;
&lt;li&gt;Application specifies whether data should be parsed&lt;/li&gt;
&lt;li&gt;Framework chooses which callback to call dynamically&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use an &lt;code&gt;enum&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last one is interesting. If we do want to create a value that
can contain either &lt;code&gt;Value&lt;/code&gt; or &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;/code&gt;, we still can in Rust. We just
have to create a new type that tells the compiler we want that:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;enum IncomingMessage {
    Parsed(Value),
    Unparsed(Vec&amp;lt;u8&amp;gt;),
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then, before we can do any work on the wrapped &lt;code&gt;Value&lt;/code&gt;, we have to say
what happens if it&amp;rsquo;s actually a &lt;code&gt;Vec&amp;lt;u8&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;let input = match input {
    Parsed(value) =&amp;gt; value,
    Unparsed(_) =&amp;gt; {
        // return an error JSON blob
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In fact, this even helps with the fact that not all parsed JSON is a
dictionary, as &lt;code&gt;serde_json::Value&lt;/code&gt; is itself an &lt;code&gt;enum&lt;/code&gt;!&lt;/p&gt;
&lt;h1 id=&#34;further-problem&#34;&gt;Further Problem&lt;/h1&gt;
&lt;p&gt;But even if we do correctly validate that we have a dictionary, and we
output an error in our message response if we don&amp;rsquo;t, I want to point
back to our original pseudo-Python for what error to output:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if not self.is_valid_input(input):
    return {&amp;#34;error&amp;#34;: &amp;#34;Invalid input&amp;#34;, &amp;#34;input&amp;#34;: input}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If &lt;code&gt;input&lt;/code&gt; is JSON parsed into a dictionary, it will definitely serialize
back into JSON, and this line makes sense. But now that &lt;code&gt;input&lt;/code&gt; might
not be parsed JSON, but instead might be in some sort of raw format,
this dictionary might fail to serialize back into JSON.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;A lot of programming is converting data from one format to another
and validating it. Strong static typing systems like Rust&amp;rsquo;s can help
prevent mistakes before they happen, and force people to come up
with more rigorous designs rather than shoe-horning different
values into the same variable, which dynamic typing makes easy &amp;ndash; too
easy. I hope this example was relatable!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Blocking Sockets and Async</title>
      <link href="https://www.thecodedmessage.com/posts/blocking-sockets/" />
      <id>https://www.thecodedmessage.com/posts/blocking-sockets/</id>
      <updated>2022-08-08T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Using &lt;code&gt;async&lt;/code&gt; in Rust can lead to bad surprises. I recently came across
a particularly gnarly one, and I thought it was interesting enough to
share a little discussion. I think that we are too used to the burden
of separating &lt;code&gt;async&lt;/code&gt; from blocking being on the programmer, and
Rust can and should do better, and so can operating system APIs,
especially in subtle situations like the one I describe here.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Using &lt;code&gt;async&lt;/code&gt; in Rust can lead to bad surprises. I recently came across
a particularly gnarly one, and I thought it was interesting enough to
share a little discussion. I think that we are too used to the burden
of separating &lt;code&gt;async&lt;/code&gt; from blocking being on the programmer, and
Rust can and should do better, and so can operating system APIs,
especially in subtle situations like the one I describe here.&lt;/p&gt;
&lt;p&gt;Every &lt;code&gt;async&lt;/code&gt; programmer learns early on not to call a blocking function
from an &lt;code&gt;async&lt;/code&gt; function.  If you do, it is a hidden color violation,
as I discuss in a &lt;a href=&#34;https://www.thecodedmessage.com/posts/async-colors&#34;&gt;previous post&lt;/a&gt;. By &amp;ldquo;hidden,&amp;rdquo; I
mean that unlike other color violations, Rust gives you no compiler-time
help. You just have to use discipline. You just have to &amp;ldquo;make sure not
to do it.&amp;rdquo; You just have to increase your cognitive load. It is a rule
that the computer is no help with &amp;ndash; which means that you&amp;rsquo;ll definitely
mess it up at some point, possibly at many points.&lt;/p&gt;
&lt;p&gt;Unfortunately, it&amp;rsquo;s also a gnarly problem to debug. The actual blocking
function call will quite possibly work just fine. It&amp;rsquo;ll return when
the resource is ready, and block until then &amp;ndash; probably exactly what
you wanted. It&amp;rsquo;s the rest of the system that falls apart &amp;ndash; other
tasks on the same thread starve, tasks that are depending on them
for progress also starve, but meanwhile other tasks might proceed
without a problem. Worse, there&amp;rsquo;s no guarantee that the
bug will manifest every time, so the bug isn&amp;rsquo;t readily
&lt;a href=&#34;https://www.thecodedmessage.com/posts/reproducibility&#34;&gt;reproducible&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You might think this is an easy problem to address, either through
improvements in the programming language or better programming
discipline.&lt;/p&gt;
&lt;p&gt;At a programming language level, you could imagine Rust having
some sort of generalization of &lt;code&gt;unsafe&lt;/code&gt;, or maybe an effects system.
Functions that block would have &lt;code&gt;blocking&lt;/code&gt; as part of their
signature. Calling a &lt;code&gt;blocking&lt;/code&gt; function from an &lt;code&gt;async&lt;/code&gt;
function would then be an error, with a way out for functions like
&lt;a href=&#34;https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html&#34;&gt;&lt;code&gt;spawn_blocking&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately, Rust doesn&amp;rsquo;t have this feature, so we have to rely on
programmer discipline.  The discipline seems easy enough: If you&amp;rsquo;re in
an async function, and you call a function that&amp;rsquo;s going to take some
time or do I/O, make sure you&amp;rsquo;re doing an async call, which in most
cases means using the &lt;code&gt;async&lt;/code&gt; keyword.&lt;/p&gt;
&lt;p&gt;Unfortunately, this doesn&amp;rsquo;t work 100% of the time, because the operating
system isn&amp;rsquo;t on board. There are system calls that block sometimes, based
on dynamic configuration. Does the &lt;code&gt;recv&lt;/code&gt; system call block? Well, that
depends on whether the socket is a blocking socket, or a non-blocking
socket. Fundamentally, &lt;code&gt;recv&lt;/code&gt; is run-time polymorphic on socket type,
in a way that makes it a different &lt;a href=&#34;https://www.thecodedmessage.com/posts/async-colors&#34;&gt;&lt;em&gt;color&lt;/em&gt;&lt;/a&gt; based
on run-time information.&lt;/p&gt;
&lt;p&gt;This is bad design: BSD should have split &lt;code&gt;recv&lt;/code&gt; into two system calls,
&lt;code&gt;recv&lt;/code&gt; or &lt;code&gt;recv_nonblock&lt;/code&gt;. &lt;code&gt;recv&lt;/code&gt; could error if given a non-blocking
socket, and &lt;code&gt;recv_nonblock&lt;/code&gt; could error if given a blocking one.
Linux at least has a flag &lt;code&gt;MSG_DONTWAIT&lt;/code&gt; that makes an individual
&lt;code&gt;recv&lt;/code&gt; call unconditionally non-blocking, but it&amp;rsquo;s non-standard. It&amp;rsquo;s
not supported on macOS and &lt;code&gt;tokio&lt;/code&gt;/&lt;code&gt;mio&lt;/code&gt; understandably doesn&amp;rsquo;t use it.&lt;/p&gt;
&lt;p&gt;Most of the time, this isn&amp;rsquo;t an issue. Sockets controlled through &lt;code&gt;tokio&lt;/code&gt;
or other async runtimes are always configured with the operating system to
be non-blocking, as an invariant on those socket types. Sockets controlled
through &lt;code&gt;std&lt;/code&gt; or other libraries will be blocking, and will be contained
in completely different Rust types. The Rust type system is used to keep
track of the distinction even if the operating system won&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;But this becomes an issue where these boundaries are
broken, namely in conversion functions between them. These
methods then have whether or not a socket is blocking
as part of their contract.  For example, the documentation for
&lt;a href=&#34;https://docs.rs/tokio/latest/tokio/net/struct.TcpStream.html#method.from_std&#34;&gt;&lt;code&gt;TcpStream::from_std&lt;/code&gt;&lt;/a&gt;
says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This function is intended to be used to wrap a TCP stream from the
standard library in the Tokio equivalent. The conversion assumes nothing
about the underlying stream; it is left up to the user to set it in
non-blocking mode.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Thus, as a precondition of calling the &lt;code&gt;from_std&lt;/code&gt; function, you
must pass a &amp;ldquo;non-blocking&amp;rdquo; socket. If you instead did not set the
socket as non-blocking &amp;ndash; perhaps because you were making it with some
extra options you needed, but assumed that &lt;code&gt;tokio&lt;/code&gt; would handle
the non-blocking part &amp;ndash; bad things happen.&lt;/p&gt;
&lt;p&gt;If blocking were considered a safety issue, this function would
be marked &lt;code&gt;unsafe&lt;/code&gt;. But it&amp;rsquo;s not, and so it&amp;rsquo;s simply an unchecked
precondition &amp;ndash; and we&amp;rsquo;re not used to those in Rust. Most
safe functions check their preconditions, either returning
a special value (like an &lt;code&gt;Err&lt;/code&gt;) or panicking if something is wrong.
The ones that don&amp;rsquo;t are typically marked &lt;code&gt;unsafe&lt;/code&gt;. Unchecked preconditions
still exist &amp;ndash; they cause rogue behavior but not behavior deemed
&amp;ldquo;unsafe&amp;rdquo; under Rust&amp;rsquo;s definition &amp;ndash; but they are rare, and
therefore surprising to a Rust programmer.&lt;/p&gt;
&lt;p&gt;Why is it not a checked precondition? That&amp;rsquo;s easy to answer: Checking
it would take an extra system call, as would unconditionally setting it
unblocked in that system call itself. System calls are slow, and that
would be an unacceptable performance penalty for many applications.&lt;/p&gt;
&lt;p&gt;This leads to a dissapointing end result, though. It&amp;rsquo;s not enough
to simply make sure you don&amp;rsquo;t call I/O methods unless they come
with an &lt;code&gt;async&lt;/code&gt; version. To be disciplined enough to be an &lt;code&gt;async&lt;/code&gt;
Rust programmer, you also have to watch out for these extra unchecked
preconditions.&lt;/p&gt;
&lt;p&gt;Otherwise, you get a hidden color bug that&amp;rsquo;s even harder to track down
because the blocking functions you&amp;rsquo;re calling don&amp;rsquo;t look blocking.
&lt;code&gt;tokio&lt;/code&gt; calls &lt;code&gt;recv&lt;/code&gt;, thinking it&amp;rsquo;s not blocking, but it is. You
expect &lt;code&gt;tokio&lt;/code&gt; to be correct, but because of this broken invariant, it
isn&amp;rsquo;t. These sorts of issues can be very hard and time-consuming to debug.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Why Rust should only have provided `expect` for turning errors into panics, and not also provided `unwrap`</title>
      <link href="https://www.thecodedmessage.com/posts/2022-07-14-programming-unwrap/" />
      <id>https://www.thecodedmessage.com/posts/2022-07-14-programming-unwrap/</id>
      <updated>2022-07-14T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;&lt;strong&gt;UPDATE 3 (from 2025):&lt;/strong&gt; I don&amp;rsquo;t really believe this anymore.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2&lt;/strong&gt;: I have made the title longer because people seem to be
insisting on misunderstanding me, giving examples where the only
reasonable thing to do is to escalate an &lt;code&gt;Err&lt;/code&gt; into a panic. Indeed,
such situations exist. I am not advocating for panic-free code.
I am advocating that &lt;code&gt;expect&lt;/code&gt; should be used for those functions,
and if a function is particularly prone to being called like that
(e.g. &lt;code&gt;Mutex::lock&lt;/code&gt; or regex compilation), there should be a panicking
version.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;&lt;strong&gt;UPDATE 3 (from 2025):&lt;/strong&gt; I don&amp;rsquo;t really believe this anymore.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE 2&lt;/strong&gt;: I have made the title longer because people seem to be
insisting on misunderstanding me, giving examples where the only
reasonable thing to do is to escalate an &lt;code&gt;Err&lt;/code&gt; into a panic. Indeed,
such situations exist. I am not advocating for panic-free code.
I am advocating that &lt;code&gt;expect&lt;/code&gt; should be used for those functions,
and if a function is particularly prone to being called like that
(e.g. &lt;code&gt;Mutex::lock&lt;/code&gt; or regex compilation), there should be a panicking
version.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: &lt;a href=&#34;https://blog.burntsushi.net/unwrap/&#34;&gt;This post&lt;/a&gt;
by Andrew Gallant, author of the excellent
&lt;a href=&#34;https://github.com/BurntSushi/ripgrep&#34;&gt;&lt;code&gt;ripgrep&lt;/code&gt;&lt;/a&gt;, is a good
overall discussion of the topic I am trying to address here. I
basically entirely agree with it and recommend it as very
educational; specifically, I disagree only in that I think
that linting for &lt;code&gt;unwrap&lt;/code&gt; is a good thing, for the reasons
he acknowledges but ultimately does not find compelling in &lt;a href=&#34;https://blog.burntsushi.net/unwrap/#should-we-lint-against-uses-of-unwrap&#34;&gt;that
section&lt;/a&gt;. In his own terms, I just think that the juice &lt;em&gt;is&lt;/em&gt; worth the squeeze.&lt;/p&gt;
&lt;p&gt;I see the &lt;code&gt;unwrap&lt;/code&gt; function called a lot, especially in example code,
quick-and-dirty prototype code, and code written by beginner Rustaceans.
Most of the time I see it, &lt;code&gt;?&lt;/code&gt; would be better and could be used instead
with minimal hassle, and the remainder of the time, I would have used
&lt;code&gt;expect&lt;/code&gt; instead. In fact, I personally never use &lt;code&gt;unwrap&lt;/code&gt;, and I even
wish it hadn&amp;rsquo;t been included in the standard library.&lt;/p&gt;
&lt;p&gt;The simple reason is that something like &lt;code&gt;expect&lt;/code&gt; is necessary and
sometimes the best tool for the job, but it&amp;rsquo;s necessary rarely and should
be used in the strictest moderation, just like panicking should be used
in strictest moderation, and only where it is appropriate (e.g. array
indexing, for reasons I elaborate on later). &lt;code&gt;unwrap&lt;/code&gt; is too easy and
indiscriminate, and using it at all encourages immoderate use.&lt;/p&gt;
&lt;p&gt;This has turned out, much to my surprise, to be a somewhat controversial
stance, and so I&amp;rsquo;d like to take some time to explain why I feel that way.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll begin by reviewing what &lt;code&gt;Result&lt;/code&gt; is and what options we have
for dealing with its recoverable errors.&lt;/p&gt;
&lt;h1 id=&#34;results-and-what-to-do-with-them&#34;&gt;&lt;code&gt;Result&lt;/code&gt;s and what to do with them&lt;/h1&gt;
&lt;p&gt;Rust is widely and rightly praised for its use of
&lt;a href=&#34;https://doc.rust-lang.org/std/result/enum.Result.html&#34;&gt;&lt;code&gt;Result&lt;/code&gt;&lt;/a&gt; for
recoverable error handling. Instead of using exceptions like C++, which
propagate invisibly and surprisingly, or using sentinal values like &lt;code&gt;NULL&lt;/code&gt;
and &lt;code&gt;-1&lt;/code&gt;, Rust has &lt;a href=&#34;https://en.wikipedia.org/wiki/Tagged_union&#34;&gt;sum types&lt;/a&gt;
and thus, a function can return a value that is either an error (of a
specified, potentially narrow type) or the value we want:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#[derive(Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[must_use = &amp;#34;this `Result` may be an `Err` variant, which should be handled&amp;#34;]
pub enum Result&amp;lt;T, E&amp;gt; {
    Ok(T),
    Err(E),
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we have a function call &lt;code&gt;foo()&lt;/code&gt; that can fail and therefore returns
a &lt;code&gt;Result&lt;/code&gt;, we have a few different tactics we can use to handle it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Ignore&lt;/strong&gt;: We can ignore the return value, and therefore also ignore
whether it errors. This is almost never what we actually want, and so the
&lt;code&gt;#[must_use]&lt;/code&gt; annotation on &lt;code&gt;Result&lt;/code&gt; causes a warning to be issued:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;foo(); // WARNING
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Manual&lt;/strong&gt; We can manually &lt;code&gt;match&lt;/code&gt; on the return value and do different
things:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;match foo() {
    Ok(value) =&amp;gt; do_something(value),
    Err(err) =&amp;gt; handle_error(err),
}
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Propagate&lt;/strong&gt;: We can propagate the error ergonomically using the &lt;code&gt;?&lt;/code&gt; operator.
This makes &lt;code&gt;Result&lt;/code&gt; work like exceptions in many of the good ways,
while cluing in the reader to the additional control flow, which
is good:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;foo()?;
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Panic with custom message&lt;/strong&gt;: We
can transform the error into an &amp;ldquo;unrecoverable&amp;rdquo;
&lt;a href=&#34;https://doc.rust-lang.org/book/ch09-01-unrecoverable-errors-with-panic.html&#34;&gt;&lt;code&gt;panic&lt;/code&gt;&lt;/a&gt;
using &lt;code&gt;expect&lt;/code&gt;, which takes a string argument which is used to customize
the error message:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;foo().expect(&amp;#34;foo error&amp;#34;);
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Panic without custom message&lt;/strong&gt;: We can transform the error into a
panic with &lt;code&gt;unwrap&lt;/code&gt;, which does not take a string argument and therefore
leads to more generic error messages:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;foo().unwrap();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Most of the time, in production code, we will want to go with the
&lt;strong&gt;propagate&lt;/strong&gt; option, especially in library code where the application
will likely have a better notion of what to do with the error. This
option makes the flow control clearer, tends to result
in better error messages when the error messages are ultimately outputted,
and gives the calling functions more options.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;manual&lt;/strong&gt; option is useful even in a library for when an error
is in fact recoverable at that particular point (e.g. by retrying). In
an application, we&amp;rsquo;re often at a point where it makes sense to report
the error (via a log message or console output or user-facing error
message).&lt;/p&gt;
&lt;p&gt;Sometimes, errors are in fact no big deal, and should be suppressed
completely, but this is better expressed through the &lt;strong&gt;manual&lt;/strong&gt; option
at the application layer, with a comment explaining why the right thing
is to do nothing.&lt;/p&gt;
&lt;p&gt;But sometimes (and &lt;em&gt;only&lt;/em&gt; sometimes), &lt;strong&gt;panic&lt;/strong&gt; is appropriate, and
for that, there are two options, &lt;code&gt;unwrap&lt;/code&gt; and &lt;code&gt;expect&lt;/code&gt;. I always prefer
&lt;code&gt;expect&lt;/code&gt; for this, and pretend that &lt;code&gt;unwrap&lt;/code&gt; doesn&amp;rsquo;t exist, because it
makes panicking too easy. To explain, I&amp;rsquo;d like to discuss in what
situations I think panics are appropriate.&lt;/p&gt;
&lt;h1 id=&#34;when-to-panic&#34;&gt;When to panic?&lt;/h1&gt;
&lt;p&gt;Escalating an &lt;code&gt;Err&lt;/code&gt; result to a panic should be done
in similar situations to when &lt;code&gt;panic&lt;/code&gt; is appropriate
in general, which the Rust book offers some &lt;a href=&#34;https://doc.rust-lang.org/book/ch09-03-to-panic-or-not-to-panic.html&#34;&gt;guidance
on&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The most clear-cut case is when a code path is a &lt;em&gt;logic error&lt;/em&gt;, when
the error is only possible if the programmer has made a mistake and an
invariant has been broken.&lt;/p&gt;
&lt;p&gt;A typical example is array indexing. We often find ourselves with
an array index that we (think we) know is valid and we want to use it to
index an array, because we got it from looping or otherwise operating on
the array bounds.  We&amp;rsquo;re not so confident that we want to use &lt;code&gt;unsafe&lt;/code&gt;
and do an unchecked array access &amp;ndash; that could result in a security
vulnerability if we&amp;rsquo;re wrong &amp;ndash; but it would also be nonsensical to try
to recover from such an invalid access.&lt;/p&gt;
&lt;p&gt;For array indexing, this is actually the most
common scenario, and so the index operator in Rust
actually panics for us if we specify an out-of-bounds
index. An &lt;code&gt;unsafe&lt;/code&gt; checked array indexing method container &lt;a href=&#34;https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked&#34;&gt;is
available&lt;/a&gt;,
as is one that &lt;a href=&#34;https://doc.rust-lang.org/std/primitive.slice.html#method.get&#34;&gt;never panics and instead returns an
&lt;code&gt;Option&lt;/code&gt;&lt;/a&gt;,
but most of the time we want the panicking checked operation
and so that is the version that gets the &lt;a href=&#34;https://doc.rust-lang.org/std/primitive.slice.html#impl-Index%3CI%3E&#34;&gt;syntactic
sugar&lt;/a&gt;:
&lt;code&gt;arr[index]&lt;/code&gt; will neither memory corrupt nor return a recoverable
error on an invalid index, but instead panic.&lt;/p&gt;
&lt;p&gt;This is definitely the best default for array indexing. But sometimes,
logic errors result in recoverable errors, in &lt;code&gt;Err&lt;/code&gt; (or its equivalent
in the &lt;code&gt;Option&lt;/code&gt; world, &lt;code&gt;None&lt;/code&gt;). For example, maybe you have an array-like
data structure in which only a &lt;code&gt;get&lt;/code&gt; method is available, which
returns an &lt;code&gt;Option&lt;/code&gt;. If you were confident in your indexing, you
would want to panic on &lt;code&gt;None&lt;/code&gt;, and you can call &lt;code&gt;expect&lt;/code&gt; or &lt;code&gt;unwrap&lt;/code&gt;
to make that happen.&lt;/p&gt;
&lt;p&gt;It is certainly more ergonomic to write &lt;code&gt;expect&lt;/code&gt; than to do the
&lt;code&gt;match&lt;/code&gt; manually, and less likely to lead to mistakes:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;let val = arr.get(i).expect(&amp;#34;i should be valid index&amp;#34;);
let val = match arr.get(i) {
    Some(val) =&amp;gt; val,
    None =&amp;gt; panic!(&amp;#34;i should be valid index&amp;#34;),
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Besides logic errors, panics are also relevant in test cases, where
they are used to indicate test failure.&lt;/p&gt;
&lt;h1 id=&#34;no-need-to-panic-propagation-made-easy&#34;&gt;No need to panic: Propagation Made Easy&lt;/h1&gt;
&lt;p&gt;However, &lt;code&gt;expect&lt;/code&gt; and &lt;code&gt;unwrap&lt;/code&gt; &amp;ndash; especially &lt;code&gt;unwrap&lt;/code&gt; &amp;ndash; are also
amenable to overuse and misuse.&lt;/p&gt;
&lt;p&gt;Perhaps you&amp;rsquo;re doing prototyping and just need something that works most
of the time, or you&amp;rsquo;re writing a simple app with limited error-handling
needs. Some people use &lt;code&gt;unwrap&lt;/code&gt; and &lt;code&gt;expect&lt;/code&gt; for this situation, but
I don&amp;rsquo;t. I use &lt;code&gt;?&lt;/code&gt; even in that situation, because I never know when
prototype code might have to escalate to production code &amp;ndash; either
so suddenly there&amp;rsquo;s no time for me to intervene and improve the
error handling or so gradually there&amp;rsquo;s no occasion for it and it
never gets prioritized. Fixing crappy usage of &lt;code&gt;?&lt;/code&gt; in such a situation
is way easier and more likely to happen than fixing a bunch of
&lt;code&gt;expect&lt;/code&gt;s or &lt;code&gt;unwrap&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;How can I prototype with &lt;code&gt;?&lt;/code&gt;? Doesn&amp;rsquo;t it require a lot of extra work,
compared with &lt;code&gt;unwrap&lt;/code&gt;? Honestly, not really. Writing &lt;code&gt;Result&amp;lt;Foo&amp;gt;&lt;/code&gt;
is not substantially harder than writing &lt;code&gt;Foo&lt;/code&gt; for functions which
can error. As for converting between error types, libraries like
&lt;a href=&#34;https://crates.io/crates/eyre&#34;&gt;&lt;code&gt;eyre&lt;/code&gt;&lt;/a&gt; and
&lt;a href=&#34;https://docs.rs/anyhow/latest/anyhow/&#34;&gt;&lt;code&gt;anyhow&lt;/code&gt;&lt;/a&gt; exist so that
all errors can be included.&lt;/p&gt;
&lt;p&gt;Example code similarly can be written with &lt;code&gt;?&lt;/code&gt;. This is important because
Rust is rapidly growing and has a lot of new programmers using it. They
see that a function returns a thing, and want to get to the thing and
don&amp;rsquo;t know how to, and they see &lt;code&gt;unwrap&lt;/code&gt; in the example code and they
cargo cult it. Even if they have learned a thing or two about Rust,
it does have the perfect type signature for their problem, and so they
jump on it, and end up using it in prototype code and then trying to use
it in production code. Perhaps they know about &lt;code&gt;?&lt;/code&gt;, but it has a higher
barrier to entry, and so they&amp;rsquo;ll procrastinate learning about it.&lt;/p&gt;
&lt;p&gt;In these situations, &lt;code&gt;unwrap&lt;/code&gt; provides an easy, ergonomic
way of calling a function that might error, and so it&amp;rsquo;s very tempting,
like &lt;a href=&#34;https://en.wikipedia.org/wiki/Desire_path&#34;&gt;walking through the grass when there&amp;rsquo;s a paved path
available&lt;/a&gt;. However,
&lt;code&gt;?&lt;/code&gt; is generally preferable to &lt;code&gt;unwrap&lt;/code&gt; or &lt;code&gt;expect&lt;/code&gt;, and so the
relative easiness is misaligned to the order of preferences.&lt;/p&gt;
&lt;p&gt;And unfortunately, once code has been written using &lt;code&gt;unwrap&lt;/code&gt;
or &lt;code&gt;expect&lt;/code&gt; heavily, it&amp;rsquo;s hard to adapt it to use &lt;code&gt;?&lt;/code&gt; and propagation,
especially if those interfaces have come to be relied upon.&lt;/p&gt;
&lt;h1 id=&#34;why-i-prefer-expect-to-unwrap&#34;&gt;Why I prefer &lt;code&gt;expect&lt;/code&gt; to &lt;code&gt;unwrap&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;There are definitely legitimate use cases to turning an error
into panic, but they are relatively rare, especially if the
code is well-factored. Turning an error into a panic is also
extremely tempting to be abused. The second situation is more
common than the first, so in many codebases, the bad &lt;code&gt;unwrap&lt;/code&gt;s
and &lt;code&gt;expect&lt;/code&gt;s, the sloppy &amp;ldquo;OK for now&amp;rdquo; ones or the &amp;ldquo;it&amp;rsquo;s just
an example&amp;rdquo; ones outnumber the legitimate use cases.&lt;/p&gt;
&lt;p&gt;Raising the barrier to entry seems like a good solution, and &lt;code&gt;expect&lt;/code&gt;
seems like the perfect balance. The error string can also serve
as documentation of why this decision was made, like comments for
unsafety. The fact that &lt;code&gt;expect&lt;/code&gt; is a little less ergonomic is a
feature, as it discourages casual use. &lt;code&gt;expect&lt;/code&gt; has enough convenience
to encapsulate the concept of escalation from a &amp;ldquo;recoverable&amp;rdquo; error
to an &amp;ldquo;unrecoverable&amp;rdquo; error, but not so much that it competes with &lt;code&gt;?&lt;/code&gt;
in ergonomics.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;expect&lt;/code&gt;&amp;rsquo;s error message can serve as a comment as to why the
panic is justified. Comments are a good thing, and for as
questionable an operation as escalating an &lt;code&gt;Err&lt;/code&gt; to a panic,
it&amp;rsquo;s useful to explain why we think it will never happen even if
we think it&amp;rsquo;s obvious. Like the comments recommended for &lt;code&gt;unsafe&lt;/code&gt;
blocks, I think that &lt;code&gt;expect&lt;/code&gt; is a situation that deserves some
indication to the reader as to why the author thinks this is OK.&lt;/p&gt;
&lt;p&gt;Why have this in the error message rather than just a comment?
&lt;code&gt;expect&lt;/code&gt;&amp;rsquo;s error message is also helpful in debugging. &lt;code&gt;unwrap&lt;/code&gt; can give
good error messages, printing the error value and providing a backtrace,
but in other configurations and deployments you might not see a backtrace
and the error value might not be useful. Some &lt;code&gt;unwrap&lt;/code&gt; calls might
provide good enough error messages sometimes, but it doesn&amp;rsquo;t work 100%
of the time, so it can&amp;rsquo;t be relied upon &amp;ndash; especially when &lt;code&gt;expect&lt;/code&gt; is
readily available. Especially in the case of a logic error,
when the condition was thought impossible, debugging will already
be hard, and the person doing the debugging needs all the help they
can get.&lt;/p&gt;
&lt;h1 id=&#34;objections&#34;&gt;Objections&lt;/h1&gt;
&lt;p&gt;When I&amp;rsquo;ve expressed my opinions about &lt;code&gt;unwrap&lt;/code&gt; before, one objection
stands out in my mind as particularly interesting and particularly
valid. I say above that legitimate use cases to turning an &lt;code&gt;Err&lt;/code&gt; into
a panic are rare, which is generally true, but sometimes
can seem false. There are certain APIs where it comes up a lot,
APIs where &lt;code&gt;Err&lt;/code&gt;s frequently are actually logic errors.&lt;/p&gt;
&lt;p&gt;For example, regular expressions. The
&lt;a href=&#34;https://crates.io/crates/regex&#34;&gt;&lt;code&gt;regex&lt;/code&gt;&lt;/a&gt; crate uses a method called
&lt;a href=&#34;https://docs.rs/regex/latest/regex/struct.Regex.html#method.new&#34;&gt;&lt;code&gt;new&lt;/code&gt;&lt;/a&gt;
that is used to prepare regular expressions. It is practically always
called on a constant string, making any failure a logic error, which
should result in a panic, as discussed above. However, this same &lt;code&gt;new&lt;/code&gt;
method returns a &lt;code&gt;Result&lt;/code&gt;, necessitating an &lt;code&gt;unwrap&lt;/code&gt; or an &lt;code&gt;expect&lt;/code&gt;
to make the logic error into a panic.  Am I seriously suggesting that
the poor user write &lt;code&gt;.expect(&amp;quot;bad regular expression&amp;quot;)&lt;/code&gt; instead of
&lt;code&gt;.unwrap()&lt;/code&gt; every time?&lt;/p&gt;
&lt;p&gt;Well, that puts regex compilation in the same category as array
indexing in my mind, and means that the &lt;em&gt;default&lt;/em&gt; regex compilation function
should panic on the user&amp;rsquo;s behalf (of course, the &lt;code&gt;Result&lt;/code&gt; version
should still be possible, just as &lt;code&gt;get&lt;/code&gt; is a possible function for
slices).&lt;/p&gt;
&lt;p&gt;Similarly, when I&amp;rsquo;ve expressed my opinions about &lt;code&gt;unwrap&lt;/code&gt;, some have
assumed I&amp;rsquo;m opposed to panics altogether, and asked me if I used array
indexing, implying that if I accept the possibility of panics in array
indexing, I should accept the possibility of panics in &lt;code&gt;unwrap&lt;/code&gt; as well.&lt;/p&gt;
&lt;p&gt;For both of these objections, I want to clarify something: I&amp;rsquo;m not
opposed to panicking in logic error situations. But that does not imply
that &lt;code&gt;unwrap&lt;/code&gt; is a good idea. Most &lt;code&gt;Err&lt;/code&gt;s are not logic errors, and so
converting one to a panic should be a little inconvenient, and should
require the user to think enough to write an error message.&lt;/p&gt;
&lt;p&gt;For those situations where an error is actually likely to be a logic
error, such as array indexing or regex compilation, returning &lt;code&gt;Result&lt;/code&gt;
need not be the function&amp;rsquo;s default behavior. Perhaps the author of
&lt;code&gt;regex&lt;/code&gt; can make &lt;code&gt;new&lt;/code&gt; panic on compiler error, and another
function can be written for when the regex in question was user
inputted, or where a regex compilation error would not be a logic error.&lt;/p&gt;
&lt;p&gt;In general, when you find yourself using &lt;code&gt;expect&lt;/code&gt; or &lt;code&gt;unwrap&lt;/code&gt; over and
over again in the same way, and you&amp;rsquo;re sure it&amp;rsquo;s legitimate each time,
do what you do with all smelly-seeming code if you know it&amp;rsquo;s actually
the right thing in spite of the smell: Wrap it in an abstraction. Put
it in a function that calls &lt;code&gt;expect&lt;/code&gt; to panic on error.&lt;/p&gt;
&lt;p&gt;This is not cheating. This new, panicking function would instead serve
as a documentation for the fact that in this context, an &lt;code&gt;Err&lt;/code&gt; is in
fact likely to be a logic error, a tangible paper trail that someone
made a conscious call that, as a policy, panicking is appropriate in
this instance. The decision to panic instead of returning an &lt;code&gt;Err&lt;/code&gt; in
this situation is made in one place instead of many, where it can be
explained in a detailed comment if desired, and where it certainly won&amp;rsquo;t
be too much of a burden to use &lt;code&gt;expect&lt;/code&gt; instead of &lt;code&gt;unwrap&lt;/code&gt;. Even the
fact of the function existing and having a panic-based interface is a
signal from the library author that they have thought about this issue,
and deemed the situation to be more analogous to array indexing than,
say, a file-not-found.&lt;/p&gt;
&lt;h1 id=&#34;tendencies-and-statistics&#34;&gt;Tendencies and Statistics&lt;/h1&gt;
&lt;p&gt;In any case, array indexing and regex compilation are the exceptions,
not the rule.
Almost all bounds checks failures may be logic errors.
Almost all regex compilation errors may be logic errors. Making these
functions panic would indeed do little damage, as panicking is almost
always the right move.&lt;/p&gt;
&lt;p&gt;But &amp;ndash; and this is a big &amp;ldquo;but&amp;rdquo; &amp;ndash; most functions, when they return
&lt;code&gt;Err&lt;/code&gt;, genuinely are signalling recoverable errors, and &lt;code&gt;unwrap&lt;/code&gt;
doesn&amp;rsquo;t discriminate &amp;ndash; it works equally well on all of them, in
the inappropriate situations as well as the appropriate situations.
With array indexing and regex compiling, the nature of the function being
called gives some indication of why it&amp;rsquo;s a logic error; with &lt;code&gt;unwrap&lt;/code&gt;,
there is no indication.&lt;/p&gt;
&lt;p&gt;Generally, this argument is in terms of statistics and human nature, not
in terms of absolutes. Turning an &lt;code&gt;Err&lt;/code&gt; into a panic should be rare, not
necessarily in terms of how often it happens, but in how often it shows up
in code. If it is common, either the programmer is using bad practices,
and should be using better practices, or the API has a design flaw, and
that needs to be fixed. In either case, &lt;code&gt;expect&lt;/code&gt; is better than &lt;code&gt;unwrap&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Ideally, we don&amp;rsquo;t get used to seeing &lt;code&gt;expect&lt;/code&gt; and &lt;code&gt;unwrap&lt;/code&gt; being used
all the time. We don&amp;rsquo;t get used to casually panicking on &lt;code&gt;Err&lt;/code&gt;, but instead
treat panicking like an operation that should be considered carefully,
whether once for all instances of a specific call (as in array indexing
or regex construction), or on a case-by-case basis (for other uses of
&lt;code&gt;expect&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Humans are creatures of habit and lazy by nature. &lt;code&gt;unwrap&lt;/code&gt; is a powerful
tool, a way to get around the type system, and as such, we might find
ourselves addicted to it.  We should treat even &lt;code&gt;expect&lt;/code&gt; as mildly
suspicious, something only to be used with consideration, something
to be wrapped behind an abstraction (as in the regex case). &lt;code&gt;unwrap&lt;/code&gt;
is even more dangerous, because it is easier, and given that legitimate
usage of &lt;code&gt;except&lt;/code&gt; should be rare (again in terms of lines of code, not
frequency of invocation) and hidden behind an abstraction when it is
common in frequency of invocation, I see no need for &lt;code&gt;unwrap&lt;/code&gt; to exist.&lt;/p&gt;
&lt;h1 id=&#34;context&#34;&gt;Context&lt;/h1&gt;
&lt;p&gt;I am aware that removing &lt;code&gt;unwrap&lt;/code&gt; from Rust is not a viable option at
this point, which is why I said that I wish it was never put in Rust to
begin with. I am aware that &lt;code&gt;unwrap&lt;/code&gt; is used in the Rust compiler,
and that there is no consensus to avoid &lt;code&gt;unwrap&lt;/code&gt; to the level that I
avoid it.&lt;/p&gt;
&lt;p&gt;I will however note that the documentation
of &lt;code&gt;unwrap&lt;/code&gt; comes with &lt;a href=&#34;https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap&#34;&gt;a warning not to use
it&lt;/a&gt;.
The warning is framed in terms of the fact
that &lt;code&gt;unwrap&lt;/code&gt; may panic, but the &lt;a href=&#34;https://doc.rust-lang.org/std/result/enum.Result.html#method.expect&#34;&gt;documentation of
&lt;code&gt;expect&lt;/code&gt;&lt;/a&gt;,
where this is equally true, does not come with such a warning.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Escalating an &lt;code&gt;Err&lt;/code&gt; to a panic is sometimes appropriate. But it should
be a considered choice, either on a function-by-function basis (through
a wrapper function calling &lt;code&gt;expect&lt;/code&gt; or a different choice of interface), or
on a case-by-case basis. In either case, &lt;code&gt;unwrap&lt;/code&gt; makes it too easy.&lt;/p&gt;
&lt;p&gt;Including an error message, and documenting why a panic is appropriate
(either through the error message or separately) should not be too much
to ask. If it is, that&amp;rsquo;s a code smell. The fact that &lt;code&gt;expect&lt;/code&gt; is more
difficult is a feature.&lt;/p&gt;
&lt;p&gt;In this article I have mentioned only briefly the other motivation for
using &lt;code&gt;expect&lt;/code&gt; &amp;ndash; better error messages for debugging.  I thought the
code smell argument was more important.  But debuggability can be very
important as well, so I&amp;rsquo;ll discuss it briefly here. I don&amp;rsquo;t think it&amp;rsquo;s
safe to assume backtraces will always be available. I don&amp;rsquo;t think it&amp;rsquo;s
safe to assume every use of &lt;code&gt;unwrap&lt;/code&gt; will print a useful error message,
even if it sometimes can. Maybe an individual use of &lt;code&gt;unwrap&lt;/code&gt; in one
context does not cause this problem, but once &lt;code&gt;unwrap&lt;/code&gt; is established
as acceptable, it opens the door for it to be abused.&lt;/p&gt;
&lt;p&gt;I personally do not use &lt;code&gt;unwrap&lt;/code&gt;, nor do I sign off on code that does.
I even prefer &lt;code&gt;expect(&amp;quot;foo&amp;quot;)&lt;/code&gt; to &lt;code&gt;unwrap&lt;/code&gt;, because it signals that it&amp;rsquo;s
off-the-cuff example code and shows that the person writing it knows
that more consideration would be needed to put it into production.
Please consider joining me in this approach.&lt;/p&gt;
&lt;p&gt;If you do not want to implement so strict a policy, and you think I&amp;rsquo;m too
extreme in this way, hopefully this article at least makes my argument
clearer, and explains why I do not call &lt;code&gt;unwrap&lt;/code&gt; but still feel
comfortable indexing my arrays. Hopefully also this has given food
for thought about &lt;code&gt;Result&lt;/code&gt;s, errors, and panics.&lt;/p&gt;
&lt;h1 id=&#34;edits&#34;&gt;Edits&lt;/h1&gt;
&lt;p&gt;This post has been edited to clarify certain things, including a
clarification in the opening to the post to make sure my overall position
is easily comprehensible.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Another Confusing Haskell Error Message</title>
      <link href="https://www.thecodedmessage.com/posts/haskell-error-message-2/" />
      <id>https://www.thecodedmessage.com/posts/haskell-error-message-2/</id>
      <updated>2022-06-17T00:00:00+00:00</updated>
      
      <summary type="html">&lt;h1 id=&#34;the-error-message&#34;&gt;The Error Message&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve written before about just how &lt;a href=&#34;https://www.thecodedmessage.com/posts/haskell-gripe/&#34;&gt;befuddling&lt;/a&gt;
Haskell error messages can be, especially for beginners. And now, even
though I have some professional Haskell development under my belt, I
ran across a Haskell error message that confused me for a bit, where I
had to get help. It&amp;rsquo;s clear to me now when I look at the error message
what it&amp;rsquo;s trying to say, but I legitimately was stumped by it, and so,
even though it&amp;rsquo;s embarrassing for me now, I feel the need to write about
how this error message could have been easier to understand:&lt;/p&gt;</summary>
      <content type="html">&lt;h1 id=&#34;the-error-message&#34;&gt;The Error Message&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve written before about just how &lt;a href=&#34;https://www.thecodedmessage.com/posts/haskell-gripe/&#34;&gt;befuddling&lt;/a&gt;
Haskell error messages can be, especially for beginners. And now, even
though I have some professional Haskell development under my belt, I
ran across a Haskell error message that confused me for a bit, where I
had to get help. It&amp;rsquo;s clear to me now when I look at the error message
what it&amp;rsquo;s trying to say, but I legitimately was stumped by it, and so,
even though it&amp;rsquo;s embarrassing for me now, I feel the need to write about
how this error message could have been easier to understand:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;frontend/src/Frontend/WordTiles.hs:87:25-45: error:
    • Could not deduce (HasDomEvent t () &amp;#39;ClickTag)
        arising from a use of ‘domEvent’
      from the context: (DomBuilder t m, PostBuild t m, MonadHold t m,
                         MonadFix m)
        bound by the type signature for:
                   app :: forall t (m :: * -&amp;gt; *).
                          (DomBuilder t m, PostBuild t m, MonadHold t m, MonadFix m) =&amp;gt;
                          m ()
        at frontend/src/Frontend/WordTiles.hs:(70,1)-(76,9)
    • In the expression: domEvent Click submit
      In an equation for ‘click’: click = domEvent Click submit
      In the second argument of ‘($)’, namely
        ‘do inputText &amp;lt;- fmap value $ inputElement $ def
            submit &amp;lt;- el &amp;#34;button&amp;#34; $ text &amp;#34;Submit&amp;#34;
            let click = domEvent Click submit
            pure $ current inputText &amp;lt;@ click’
   |
87 |             let click = domEvent Click submit
   |                         ^^^^^^^^^^^^^^^^^^^^^
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The code in question was in the Reflex FRP&amp;rsquo;s &amp;ldquo;widget&amp;rdquo; monad, defined
as usual by a number of monad typeclasses:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;app
  :: ( DomBuilder t m
     , PostBuild t m
     , MonadHold t m
     , MonadFix m
     )
  =&amp;gt; m ()
app = do
    let
        start = Game [] wordSet &amp;#34;PIETY&amp;#34;
        moveAll word (gm, _) = move word gm
    rec
        game &amp;lt;- foldDyn moveAll (start, []) newWord
        gameDisplay game
        newWord &amp;lt;- fmap (fmap T.unpack) $ el &amp;#34;div&amp;#34; $ do
            inputText &amp;lt;- fmap value $ inputElement $ def
            submit &amp;lt;- el &amp;#34;button&amp;#34; $ text &amp;#34;Submit&amp;#34;
            let click = domEvent Click submit
            pure $ current inputText &amp;lt;@ click
    pure ()
&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;my-confusion&#34;&gt;My Confusion&lt;/h1&gt;
&lt;p&gt;Some of you might already see the problem, especially those who know
Reflex. But I didn&amp;rsquo;t see it. My brain saw &lt;code&gt;(HasDomEvent t () &#39;ClickTag)&lt;/code&gt;
and completely misread it. I assumed it meant something like &amp;ldquo;with &lt;code&gt;t&lt;/code&gt;
as the tag, we can get the DOM event as &lt;code&gt;&#39;ClickTag&lt;/code&gt;.&amp;rdquo; I assumed that the
&lt;code&gt;()&lt;/code&gt; was irrelevant to understanding the type, indicating some sort of
optional type was not necessary to be provided.&lt;/p&gt;
&lt;p&gt;I then tried to address this by adding &lt;code&gt;(HasDomEvent t () &#39;ClickTag)&lt;/code&gt; to
the context of &lt;code&gt;app&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;app
  :: ( DomBuilder t m
     , PostBuild t m
     , MonadHold t m
     , MonadFix m
     , HasDomEvent t () &amp;#39;ClickTag
     )
  =&amp;gt; m ()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It wasn&amp;rsquo;t the issue.&lt;/p&gt;
&lt;p&gt;I had hoped this wasn&amp;rsquo;t the issue, but I thought it might be, and I
had no idea what the issue actually was. Maybe we just needed to list
all the DOM events &lt;code&gt;t&lt;/code&gt; can handle, I had thought. I should&amp;rsquo;ve noticed
it was &lt;code&gt;t&lt;/code&gt; and not &lt;code&gt;m&lt;/code&gt;, and I would expect &lt;code&gt;m&lt;/code&gt; to be involved in such a
context. I should have read the thing out loud in my head, and realized
that it wasn&amp;rsquo;t &lt;code&gt;t&lt;/code&gt; that didn&amp;rsquo;t have the DOM event of &lt;code&gt;&#39;ClickTag&lt;/code&gt;, but
&lt;code&gt;()&lt;/code&gt;. But I didn&amp;rsquo;t. My eyes kind of glazed over at the complicated
typeclass expression. I just didn&amp;rsquo;t think.&lt;/p&gt;
&lt;h1 id=&#34;the-solution&#34;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;The problem, a friend had to tell me, was nothing to do with &lt;code&gt;t&lt;/code&gt;
and everything to do with &lt;code&gt;()&lt;/code&gt;. &lt;code&gt;submit&lt;/code&gt; was not, as I had thought,
a representation of the DOM element I had created with a button. To do
that, you need to call &lt;code&gt;el&#39;&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;(submit, _) &amp;lt;- el&amp;#39; &amp;#34;button&amp;#34; $ text &amp;#34;Submit&amp;#34;
let click = domEvent Click submit
pure $ current inputText &amp;lt;@ click
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;submit&lt;/code&gt;, gotten from &lt;code&gt;el&lt;/code&gt;, was actually of type &lt;code&gt;()&lt;/code&gt;. And, of course,
you can&amp;rsquo;t get any DOM event out of &lt;code&gt;()&lt;/code&gt;, let alone a &lt;code&gt;Click&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;better-error-messages&#34;&gt;Better Error Messages&lt;/h1&gt;
&lt;p&gt;But while I left this situation with take-aways for myself, to better
read Haskell error messages in the future, I was also frustrated
at the Haskell compiler, especially in comparison to the Rust compiler
I have gotten used to recently through my job.&lt;/p&gt;
&lt;h2 id=&#34;list-involved-types&#34;&gt;List Involved Types&lt;/h2&gt;
&lt;p&gt;How on earth did it not indicate at all that &lt;code&gt;(HasDomEvent t () &#39;ClickTag)&lt;/code&gt;
was a problem with the type of &lt;code&gt;submit&lt;/code&gt;? Sure, the constraint &amp;ldquo;arose&amp;rdquo;
from the type of &lt;code&gt;domEvent&lt;/code&gt;, but &lt;code&gt;submit&lt;/code&gt; is clearly an important value
involved in making the type not work.&lt;/p&gt;
&lt;p&gt;This is easier to implement than a Haskell person might think. I
understand that it&amp;rsquo;s unclear which type &amp;ldquo;caused&amp;rdquo; the problem from a
human perspective.  So why not list them all?  Just a laundry list of
inferred types would&amp;rsquo;ve been helpful: I would have seen that &lt;code&gt;submit&lt;/code&gt;
was of type &lt;code&gt;()&lt;/code&gt;, and that would&amp;rsquo;ve helped me through the situation. Is
that too much to ask? Something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Related types:
domEvent :: HasDomEvent t a =&amp;gt; EventName en -&amp;gt; a -&amp;gt; Event t (EventResultType en)
Click :: EventName ClickTag
submit :: ()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Any two of those types would have given me the hint I needed. Really,
either &lt;code&gt;domEvent&lt;/code&gt; or &lt;code&gt; submit&lt;/code&gt; would have enabled me to figure it out.&lt;/p&gt;
&lt;h2 id=&#34;warn-about--bindings&#34;&gt;Warn About &lt;code&gt;()&lt;/code&gt; Bindings&lt;/h2&gt;
&lt;p&gt;Similarly, how on earth was I allowed to write this line without a warning:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;submit &amp;lt;- el &amp;#34;button&amp;#34; $ text &amp;#34;Submit&amp;#34;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;submit&lt;/code&gt; is invariately &lt;code&gt;()&lt;/code&gt;. Shouldn&amp;rsquo;t binding a &lt;code&gt;()&lt;/code&gt; value be at least
a warning? In what possible situation would you want to do that? I know
that situations exist, especially situations where a type is sometimes
&lt;code&gt;()&lt;/code&gt;, but this type is invariably &lt;code&gt;()&lt;/code&gt;, and I have &lt;code&gt;-Wall&lt;/code&gt; turned on in
this project. I want warnings for things that there are occasionally
legitimate use cases for. Binding a name to &lt;code&gt;()&lt;/code&gt;, especially when it&amp;rsquo;s
from a function call and not literally &lt;code&gt;let unit = ()&lt;/code&gt;, has got to
be a mistake 99 times out of 100.&lt;/p&gt;
&lt;p&gt;This is apparently not a warning in Rust either, and I am confused by that,
because Rust is normally better about its warnings:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn foo() {
}

fn main() {
    let x = foo(); // Compiles without warning!
    drop(x);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I think it would be a reasonable and useful warning in both programming
languages. The opposite situation already provokes a warning in Haskell,
where you have an action in a &lt;code&gt;do&lt;/code&gt;-block that returns a value and you
implicitly ignore it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~/Writing/TheCodedMessage/content/posts]$ ghci -Wall
GHCi, version 8.8.4: https://www.haskell.org/ghc/  :? for help
Prelude&amp;gt; do { pure &amp;#39;x&amp;#39;; pure () }

&amp;lt;interactive&amp;gt;:1:6: warning: [-Wunused-do-bind]
    A do-notation statement discarded a result of type ‘Char’
    Suppress this warning by saying ‘_ &amp;lt;- pure &amp;#39;x&amp;#39;’
Prelude&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It only makes sense that the converse mistake, which is even more likely
to be a mistake, also have a warning.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Error messages are an extremely important part of a programming
language, both for adoption and for programmer efficiency. Part of
the point in working in a strongly-typed language with a sophisticated
type system, like Rust or Haskell, is supposed to be that we discover
most of our problems through compiler error messages, rather than
through runtime bugs. So most of our troubleshooting will happen at
compile time, grappling with these error message. This makes error
messages in Haskell more important than in the average programming
language, and makes the standard for good error messages even higher.
We can do better than the status quo, and we should.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Command Line Interface UXes Need Love, Too</title>
      <link href="https://www.thecodedmessage.com/posts/2022-06-16-programming---cli/" />
      <id>https://www.thecodedmessage.com/posts/2022-06-16-programming---cli/</id>
      <updated>2022-06-16T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;It took me a long time to admit to myself that the venerable Unix
command line interface is stuck in the past and in need of a refresh,
but it was a formative moment in my development as a programmer when I
finally did. Coming from that perspective, I am very glad that there is a new
wave of enthusiasm (coming especially from the Rust community) to build
new tools that are fixing some of the problems with this very old and
established user-interface.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;It took me a long time to admit to myself that the venerable Unix
command line interface is stuck in the past and in need of a refresh,
but it was a formative moment in my development as a programmer when I
finally did. Coming from that perspective, I am very glad that there is a new
wave of enthusiasm (coming especially from the Rust community) to build
new tools that are fixing some of the problems with this very old and
established user-interface.&lt;/p&gt;
&lt;h1 id=&#34;the-role-of-the-unix-cli-interface&#34;&gt;The Role of the Unix CLI Interface&lt;/h1&gt;
&lt;p&gt;To describe the Unix command line interface, &amp;ldquo;venerable&amp;rdquo; is definitely
the right word: many programmers (including myself at some points of
my life) have an awe of Unix and its role in computing history that has
sometimes bordered on veneration.&lt;/p&gt;
&lt;p&gt;Since the &lt;a href=&#34;https://en.wikipedia.org/wiki/Unix&#34;&gt;Unix&lt;/a&gt;
operating system began development at Bell Labs in 1969, it has gone
viral. That&amp;rsquo;s probably an understatement: Most modern operating
systems descend from this original Unix, either directly through
gradual code change (macOS and iOS are descended it from it through
&lt;a href=&#34;https://en.wikipedia.org/wiki/Berkeley_Software_Distribution&#34;&gt;BSD&lt;/a&gt;),
or through &lt;a href=&#34;https://en.wikipedia.org/wiki/Linux&#34;&gt;Linux&lt;/a&gt; (the
kernel behind most servers and behind Android and ChromeOS) and
its accompanying usermode software (much of which was part of the
&lt;a href=&#34;https://www.gnu.org/&#34;&gt;GNU&lt;/a&gt; project), which were designed to work like
Unix due its familiarity for users and programmers.&lt;/p&gt;
&lt;p&gt;Unix was and is billed not just as an operating system, but a
&lt;a href=&#34;https://en.wikipedia.org/wiki/Unix_philosophy&#34;&gt;philosophy&lt;/a&gt;. Among other
things, its command line interface has been held up time and time again
as an example of good design practices and an ideal realization of this
philosophy, with its developer- and administrator-friendly orientation
towards plain text files and with its modularity, especially as embodied
in the concept of pipelining.&lt;/p&gt;
&lt;p&gt;And as a result, when people say they know &amp;ldquo;the command line,&amp;rdquo;
it&amp;rsquo;s almost certainly the Unix command-line interface that
they&amp;rsquo;re talking about. And what&amp;rsquo;s more, many of us were taught
it from texts that gushed about how great it is. But even the
Unix command line interface, though part of a &lt;a href=&#34;https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/&#34;&gt;well-established
standard&lt;/a&gt;,
the topic of many books, and used by and intimately familiar to millions
of programmers and admins across generations, is, in the end, just
another computer interface for users and developers. And it has its flaws.&lt;/p&gt;
&lt;h1 id=&#34;a-disappointing-ambiguity&#34;&gt;A Disappointing Ambiguity&lt;/h1&gt;
&lt;p&gt;As I alluded to before, when I was a much younger programmer, I had an
awe-struck veneration for Unix. One of my colleagues at an early job in my
career referred to me as our company&amp;rsquo;s &amp;ldquo;Unix philosopher.&amp;rdquo; While I wasn&amp;rsquo;t
sure whether he meant it as a compliment, at the time, I took it as one.&lt;/p&gt;
&lt;p&gt;The first flaw that really got my attention in the Unix command line had
to do with the &lt;code&gt;mv&lt;/code&gt; command. I&amp;rsquo;m going to take some time explaining this
flaw in detail, as it&amp;rsquo;s somewhat subtle, and as discovering it was
a formative moment for me in my development as a programmer.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mv&lt;/code&gt;, as many of you know, is short for &amp;ldquo;move.&amp;rdquo;  And while its job indeed
includes moving files from one place to another, due to idiosyncracies
of the Unix file system (if they can be called idiosyncracies when most
file systems followed Unix&amp;rsquo;s lead on this), moving files and renaming
files are closely related operations under the hood, causing the &lt;code&gt;mv&lt;/code&gt;
command to be both the &amp;ldquo;move&amp;rdquo; command and the &amp;ldquo;rename&amp;rdquo; command:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Assume a file called &amp;#39;draft-file&amp;#39;
# Assume a directory called &amp;#39;final-docs&amp;#39;

# Rename &amp;#39;draft-file&amp;#39; to &amp;#39;final-file&amp;#39; and put it in &amp;#39;final-docs&amp;#39;
mv draft-file final-file # rename &amp;#39;draft-file&amp;#39; to &amp;#39;final-file&amp;#39;
mv final-file final-docs # move &amp;#39;final-file&amp;#39; into &amp;#39;final-docs&amp;#39; directory

# Alternatively, one step:
mv draft-file final-docs/final-file
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As you can see, there is no distinction between these operations.
There is no option that you must enable to get the &amp;ldquo;moving&amp;rdquo; feature as
opposed to the &amp;ldquo;renaming&amp;rdquo; feature. And this can result in surprises, which
are &lt;a href=&#34;https://en.wikipedia.org/wiki/Principle_of_least_astonishment&#34;&gt;bad&lt;/a&gt;
in software development.&lt;/p&gt;
&lt;p&gt;Consider this command again:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;mv draft-file final-file
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What does it do? It changes the name of the file from &lt;code&gt;draft-file&lt;/code&gt;
to &lt;code&gt;final-file&lt;/code&gt;, keeping it in the same directory, right? Well,
probably, and that&amp;rsquo;s almost certainly what the user intended, but
what if someone, accidentally or intentionally, had created a
directory called &lt;code&gt;final-file&lt;/code&gt;? That command would be interpreted
instead as moving &lt;code&gt;draft-file&lt;/code&gt; into the &lt;code&gt;final-file&lt;/code&gt; directory:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ # Rename operation
$ touch draft-file
$ ls
draft-file
$ mv draft-file final-file
$ ls
final-file
$ ls final-file
final-file
$ rm final-file
$
$ # Move operation
$ mkdir final-file # Imagine someone else did this, or it was done by accident
$ touch draft-file
$ mv draft-file final-file
$ ls
final-file
$ ls final-file
draft-file
$ rm final-file
rm: cannot remove &amp;#39;final-file&amp;#39;: Is a directory
$ rm -rf final-file
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Notice that if there is no color-coding enabled, a simple &lt;code&gt;ls&lt;/code&gt; command
doesn&amp;rsquo;t even distinguish the two situations, so you can&amp;rsquo;t tell which
one happened without issuing a more specific command, as &lt;code&gt;ls&lt;/code&gt; also has
a dual role: it can either show you the names of the files you specify,
if they are present, or it can show you the files in a directory you
specify. The &lt;code&gt;-d&lt;/code&gt; option disambiguates that you want the names and not
the contents, but the default is still ambiguous.&lt;/p&gt;
&lt;p&gt;In the case of the &lt;code&gt;mv&lt;/code&gt; command, this potentially could even be a security
vulnerability in a shell script (which is admittedly not a very secure
platform). It is in any case an unnecessary complication.&lt;/p&gt;
&lt;p&gt;The GNU version of &lt;code&gt;mv&lt;/code&gt; has a &lt;code&gt;-t&lt;/code&gt; option to indicate that the destination
is not to be interpreted as a directory to put things in, and a &lt;code&gt;-T&lt;/code&gt; option
to show unambiguous intent for a target directory to be used. But these
are extensions; the POSIX standard manual page for &lt;code&gt;mv&lt;/code&gt; doesn&amp;rsquo;t mention them.&lt;/p&gt;
&lt;p&gt;And while this GNU extension is helpful, especially in scripts that you
know will only be run with the GNU version of &lt;code&gt;mv&lt;/code&gt; (that is, not on macOS),
I don&amp;rsquo;t think it goes far enough. Most people don&amp;rsquo;t know about them,
and the possibility of surprise is still there.&lt;/p&gt;
&lt;h1 id=&#34;disillusioned&#34;&gt;Disillusioned&lt;/h1&gt;
&lt;p&gt;When I realized this, it created a huge hole in my previous (admittedly
unreasonable) esteem for the Unix command line interface. I realized
that the ideal solution was something impractical, almost unthinkable
to the younger version of me: &lt;code&gt;mv&lt;/code&gt; should be deprecated in favor of two
commands, one to do renaming, and one to do targeted directory-dropping.&lt;/p&gt;
&lt;p&gt;This glitch in the &lt;code&gt;mv&lt;/code&gt; command is just a gotcha to be aware of,
one of many minor flaws to dance around when shell scripting. But I
remember it strongly, because rather than being warned about it in a
book, I discovered it myself, and therefore it was the distinct moment I
realized that the command line interface would need to be improved at some
point.  And once the metaphorical levee was broken, I started noticing
many inconveniences and problems in the traditional Unix CLI tools,
often more relevant to my day-to-day workflow than this minor gotcha.&lt;/p&gt;
&lt;p&gt;I ultimately came to read more critical sources about Unix, such as the
famous &lt;a href=&#34;https://web.mit.edu/~simsong/www/ugh.pdf&#34;&gt;UNIX-HATERS Handbook&lt;/a&gt;,
and similar sources that emphasized the problems.  And I&amp;rsquo;m very
glad I went through this process, because before this, I was a naive
CLI user and shell-scripter, trusting the system way more than I should,
leaving myself open to serious problems.&lt;/p&gt;
&lt;p&gt;Many Unix commands have gotchas and inconveniences, some I knew
about before this revelation and brushed aside, others that I
found out about later. &lt;code&gt;tar&lt;/code&gt; has its &lt;a href=&#34;https://xkcd.com/1168/&#34;&gt;idiosyncratic traditional
syntax&lt;/a&gt; that many, many scripts (and people)
still use, and inconsistency between platforms on whether you need
&lt;code&gt;-z&lt;/code&gt; to unpack a compressed archive. The way the shell itself worked
also contained gotchas: What happens if you have files whose names
start with a &lt;code&gt;-&lt;/code&gt;? (Answer: Their names get misinterpreted as options,
even if you didn&amp;rsquo;t type them but simply included them accidentally in
a wildcard expansion.)&lt;/p&gt;
&lt;p&gt;Among the more practical issues that particularly effect me, I want
to emphasize two in particular: Why is &lt;code&gt;find&lt;/code&gt;&amp;rsquo;s syntax so gnarly, so
that you have to type out &lt;code&gt;--name&lt;/code&gt; and explicitly specify the current
directory? Why is it so hard to get &lt;code&gt;grep&lt;/code&gt; to not display the pages-long
lines of minimized Javascript or similar files when I want to only
display the shorter lines from actual source files?&lt;/p&gt;
&lt;h1 id=&#34;the-future&#34;&gt;The Future&lt;/h1&gt;
&lt;p&gt;Luckily, improvement is on its way. For the last two cherry-picked
examples, there are new re-conceptions of &lt;code&gt;find&lt;/code&gt; and &lt;code&gt;grep -r&lt;/code&gt;
that fix them (with new names, of course, so they&amp;rsquo;re not beholden
to interface-compatibility), and I recommend them (dare I say such
blasphemy?) over the traditional equivalents:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sharkdp/fd&#34;&gt;&lt;code&gt;fd-find&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/BurntSushi/ripgrep&#34;&gt;&lt;code&gt;ripgrep&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Don&amp;rsquo;t let their long names dissuade you; they are commonly installed
as &lt;code&gt;fd&lt;/code&gt; and &lt;code&gt;rg&lt;/code&gt;, respectively, and come with such modern features as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Normal command line syntax (&lt;code&gt;fd&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Integration with &lt;code&gt;git&lt;/code&gt;, the &lt;em&gt;de facto&lt;/em&gt; standard version control system, by ignoring &lt;code&gt;.git&lt;/code&gt; and &lt;code&gt;.gitignore&lt;/code&gt;&amp;rsquo;d files by default (both)&lt;/li&gt;
&lt;li&gt;Line length maximums (&lt;code&gt;rg&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Modern leveraging of multithreading (both)&lt;/li&gt;
&lt;li&gt;Better performance than their traditional counterparts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are the only new Rust-based commands I&amp;rsquo;ve tried, but they&amp;rsquo;ve
already vastly improved my workflow, so that I miss having them
(&lt;code&gt;fd&lt;/code&gt; especially) when SSH&amp;rsquo;d into relatively minimalist embedded
devices. And I have reason to hope there&amp;rsquo;s more gems out there
as part of this explosive movement to implement &lt;a href=&#34;https://gist.github.com/sts10/daadbc2f403bdffad1b6d33aff016c0a&#34;&gt;new Rust-based
commands&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Whether people are doing this to improve their Rust chops, or because
they&amp;rsquo;ve felt a need for a long time and Rust is just their PL of choice,
it&amp;rsquo;s good to see some actual evolution in my day-to-day experience
as a Unix CLI user. It hasn&amp;rsquo;t fixed &lt;code&gt;mv&lt;/code&gt; &amp;ndash; yet &amp;ndash; but it&amp;rsquo;s good to
see it evolving.&lt;/p&gt;
&lt;p&gt;On the implementation side of things, I am also very
happy to see a Rust project to &lt;a href=&#34;https://github.com/uutils/coreutils&#34;&gt;reimplement the standard
&lt;code&gt;coreutils&lt;/code&gt;&lt;/a&gt;. The C implementations
undoubtedly leave some performance and stability on the table, and a
new implementation is long over-due. A fresh implementation of these
utilities will hopefully also spark improvements to the interfaces.&lt;/p&gt;
&lt;h2 id=&#34;and-meanwhile-in-git-land&#34;&gt;And Meanwhile, in &lt;code&gt;git&lt;/code&gt;-land&lt;/h2&gt;
&lt;p&gt;On a related positive note, I learned very recently (in 2022)
that &lt;code&gt;git&lt;/code&gt; has (in 2019) fixed a problem similar to &lt;code&gt;mv&lt;/code&gt;s:
&lt;code&gt;git checkout&lt;/code&gt;, ambiguous in a similar way, has been rendered
unnecessary by the less ambiguous &lt;a href=&#34;https://tanzu.vmware.com/developer/blog/git-switch-and-restore-an-improved-user-experience/&#34;&gt;&lt;code&gt;git switch&lt;/code&gt; and &lt;code&gt;git restore&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Trivia About Rust Types: An (Authorized) Transcription of Jon Gjengset&#39;s Twitter Thread</title>
      <link href="https://www.thecodedmessage.com/posts/trivia-rust-types/" />
      <id>https://www.thecodedmessage.com/posts/trivia-rust-types/</id>
      <updated>2022-06-06T00:00:00+00:00</updated>
      
      <summary type="html">&lt;h1 id=&#34;preface-by-jimmy-hartzell&#34;&gt;Preface (by Jimmy Hartzell)&lt;/h1&gt;
&lt;p&gt;I am a huge fan of Jon Gjengset&amp;rsquo;s &lt;a href=&#34;https://nostarch.com/rust-rustaceans&#34;&gt;Rust for
Rustaceans&lt;/a&gt;,
an excellent book to bridge the gap between beginner
Rust programming skills and becoming a fully-functional
member of the Rust community.  He&amp;rsquo;s famous for his &lt;a href=&#34;https://www.youtube.com/playlist?app=desktop&amp;amp;list=PLqbS7AVVErFiWDOAVrPt7aYmnuuOLYvOa&#34;&gt;YouTube
channel&lt;/a&gt;
as well; I&amp;rsquo;ve heard good things about it (watching video
instruction isn&amp;rsquo;t really my thing personally).  I have also
greatly enjoyed his &lt;a href=&#34;https://twitter.com/jonhoo&#34;&gt;Twitter feed&lt;/a&gt;,
and especially have enjoyed the thread surrounding &lt;a href=&#34;https://twitter.com/jonhoo/status/1532761983606411264&#34;&gt;this
tweet&lt;/a&gt;:&lt;/p&gt;</summary>
      <content type="html">&lt;h1 id=&#34;preface-by-jimmy-hartzell&#34;&gt;Preface (by Jimmy Hartzell)&lt;/h1&gt;
&lt;p&gt;I am a huge fan of Jon Gjengset&amp;rsquo;s &lt;a href=&#34;https://nostarch.com/rust-rustaceans&#34;&gt;Rust for
Rustaceans&lt;/a&gt;,
an excellent book to bridge the gap between beginner
Rust programming skills and becoming a fully-functional
member of the Rust community.  He&amp;rsquo;s famous for his &lt;a href=&#34;https://www.youtube.com/playlist?app=desktop&amp;amp;list=PLqbS7AVVErFiWDOAVrPt7aYmnuuOLYvOa&#34;&gt;YouTube
channel&lt;/a&gt;
as well; I&amp;rsquo;ve heard good things about it (watching video
instruction isn&amp;rsquo;t really my thing personally).  I have also
greatly enjoyed his &lt;a href=&#34;https://twitter.com/jonhoo&#34;&gt;Twitter feed&lt;/a&gt;,
and especially have enjoyed the thread surrounding &lt;a href=&#34;https://twitter.com/jonhoo/status/1532761983606411264&#34;&gt;this
tweet&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Okay, learning time! Name a @rustlang
type (can be generic), and I&amp;rsquo;ll (try to) tell you something you didn&amp;rsquo;t
know about that type!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What great fun!&lt;/p&gt;
&lt;p&gt;I immediately felt that this thread should have a
transcription outside of social media (Jon Gjengset already did a &lt;a href=&#34;https://www.reddit.com/r/rust/comments/v4dnaj/twitter_thread_with_trivia_about_rust_types/&#34;&gt;Reddit
transcription&lt;/a&gt;),
and so I asked him if he had any plans to turn
it into a blog post, and failing that, whether &lt;a href=&#34;https://twitter.com/thecodedmessage/status/1533080530513801219&#34;&gt;I
could&lt;/a&gt;.
Much to my surprise, &lt;a href=&#34;https://twitter.com/jonhoo/status/1533139200811290625&#34;&gt;he gave me the
go-ahead&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So I have done so, and this is the blog post!  It wasn&amp;rsquo;t even boring,
because I learned so much as I copied the entries!  Minor edits have
been made to add formatting and adapt links to how blogs work rather
than how Twitter works. This is taken from the Reddit version. My
&lt;a href=&#34;https://www.thecodedmessage.com/2022-06-06-programming---trivia-rust-types.md&#34;&gt;markdown source&lt;/a&gt;
is also available.&lt;/p&gt;
&lt;p&gt;So, without further ado, Jon Gjengset&amp;rsquo;s &amp;ldquo;Trivia About Rust Types.&amp;rdquo;&lt;/p&gt;
&lt;h1 id=&#34;trivia-about-rust-types-by-jon-gjengset&#34;&gt;Trivia About Rust Types (by Jon Gjengset)&lt;/h1&gt;
&lt;h2 id=&#34;stdfmtdebug&#34;&gt;&lt;code&gt;std::fmt::Debug&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that the Formatter argument to &lt;code&gt;Debug::fmt&lt;/code&gt; makes it really easy to customize debug representations for structs, enums, lists, and sets? See the &lt;code&gt;debug_*&lt;/code&gt; methods on it.&lt;/p&gt;
&lt;h2 id=&#34;formatter&#34;&gt;&lt;code&gt;Formatter&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;std::fmt::Formatter&lt;/code&gt; is super easy to use if you want more control over debugging for a custom type? For example, to emit a &amp;ldquo;list-like&amp;rdquo; type, just &lt;code&gt;Formatter::debug_list().entries(self.0.iter()).finish()&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;optiont&#34;&gt;&lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt; implements &lt;code&gt;IntoIterator&lt;/code&gt; yielding 0/1
elements, and you can then call &lt;code&gt;Iterator::flatten&lt;/code&gt; to make that be 0/n
elements if T: IntoIterator?&lt;/p&gt;
&lt;h2 id=&#34;type-emptytuplelist--vec&#34;&gt;&lt;code&gt;type EmptyTupleList = Vec&amp;lt;()&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that since &lt;code&gt;()&lt;/code&gt; is a zero-sized type, and the vector never actually has to store any data, the capacity of &lt;code&gt;Vec&amp;lt;()&amp;gt;&lt;/code&gt; is &lt;code&gt;usize::MAX&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id=&#34;t&#34;&gt;&lt;code&gt;T&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;T&lt;/code&gt; doesn&amp;rsquo;t imply ownership? When we say a type is
generic over &lt;code&gt;T&lt;/code&gt;, that &lt;code&gt;T&lt;/code&gt; can just as easily be a reference to something
on the stack, and the type system will still be happy. Even &lt;code&gt;T: &#39;static&lt;/code&gt;
doesn&amp;rsquo;t imply owned — consider &lt;code&gt;&amp;amp;&#39;static str&lt;/code&gt; for example.&lt;/p&gt;
&lt;p&gt;[Reminds me of this &lt;a href=&#34;https://github.com/pretzelhammer/rust-blog/blob/master/posts/common-rust-lifetime-misconceptions.md&#34;&gt;excellent article&lt;/a&gt; -Jimmy]&lt;/p&gt;
&lt;h2 id=&#34;stdsyncmpscchannelsender&#34;&gt;&lt;code&gt;std::sync::mpsc::channel::Sender&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;std::sync::mpsc&lt;/code&gt; has had a &lt;a href=&#34;https://github.com/rust-lang/rust/issues/39364&#34;&gt;known bug since
2017&lt;/a&gt;, and that the
implementation may actually be replaced entirely with the crossbeam
channel implementation? &lt;a href=&#34;https://github.com/rust-lang/rust/pull/93563&#34;&gt;https://github.com/rust-lang/rust/pull/93563&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;u128&#34;&gt;&lt;code&gt;u128&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that even though we got &lt;code&gt;u128&lt;/code&gt; a long time ago now, we
still don&amp;rsquo;t have &lt;code&gt;repr(128)&lt;/code&gt;? &lt;a href=&#34;https://github.com/rust-lang/rust/issues/56071&#34;&gt;https://github.com/rust-lang/rust/issues/56071&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;stdffiosstring&#34;&gt;&lt;code&gt;std::ffi::OsString&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that there are per-platform extension traits
for &lt;code&gt;OsString&lt;/code&gt; that bake in the assumptions you can safely
make on that platform? Such as &lt;a href=&#34;https://doc.rust-lang.org/std/os/unix/ffi/trait.OsStringExt.html&#34;&gt;strings being &lt;code&gt;[u8]&lt;/code&gt; on
Unix&lt;/a&gt;
and &lt;a href=&#34;https://doc.rust-lang.org/std/os/windows/ffi/trait.OsStringExt.html&#34;&gt;UTF-16 on
Windows&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;stdptrnonnull&#34;&gt;&lt;code&gt;std::ptr::NonNull&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that one of the super neat features of &lt;code&gt;NonNull&lt;/code&gt; is that
it enables the same niche optimization that regular references and the
&lt;code&gt;NonZero*&lt;/code&gt; types get where &lt;code&gt;Option&amp;lt;NonNull&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt; is the same size as &lt;code&gt;*mut T&lt;/code&gt;?&lt;/p&gt;
&lt;h2 id=&#34;cowt&#34;&gt;&lt;code&gt;Cow&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that there used to be a special
&lt;code&gt;IntoCow&lt;/code&gt; trait, but it was deprecated before 1.0 was
released! &lt;a href=&#34;https://github.com/rust-lang/rust/issues/27735&#34;&gt;https://github.com/rust-lang/rust/issues/27735&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;boxt&#34;&gt;&lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt; is a &lt;code&gt;#[fundamental]&lt;/code&gt; type, which means that
it&amp;rsquo;s exempt from the normal rules that don&amp;rsquo;t allow you to implement
foreign traits for foreign types (assuming T is a local type)?&lt;/p&gt;
&lt;h2 id=&#34;stdprocesschild&#34;&gt;&lt;code&gt;std::process::Child&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;std&lt;/code&gt; has
&lt;a href=&#34;https://github.com/rust-lang/rust/blob/master/library/std/src/sys/unix/process/process_unix.rs&#34;&gt;three different ways&lt;/a&gt;
to spawn a
child process on Linux (&lt;code&gt;posix_spawn&lt;/code&gt;, &lt;code&gt;clone3&lt;/code&gt;/&lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;fork&lt;/code&gt;/&lt;code&gt;exec&lt;/code&gt;)
depending on what capabilities your kernel version has?&lt;/p&gt;
&lt;h2 id=&#34;pint&#34;&gt;&lt;code&gt;Pin&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that the name &lt;code&gt;Pin&lt;/code&gt; (and the name &lt;code&gt;Unpin&lt;/code&gt;) where
both heavily debated? Pin was almost called Pinned, for example. &lt;a href=&#34;https://github.com/rust-lang/rust/issues/55766#issuecomment-438789462&#34;&gt;The
discussion&lt;/a&gt;
is an interesting read now after the fact.&lt;/p&gt;
&lt;h2 id=&#34;vect&#34;&gt;&lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;Vec::swap_remove&lt;/code&gt; is way faster than &lt;code&gt;Vec::remove&lt;/code&gt;
if you can tolerate changes to ordering?&lt;/p&gt;
&lt;p&gt;Did you know that the smallest non-zero
capacity for a &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt; &lt;a href=&#34;https://github.com/rust-lang/rust/blob/9a74608543d499bcc7dd505e195e8bfab9447315/library/alloc/src/raw_vec.rs#L106-L110&#34;&gt;depends on the size of
&lt;code&gt;T&lt;/code&gt;&lt;/a&gt;?&lt;/p&gt;
&lt;h2 id=&#34;cstr&#34;&gt;&lt;code&gt;CStr&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;CStr::default&lt;/code&gt; creates a &lt;code&gt;CStr&lt;/code&gt; that points to a
const string &lt;code&gt;&amp;quot;\0&amp;quot;&lt;/code&gt; stored in the binary text segment, which means all
default &lt;code&gt;CStr&lt;/code&gt;s point to the same (non-null) string!&lt;/p&gt;
&lt;h2 id=&#34;fora-sometraita&#34;&gt;&lt;code&gt;for&amp;lt;&#39;a&amp;gt; SomeTrait&amp;lt;&#39;a&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that you can use &lt;code&gt;for&amp;lt;&#39;a&amp;gt;&lt;/code&gt; to say that a bound has to hold
for any lifetime &lt;code&gt;&#39;a&lt;/code&gt;, not just a specific lifetime you happen to have
available at the time. For example, &lt;code&gt;&amp;lt;T&amp;gt; for&amp;lt;&#39;a&amp;gt;: &amp;amp;&#39;a T: Read&lt;/code&gt; says that
any shared reference to a &lt;code&gt;T&lt;/code&gt; must implement &lt;code&gt;Read&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;this-monstrous-warp-type&#34;&gt;&lt;a href=&#34;https://gist.githubusercontent.com/fasterthanlime/de0955a8b29d0d66110983ebb5fae442/raw/1827a3afbca01cd42eafd0905cfdc451da805cb7/gistfile1.txt&#34;&gt;This monstrous warp type&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that the trailing commas you see in some places in there,
&lt;code&gt;,)&lt;/code&gt;, are to &lt;a href=&#34;https://doc.rust-lang.org/nightly/reference/expressions/tuple-expr.html&#34;&gt;distinguish one-element tuples from regular parenthetical
expressions&lt;/a&gt;?&lt;/p&gt;
&lt;h2 id=&#34;fnonce&#34;&gt;&lt;code&gt;FnOnce&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that until Rust 1.35, you couldn&amp;rsquo;t call a &lt;code&gt;Box&amp;lt;dyn FnOnce&amp;gt;&lt;/code&gt; and needed a special type (&lt;code&gt;FnBox&lt;/code&gt;) for it! This was
because it requires &amp;ldquo;unsized rvalues&amp;rdquo; to implement, which are still
unstable today. &lt;a href=&#34;https://github.com/rust-lang/rust/issues/28796&#34;&gt;https://github.com/rust-lang/rust/issues/28796&lt;/a&gt; +
&lt;a href=&#34;https://github.com/rust-lang/rust/issues/48055&#34;&gt;https://github.com/rust-lang/rust/issues/48055&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;f32&#34;&gt;&lt;code&gt;f32&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that in Rust 1.62 we&amp;rsquo;ll get a deterministic ordering function
for floating point numbers? &lt;a href=&#34;https://github.com/rust-lang/rust/pull/95431&#34;&gt;https://github.com/rust-lang/rust/pull/95431&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;arct&#34;&gt;&lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;Arc&lt;/code&gt; has a &lt;code&gt;make_mut&lt;/code&gt; method that effectively gives
you copy-on-write? Given a &lt;code&gt;&amp;amp;mut Arc&amp;lt;T&amp;gt;&lt;/code&gt;, it will either give you &lt;code&gt;&amp;amp;mut T&lt;/code&gt; if there are no other Arcs, or it will clone &lt;code&gt;T&lt;/code&gt;, make the &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt;
point to that new &lt;code&gt;T&lt;/code&gt;, and then give you a &lt;code&gt;&amp;amp;mut&lt;/code&gt; to it!&lt;/p&gt;
&lt;h2 id=&#34;heading&#34;&gt;&lt;code&gt;!&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;std::convert::Infallible&lt;/code&gt; is the &amp;ldquo;original&amp;rdquo; &lt;code&gt;!&lt;/code&gt;, and that
the plan is to one day replace &lt;code&gt;Infallible&lt;/code&gt; with a type alias for &lt;code&gt;!&lt;/code&gt;?&lt;/p&gt;
&lt;h2 id=&#34;fn&#34;&gt;&lt;code&gt;fn&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Specifically, did you know that the name of a function is not an
&lt;code&gt;fn&lt;/code&gt;? It&amp;rsquo;s a &lt;code&gt;FnDef&lt;/code&gt;, which can then be
&lt;a href=&#34;https://github.com/rust-lang/rust/issues/86654#issuecomment-869173835&#34;&gt;coerced to a &lt;code&gt;FnPtr&lt;/code&gt;&lt;/a&gt;?&lt;/p&gt;
&lt;h2 id=&#34;phantomdata&#34;&gt;&lt;code&gt;PhantomData&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that it&amp;rsquo;s actually kind of tricky to define &lt;code&gt;PhantomData&lt;/code&gt; yourself: &lt;a href=&#34;https://github.com/dtolnay/ghost&#34;&gt;https://github.com/dtolnay/ghost&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;u32&#34;&gt;&lt;code&gt;u32&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;u32&lt;/code&gt; now has associated constants for &lt;code&gt;MIN&lt;/code&gt; and &lt;code&gt;MAX&lt;/code&gt;,
so you no longer need to use &lt;code&gt;std::u32::MIN&lt;/code&gt; and can use &lt;code&gt;u32::MIN&lt;/code&gt;
directly instead?&lt;/p&gt;
&lt;h2 id=&#34;bool&#34;&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that bool isn&amp;rsquo;t just &amp;ldquo;stored as a byte&amp;rdquo;, the compiler
straight up declares its representation as &lt;a href=&#34;https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/ty/layout.rs#L676-L682&#34;&gt;the same as that of
u8&lt;/a&gt;?&lt;/p&gt;
&lt;h2 id=&#34;any&#34;&gt;&lt;code&gt;Any&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;Any&lt;/code&gt; is &lt;em&gt;really&lt;/em&gt; non-magical? It just has a blanket
implementation for all &lt;code&gt;T&lt;/code&gt; that returns &lt;code&gt;TypeId::of::&amp;lt;T&amp;gt;()&lt;/code&gt;, and to
downcast it simply compares the return value of that trait method to
see if it&amp;rsquo;s safe to cast to downcast to a type! &lt;code&gt;TypeId&lt;/code&gt; is magic though.&lt;/p&gt;
&lt;h2 id=&#34;self&#34;&gt;&lt;code&gt;Self&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;fn foo(self)&lt;/code&gt; is syntactic sugar for
&lt;code&gt;fn foo(self: Self)&lt;/code&gt;, and that one day you&amp;rsquo;ll be able to use
other types for &lt;code&gt;self&lt;/code&gt; that involve &lt;code&gt;Self&lt;/code&gt;, like &lt;code&gt;fn foo(self: Arc&amp;lt;Self&amp;gt;)&lt;/code&gt;?
&lt;a href=&#34;https://github.com/rust-lang/rust/issues/44874&#34;&gt;https://github.com/rust-lang/rust/issues/44874&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;heading-1&#34;&gt;&lt;code&gt;()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;()&lt;/code&gt; implements FromIterator, so you can
&lt;code&gt;.collect::&amp;lt;Result&amp;lt;(), E&amp;gt;&amp;gt;&lt;/code&gt; to just see if anything in an iterator erred?&lt;/p&gt;
&lt;p&gt;[Note that this doesn&amp;rsquo;t say whether or not this is a good idea. -Jimmy]&lt;/p&gt;
&lt;h2 id=&#34;struct-s&#34;&gt;&lt;code&gt;struct S&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;struct S&lt;/code&gt; implicitly declares a constant called &lt;code&gt;S&lt;/code&gt;,
which is why you can make one using just &lt;code&gt;S&lt;/code&gt;?&lt;/p&gt;
&lt;h2 id=&#34;refcell&#34;&gt;&lt;code&gt;RefCell&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that RefCell allows you to replace a
value in-place directly (like &lt;code&gt;std::mem::replace&lt;/code&gt;)?
&lt;a href=&#34;https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.replace&#34;&gt;https://doc.rust-lang.org/std/cell/struct.RefCell.html#method.replace&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;corenumwrapping&#34;&gt;&lt;code&gt;core::num::Wrapping&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that there used to also be a trait accompanying &lt;code&gt;Wrapping&lt;/code&gt;,
&lt;code&gt;WrappingOps&lt;/code&gt;, that was removed last minute before
1.0? &lt;a href=&#34;https://github.com/rust-lang/rust/pull/23549&#34;&gt;https://github.com/rust-lang/rust/pull/23549&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;const-t&#34;&gt;&lt;code&gt;*const T&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that, at least for the time being,
&lt;code&gt;*const T&lt;/code&gt; and &lt;code&gt;*mut T&lt;/code&gt; are more or less
equivalent? &lt;a href=&#34;https://github.com/rust-lang/unsafe-code-guidelines/issues/257&#34;&gt;https://github.com/rust-lang/unsafe-code-guidelines/issues/257&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;stdosunixnetunixstream&#34;&gt;&lt;code&gt;std::os::unix::net::UnixStream&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that (on nightly) you can pass UNIX file
descriptors over UnixStreams too, and thereby &lt;a href=&#34;https://doc.rust-lang.org/std/os/unix/net/struct.SocketAncillary.html#method.add_fds&#34;&gt;give another process
access&lt;/a&gt;
to a file it may not otherwise be able to open?&lt;/p&gt;
&lt;h2 id=&#34;stdsynccondvarmutex&#34;&gt;&lt;code&gt;std::sync::Condvar&lt;/code&gt;/&lt;code&gt;Mutex&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that Mara is doing some awesome work on making
&lt;code&gt;Condvar&lt;/code&gt; (and &lt;code&gt;Mutex&lt;/code&gt; and &lt;code&gt;RwLock&lt;/code&gt;) much better on a wide array on
platforms? &lt;a href=&#34;https://github.com/rust-lang/rust/issues/93740&#34;&gt;https://github.com/rust-lang/rust/issues/93740&lt;/a&gt;￼￼&lt;/p&gt;
&lt;h2 id=&#34;stdtaskwaker&#34;&gt;&lt;code&gt;std::task::Waker&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;Waker&lt;/code&gt; is secretly just a &lt;code&gt;dyn std::task::Wake + Clone&lt;/code&gt; done in a way that doesn&amp;rsquo;t require a
wide pointer or support for multi-trait dynamic dispatch? See
&lt;a href=&#34;https://doc.rust-lang.org/std/task/struct.RawWakerVTable.html&#34;&gt;https://doc.rust-lang.org/std/task/struct.RawWakerVTable.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;impl-trait&#34;&gt;&lt;code&gt;impl Trait&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;impl Trait&lt;/code&gt; in argument position and
&lt;code&gt;impl Trait&lt;/code&gt; in return position represent completely
different type constructs, even though they &amp;ldquo;feel&amp;rdquo;
related? &lt;a href=&#34;https://doc.rust-lang.org/nightly/reference/types/impl-trait.html&#34;&gt;https://doc.rust-lang.org/nightly/reference/types/impl-trait.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;btreemapk-v&#34;&gt;&lt;code&gt;BTreeMap&amp;lt;K, V&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;BTreeMap&lt;/code&gt; is one of the few
collections that still doesn&amp;rsquo;t have a &lt;code&gt;drain&lt;/code&gt;
method? &lt;a href=&#34;https://github.com/rust-lang/rust/issues/81074&#34;&gt;https://github.com/rust-lang/rust/issues/81074&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;struct-invariantlifetimeidphantomdatamut-id-&#34;&gt;&lt;code&gt;struct InvariantLifetime&amp;lt;&#39;id&amp;gt;(PhantomData&amp;lt;*mut &amp;amp;&#39;id ()&amp;gt;);&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;PhantomData&amp;lt;T&amp;gt;&lt;/code&gt; has variance like &lt;code&gt;T&lt;/code&gt;, and &lt;code&gt;*mut T&lt;/code&gt;
is invariant over &lt;code&gt;T&lt;/code&gt;, and so by placing a lifetime inside &lt;code&gt;T&lt;/code&gt; you make
the outer type invariant over that lifetime?&lt;/p&gt;
&lt;h2 id=&#34;rct&#34;&gt;&lt;code&gt;Rc&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that the &lt;code&gt;Rc&lt;/code&gt; type was among the arguments
for why &lt;code&gt;std::mem::forget&lt;/code&gt; shouldn&amp;rsquo;t be marked as
unsafe? &lt;a href=&#34;https://github.com/rust-lang/rust/issues/24456&#34;&gt;https://github.com/rust-lang/rust/issues/24456&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;stdfutureready&#34;&gt;&lt;code&gt;std::future::Ready&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that these days you can just use &lt;code&gt;async move { x }&lt;/code&gt; instead
of &lt;code&gt;future::ready(x)&lt;/code&gt;. The main reason to still use &lt;code&gt;future::ready(x)&lt;/code&gt;
is that you can name the future it returns, which is harder with &lt;code&gt;async&lt;/code&gt;
(without &lt;code&gt;type_alias_impl_trait&lt;/code&gt; that is).&lt;/p&gt;
&lt;h2 id=&#34;usize&#34;&gt;&lt;code&gt;usize&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;usize&lt;/code&gt; isn&amp;rsquo;t really &amp;ldquo;the size of a pointer&amp;rdquo;. Instead,
it&amp;rsquo;s more like &amp;ldquo;the size of a pointer address difference&amp;rdquo;, and the two
can be fairly different! &lt;a href=&#34;https://github.com/rust-lang/rust/issues/95228&#34;&gt;https://github.com/rust-lang/rust/issues/95228&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;stdthreadthread&#34;&gt;&lt;code&gt;std::thread::Thread&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that the &lt;code&gt;ThreadId&lt;/code&gt; that&amp;rsquo;s available for each &lt;code&gt;Thread&lt;/code&gt; is
entirely a &lt;code&gt;std&lt;/code&gt; construct? Creating a &lt;code&gt;ThreadId&lt;/code&gt; simply increments a global
static counter under a lock.&lt;/p&gt;
&lt;h2 id=&#34;stdopscontrolflow&#34;&gt;&lt;code&gt;std::ops::ControlFlow&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;ControlFlow&lt;/code&gt; is really a stepping stone towards making
&lt;code&gt;?&lt;/code&gt; work for other types than &lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt;? The full design has gone
through a lot of iterations, but the latest and greatest is
&lt;a href=&#34;https://github.com/rust-lang/rust/issues/84277&#34;&gt;RFC3058&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;file&#34;&gt;&lt;code&gt;File&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that there are implementations of &lt;code&gt;Read&lt;/code&gt;, &lt;code&gt;Write&lt;/code&gt;, and &lt;code&gt;Seek&lt;/code&gt;
for &lt;code&gt;&amp;amp;File&lt;/code&gt; as well, so multiple threads can share a single &lt;code&gt;File&lt;/code&gt; and call
those concurrently. Whether they should is a different question of course.&lt;/p&gt;
&lt;h2 id=&#34;resultt-e&#34;&gt;&lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that Rust originally (pre-1.0) had both Result and an Either type? They decided to remove Either &lt;a href=&#34;https://github.com/rust-lang/rust/issues/9157&#34;&gt;way back in 2013&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;cowstr&#34;&gt;&lt;code&gt;Cow&amp;lt;str&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that because &lt;code&gt;Cow&amp;lt;&#39;a, T&amp;gt;&lt;/code&gt; is covariant in &lt;code&gt;&#39;a&lt;/code&gt;, you can always
assign &lt;code&gt;Cow::Borrowed(&amp;quot;some string&amp;quot;)&lt;/code&gt; to one no matter what it originally
held?&lt;/p&gt;
&lt;h2 id=&#34;panicinfo&#34;&gt;&lt;code&gt;PanicInfo&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that since &lt;code&gt;PanicInfo&lt;/code&gt; is in core, its &lt;code&gt;Display&lt;/code&gt;
implementation cannot access the panic data if it&amp;rsquo;s a &lt;code&gt;String&lt;/code&gt; (since
it can&amp;rsquo;t name that type), so trying to print the &lt;code&gt;PanicInfo&lt;/code&gt; after
a &lt;code&gt;std::panic::panic_any(format!(&amp;quot;x y z&amp;quot;))&lt;/code&gt; won&amp;rsquo;t print &lt;code&gt;&amp;quot;x y z&amp;quot;&lt;/code&gt;?
&lt;a href=&#34;https://github.com/rust-lang/rust/blob/352e621368c31d7b4a6362e081586cdb931ba020/library/core/src/panic/panic_info.rs#L159-L162&#34;&gt;Source link.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;stdffic_void&#34;&gt;&lt;code&gt;std::ffi::c_void&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that the whole &lt;code&gt;c_void&lt;/code&gt; type is a collection
of hacks to try to work around the lack for extern
types? &lt;a href=&#34;https://github.com/rust-lang/rust/issues/43467&#34;&gt;https://github.com/rust-lang/rust/issues/43467&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;featureraw_ref_op-raw-const-t&#34;&gt;&lt;code&gt;#[feature(raw_ref_op)] &amp;amp;raw const T&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Definitely cheating :p But did you know that originally the intention
was to have &lt;code&gt;&amp;amp;const raw&lt;/code&gt; variable be just a MIR construct and let
&lt;code&gt;&amp;amp;variable as *const _&lt;/code&gt; be automatically changed to &lt;code&gt;&amp;amp;const raw&lt;/code&gt;?
&lt;a href=&#34;https://github.com/RalfJung/rfcs/blob/fd4b4cd769300cfde5d54865d227990b71b762d1/text/0000-raw-reference-operator.md&#34;&gt;https://github.com/RalfJung/rfcs/blob/fd4b4cd769300cfde5d54865d227990b71b762d1/text/0000-raw-reference-operator.md&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;u256&#34;&gt;&lt;code&gt;u256&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that because Rust compiles through LLVM,
we&amp;rsquo;re sort of constrained to the primitive types
LLVM supports, and &lt;a href=&#34;https://llvm.org/doxygen/classllvm_1_1Type.html#pub-static-methods&#34;&gt;LLVM itself only goes up to
128&lt;/a&gt;?&lt;/p&gt;
&lt;h2 id=&#34;_&#34;&gt;&lt;code&gt;_&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that whether or not &lt;code&gt;let _ = x&lt;/code&gt; should move &lt;code&gt;x&lt;/code&gt; is actually
fairly subtle? &lt;a href=&#34;https://github.com/rust-lang/rust/issues/10488&#34;&gt;https://github.com/rust-lang/rust/issues/10488&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;maybeuninit&#34;&gt;&lt;code&gt;MaybeUninit&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;MaybeUninit&lt;/code&gt; arose because the previous mechanism,
&lt;code&gt;std::mem::uninitialized&lt;/code&gt;, produced immediate undefined behavior when
invoked with most types (like &lt;code&gt;uninitialized::&amp;lt;bool&amp;gt;()&lt;/code&gt;).&lt;/p&gt;
&lt;h2 id=&#34;struct-tconst-c-usize&#34;&gt;&lt;code&gt;struct T&amp;lt;const C: usize&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that with Rust 1.59.0 you can now
&lt;a href=&#34;https://blog.rust-lang.org/2022/02/24/Rust-1.59.0.html#const-generics-defaults-and-interleaving&#34;&gt;give &lt;code&gt;C&lt;/code&gt; a default value&lt;/a&gt;?&lt;/p&gt;
&lt;h2 id=&#34;weakt&#34;&gt;&lt;code&gt;Weak&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that actual deallocation logic for &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt; is
implemented in &lt;code&gt;Weak&amp;lt;T&amp;gt;&lt;/code&gt;, and is invoked by considering all copies of
a particular &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt; to collectively hold a single &lt;code&gt;Weak&amp;lt;T&amp;gt;&lt;/code&gt; between them?
&lt;a href=&#34;https://github.com/rust-lang/rust/blob/7e9b92cb43a489b34e2bcb8d21f36198e02eedbc/library/alloc/src/sync.rs#L1108-L1109&#34;&gt;Source link.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;t-n&#34;&gt;&lt;code&gt;[T; N]&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that while &lt;em&gt;most&lt;/em&gt; trait implementations for arrays now use
const generics to impl for any length &lt;code&gt;N&lt;/code&gt;, &lt;a href=&#34;https://github.com/rust-lang/rust/blob/e40d5e83dc133d093c22c7ff016b10daa4f40dcf/library/core/src/array/mod.rs#L371-L394&#34;&gt;we can&amp;rsquo;t &lt;em&gt;yet&lt;/em&gt; do the same for
&lt;code&gt;Default&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;u8&#34;&gt;&lt;code&gt;u8&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that as of Rust 1.60, you can now use &lt;code&gt;u8::escape_ascii&lt;/code&gt; to
&lt;a href=&#34;https://doc.rust-lang.org/std/ascii/fn.escape_default.html&#34;&gt;get an iterator of the bytes needed to escape that byte character in
most contexts&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;hashmapk-v&#34;&gt;&lt;code&gt;HashMap&amp;lt;K, V&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that the Rust devs are working on a &amp;ldquo;raw&amp;rdquo; entry API for
&lt;code&gt;HashMap&lt;/code&gt; that allows you to (unsafely) avoid re-hashing a key you&amp;rsquo;ve
already hashed? &lt;a href=&#34;https://github.com/rust-lang/rust/issues/56167&#34;&gt;https://github.com/rust-lang/rust/issues/56167&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;mut-t&#34;&gt;&lt;code&gt;&amp;amp;mut T&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that while &lt;code&gt;&amp;amp;mut T&lt;/code&gt; is defined as meaning &amp;ldquo;mutable reference&amp;rdquo; in the Rust reference, you&amp;rsquo;re often better off thinking of it as &amp;ldquo;mutually exclusive reference&amp;rdquo;. &lt;a href=&#34;https://docs.rs/dtolnay/latest/dtolnay/macro._02__reference_types.html&#34;&gt;Quoth David Tolnay&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;stdopsrange&#34;&gt;&lt;code&gt;std::ops::Range&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that there&amp;rsquo;s been a lot of debate around whether or not the
&lt;code&gt;Range&lt;/code&gt; types should be &lt;code&gt;Copy&lt;/code&gt;? &lt;a href=&#34;https://github.com/rust-lang/rust/pull/21846&#34;&gt;https://github.com/rust-lang/rust/pull/21846&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;atomicu32&#34;&gt;&lt;code&gt;AtomicU32&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that you&amp;rsquo;ll often want &lt;code&gt;compare_exchange_weak&lt;/code&gt;
over &lt;code&gt;compare_exchange&lt;/code&gt; to get
&lt;a href=&#34;https://devblogs.microsoft.com/oldnewthing/20180329-00/?p=98375&#34;&gt;more efficient code on ARM cores&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;stdopshash&#34;&gt;&lt;code&gt;std::ops::Hash&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that Hash is responsible for not just
&lt;a href=&#34;https://github.com/rust-lang/rust/issues/29263&#34;&gt;one&lt;/a&gt;
, but
&lt;a href=&#34;https://github.com/rust-lang/rust/issues/65744&#34;&gt;two&lt;/a&gt;
of the issues on the &amp;ldquo;rust 2 breakage wishlist&amp;rdquo;?&lt;/p&gt;
&lt;h2 id=&#34;integer&#34;&gt;&lt;code&gt;{integer}&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that fasterthanlime&amp;rsquo;s &lt;a href=&#34;https://fasterthanli.me/articles/the-curse-of-strong-typing#different-kinds-of-numbers&#34;&gt;most recent
article&lt;/a&gt;
does a great job at explaining &lt;code&gt;{integer}&lt;/code&gt;?&lt;/p&gt;
&lt;h2 id=&#34;fn-1&#34;&gt;&lt;code&gt;Fn&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that until Rust 1.35.0, &lt;code&gt;Box&amp;lt;T&amp;gt; where T: Fn&lt;/code&gt;
did not &lt;code&gt;impl Fn&lt;/code&gt;, so you couldn&amp;rsquo;t (easily) call boxed
closures! &lt;a href=&#34;https://github.com/rust-lang/rust/pull/55431&#34;&gt;https://github.com/rust-lang/rust/pull/55431&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;-&#34;&gt;&lt;code&gt;((), ())&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;((), ())&lt;/code&gt; and &lt;code&gt;()&lt;/code&gt; have the same hash?
&lt;a href=&#34;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=894b78e8ee2721440aa8dea5e35f9dc3&#34;&gt;Playground link.&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;t-1&#34;&gt;&lt;code&gt;[T]&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;&amp;amp;[u8]&lt;/code&gt; implements &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Write&lt;/code&gt;? So for anything
that takes &lt;code&gt;impl Read&lt;/code&gt;, you can provide &lt;code&gt;&amp;amp;mut&lt;/code&gt; slice instead! Comes in
handy for testing. Note that the slice itself is shortened for each read,
hence &lt;code&gt;&amp;amp;mut &amp;amp;[u8]&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;heading-2&#34;&gt;&lt;code&gt;*&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;*&lt;/code&gt; is (mostly) just syntax sugar for the std::ops::Mul
trait?&lt;/p&gt;
&lt;h2 id=&#34;unsafecellt&#34;&gt;&lt;code&gt;UnsafeCell&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Did you know that &lt;code&gt;UnsafeCell&lt;/code&gt; is one of those types that the compiler
needs &amp;ldquo;special magic&amp;rdquo; for because it has to instruct LLVM to not assume
Rust&amp;rsquo;s normal aliasing rules hold once code traverses the boundary of any
&lt;code&gt;UnsafeCell&lt;/code&gt;?&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Function Overloading in Rust</title>
      <link href="https://www.thecodedmessage.com/posts/function-overloading-in-rust/" />
      <id>https://www.thecodedmessage.com/posts/function-overloading-in-rust/</id>
      <updated>2022-06-04T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I just made a &lt;a href=&#34;https://github.com/seanmonstar/reqwest/pull/1553&#34;&gt;pull request&lt;/a&gt;
to &lt;a href=&#34;https://github.com/seanmonstar/reqwest/&#34;&gt;reqwest&lt;/a&gt;. I thought this
particular one was interesting enough to be worth blogging about, so I am.&lt;/p&gt;
&lt;p&gt;We know that many C++ family languages have a feature known as function
overloading, where two functions or methods can exist with the same name
but different argument types. It looks something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;void use_connector(ConnectorA conn) {
    // IMPL
}

void use_connector(ConnectorB conn) {
    // IMPL
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The compiler then chooses which method to call, at compile-time, based
on the static type of the argument. In C++, this is part of compile-time
polymorphism, an easy &amp;ldquo;&lt;code&gt;if&lt;/code&gt; statement&amp;rdquo; in the template meta-language. In
Java and many other languages, it&amp;rsquo;s merely a convenience, for when an
ad-hoc group of types are possible for what an outsider sees as the
same operation, but which from the perspective of the library requires
different implementations.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I just made a &lt;a href=&#34;https://github.com/seanmonstar/reqwest/pull/1553&#34;&gt;pull request&lt;/a&gt;
to &lt;a href=&#34;https://github.com/seanmonstar/reqwest/&#34;&gt;reqwest&lt;/a&gt;. I thought this
particular one was interesting enough to be worth blogging about, so I am.&lt;/p&gt;
&lt;p&gt;We know that many C++ family languages have a feature known as function
overloading, where two functions or methods can exist with the same name
but different argument types. It looks something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;void use_connector(ConnectorA conn) {
    // IMPL
}

void use_connector(ConnectorB conn) {
    // IMPL
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The compiler then chooses which method to call, at compile-time, based
on the static type of the argument. In C++, this is part of compile-time
polymorphism, an easy &amp;ldquo;&lt;code&gt;if&lt;/code&gt; statement&amp;rdquo; in the template meta-language. In
Java and many other languages, it&amp;rsquo;s merely a convenience, for when an
ad-hoc group of types are possible for what an outsider sees as the
same operation, but which from the perspective of the library requires
different implementations.&lt;/p&gt;
&lt;p&gt;Rust does not support this, at least not in this form. This is a mildly
controversial decision; I&amp;rsquo;ve seen many people complain about it,
because it is a commonly-used feature in the languages they&amp;rsquo;ve come
from. Ultimately, I think Rust made the right call. There are too
many advantages of having a one-to-one correspondence between method or
function names and implementations, and ultimately I think the feature is
more confusing than helpful. &lt;code&gt;trait&lt;/code&gt;s cover a lot of the same ability,
but in a more structured fashion, acting like C++&amp;rsquo;s compile-time
&amp;ldquo;&lt;code&gt;if&lt;/code&gt;-statements.&amp;rdquo; But of course, there is always a learning curve giving
up a feature you&amp;rsquo;re used to using.&lt;/p&gt;
&lt;p&gt;But just because Rust doesn&amp;rsquo;t officially support function
loading as a feature, surprisingly doesn&amp;rsquo;t mean that it&amp;rsquo;s
completely impossible. Recently, I was looking into the
depths of &lt;a href=&#34;https://crates.io/crates/reqwest&#34;&gt;&lt;code&gt;reqwest&lt;/code&gt;&lt;/a&gt;,
trying to troubleshoot an issue, and I came across &lt;a href=&#34;https://github.com/seanmonstar/reqwest/blob/d536ce261c6e92d9956cc9a3d28c4288046f454b/src/async_impl/client.rs#L1248-L1271&#34;&gt;this
code&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#[cfg(any(feature = &amp;#34;native-tls&amp;#34;, feature = &amp;#34;__rustls&amp;#34;,))]
#[cfg_attr(docsrs, doc(cfg(any(feature = &amp;#34;native-tls&amp;#34;, feature = &amp;#34;rustls-tls&amp;#34;))))]
pub fn use_preconfigured_tls(mut self, tls: impl Any) -&amp;gt; ClientBuilder {
    let mut tls = Some(tls);
    #[cfg(feature = &amp;#34;native-tls&amp;#34;)]
    {
        if let Some(conn) =
            (&amp;amp;mut tls as &amp;amp;mut dyn Any).downcast_mut::&amp;lt;Option&amp;lt;native_tls_crate::TlsConnector&amp;gt;&amp;gt;()
        {
            let tls = conn.take().expect(&amp;#34;is definitely Some&amp;#34;);
            let tls = crate::tls::TlsBackend::BuiltNativeTls(tls);
            self.config.tls = tls;
            return self;
        }
    }
    #[cfg(feature = &amp;#34;__rustls&amp;#34;)]
    {
        if let Some(conn) =
            (&amp;amp;mut tls as &amp;amp;mut dyn Any).downcast_mut::&amp;lt;Option&amp;lt;rustls::ClientConfig&amp;gt;&amp;gt;()
        {
            let tls = conn.take().expect(&amp;#34;is definitely Some&amp;#34;);
            let tls = crate::tls::TlsBackend::BuiltRustls(tls);
            self.config.tls = tls;
            return self;
        }
    }

    // Otherwise, we don&amp;#39;t recognize the TLS backend!
    self.config.tls = crate::tls::TlsBackend::UnknownPreconfigured;
    self
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I was shocked to see this! I felt like I was reading Java.
My first thought was that this was the Java &lt;code&gt;instanceof&lt;/code&gt; (anti-)pattern,
but after a little more thought, I realized that this in practice
would work out to function overloading.&lt;/p&gt;
&lt;p&gt;Since this uses &lt;code&gt;impl Any&lt;/code&gt; instead of &lt;code&gt;&amp;amp;mut dyn Any&lt;/code&gt;, this function
will be monomorphized at compile-time, and I would expect that
the relevant branching would be collapsed, resulting in these
monomorphizations, written in an imaginary version of Rust where
function overloading is supported:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#[cfg(feature = &amp;#34;native-tls&amp;#34;)]
pub fn use_preconfigured_tls(mut self, tls: native_tls_crate::TlsConnector) -&amp;gt; ClientBuilder {
    let tls = crate::tls::TlsBackend::BuiltNativeTls(tls);
    self.config.tls = tls;
    self
}

#[cfg(feature = &amp;#34;__rustls&amp;#34;)]
pub fn use_preconfigured_tls(mut self, tls: rustls::ClientConfig) -&amp;gt; ClientBuilder {
    let tls = crate::tls::TlsBackend::BuiltRustls(tls);
    self.config.tls = tls;
    self
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There is a wrinkle though. Unlike the Java or pseudo-Rust equivalent, the Rust
code in &lt;code&gt;reqwest&lt;/code&gt; will still allow functions to compile if they specify
another type that is not one of the two supported. So you can call this
function with anything, even an &lt;code&gt;i32&lt;/code&gt;, and the compiler won&amp;rsquo;t signal
an error or even a warning:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;client_builder.use_preconfigured_tls(42); // COMPILES!
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this implementation, it eventually causes a run-time error instead (a
separate function produces it in the case of &lt;code&gt;UnknownPreconfigured&lt;/code&gt;). But
this odd type-safety work-around still can&amp;rsquo;t be removed without breaking
API-compatibility. Code could theoretically be relying on this function
producing a run-time error in certain situations, or it could rely on
that other function not being called. Luckily, &lt;code&gt;reqwest&lt;/code&gt; is not 1.0,
and I have reason to hope they won&amp;rsquo;t consider this problematic.&lt;/p&gt;
&lt;p&gt;There are other ways to accomplish the same goal. Instead of an ad-hoc
list of supported types, this code could&amp;rsquo;ve used a &lt;code&gt;trait&lt;/code&gt;. Such code
would look something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pub trait TlsConfig {
    fn to_tls_backend(self) -&amp;gt; crate::tls::TlsBackend;
}

#[cfg(feature = &amp;#34;native-tls&amp;#34;)]
impl TlsConfig for native_tls_crate::TlsConnector {
    fn to_tls_backend(self) -&amp;gt; crate::tls::TlsBackend {
        crate::tls::TlsBackend::BuiltNativeTls(self)
    }
}

#[cfg(feature = &amp;#34;__rustls&amp;#34;)]
impl TlsConfig for rustls::ClientConfig {
    fn to_tls_backend(self) -&amp;gt; crate::tls::TlsBackend {
        crate::tls::TlsBackend::BuiltRustls(self)
    }
}

pub fn use_preconfigured_tls(mut self, tls: impl Tls) -&amp;gt; ClientBuilder {
    self.config.tls = tls.to_tls_backend();
    self
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This would allow the library to be used in the exact same way for valid
uses, but would still allow the compiler to catch invalid types. To be
sure, the &lt;code&gt;trait&lt;/code&gt; and its &lt;code&gt;impl&lt;/code&gt;s would have to be separated in the
code from the &lt;code&gt;use_preconfigured_tls&lt;/code&gt; method, as you can&amp;rsquo;t put
a &lt;code&gt;trait&lt;/code&gt; inside an &lt;code&gt;impl&lt;/code&gt; block. But I think such an inconvenience
is worth the better type-safety.&lt;/p&gt;
&lt;p&gt;My take-away here is to be wary of emulating features from other
programming languages, and also to be wary of &lt;code&gt;std::any&lt;/code&gt;.&lt;/p&gt;
&lt;h1 id=&#34;addendumerrata&#34;&gt;Addendum/Errata&lt;/h1&gt;
&lt;p&gt;I was wrong about the existing code not providing a run-time error. It
sets an &lt;code&gt;enum&lt;/code&gt; to &lt;code&gt;UnknownPreconfigured&lt;/code&gt;, which then triggers a run-time
error elsewhere in a separate function. The article has been updated
accordingly.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;trait&lt;/code&gt; example code was also edited to reflect a version that actually
compiles, but not the final version in the MR.&lt;/p&gt;
&lt;p&gt;I also edited the intro to clarify the relationship between function
overloading and traits.&lt;/p&gt;
&lt;p&gt;The MR was ultimately &lt;a href=&#34;https://github.com/seanmonstar/reqwest/pull/1553#issuecomment-1148059370&#34;&gt;rejected&lt;/a&gt; for reasons I deeply disagree with.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Can you have too many programming language features?</title>
      <link href="https://www.thecodedmessage.com/posts/2022-05-11-programming---multiparadigm/" />
      <id>https://www.thecodedmessage.com/posts/2022-05-11-programming---multiparadigm/</id>
      <updated>2022-05-11T00:00:00+00:00</updated>
      
      <summary type="html">&lt;blockquote&gt;
&lt;p&gt;There&amp;rsquo;s more than one way to do it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it&#34;&gt;Perl motto&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;There should be one&amp;ndash; and preferably only one &amp;ndash;obvious way to do it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://peps.python.org/pep-0020/&#34;&gt;The Zen of Python&lt;/a&gt; (inconsistent
formatting is part of the quote)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;When it comes to statically-typed systems programming languages, C++ is
the Perl, and Rust is the Python. In this post, the next installment of
my &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;Rust vs C++&lt;/a&gt; series, I will attempt to explain
why C++&amp;rsquo;s feature-set is problematic, and explain how Rust does better.&lt;/p&gt;</summary>
      <content type="html">&lt;blockquote&gt;
&lt;p&gt;There&amp;rsquo;s more than one way to do it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it&#34;&gt;Perl motto&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;There should be one&amp;ndash; and preferably only one &amp;ndash;obvious way to do it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://peps.python.org/pep-0020/&#34;&gt;The Zen of Python&lt;/a&gt; (inconsistent
formatting is part of the quote)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;When it comes to statically-typed systems programming languages, C++ is
the Perl, and Rust is the Python. In this post, the next installment of
my &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;Rust vs C++&lt;/a&gt; series, I will attempt to explain
why C++&amp;rsquo;s feature-set is problematic, and explain how Rust does better.&lt;/p&gt;
&lt;p&gt;C++ fans brag that it is &amp;ldquo;multi-paradigm,&amp;rdquo; and it is. You can do
everything the C way, as C++ has a subset almost exactly identical to
C. You can use pointers and virtual functions and inheritance to create
all the classic OOP design patterns, as C++ is object-oriented. Or you
can use templates, and &amp;ldquo;static&amp;rdquo; or &amp;ldquo;compile-time&amp;rdquo; polymorphism, and
program that way.&lt;/p&gt;
&lt;p&gt;At first glance, this all seems like an unmitigated good thing, because
it gives you, as a programmer, flexibility. You can express your code
in OOP style if that matches the problem at hand, or even if you
just like it better. If you need the performance of
templates, you can use them, and if you don&amp;rsquo;t (or you just find them
confusing), you can use run-time polymorphism instead. Or you
can just ignore all of it, and program in almost-plain C.
Flexibility is good: you can use the features you want, and not
use the features you don&amp;rsquo;t want. Even if a feature is downright
harmful, in your opinion, that&amp;rsquo;s easy enough to handle: Just don&amp;rsquo;t
use it.&lt;/p&gt;
&lt;p&gt;And this is all very well and good if you&amp;rsquo;re programming a quick project
completely by yourself. But most code comes in long-lived projects, with
developers jumping in and out of the project all the time.  In such an
environment, as Robert C. Martin puts it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Indeed, the ratio of time spent reading versus writing is well over
10 to 1. We are constantly reading old code as part of the effort to
write new code. &amp;hellip;[Therefore,] making it easy to read makes it easier
to write.”&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Robert C. Martin, &lt;em&gt;Clean Code: A Handbook of Agile Software Craftsmanship&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;(Sidenote: I will admit to knowing almost nothing about Robert C. Martin
besides this famous quote. I have no idea if the rest of his work is
as insightful as this quote, or not, and will probably try to find out
someday, but not today.)&lt;/p&gt;
&lt;p&gt;Since programmers in general spend much more time reading code than
writing it, we very rarely actually get to reap the benefits of this
flexibility as writers. Much more often, as maintainers and readers,
we have to be flexible ourselves. We have to be ready to read code
in any style, in any paradigm, using any feature-set.&lt;/p&gt;
&lt;p&gt;This is why Perl was commonly panned as a write-only programming language:
It had so many features that you could not be up to speed on all of them.
Each programmer at each point in time had a set that they used, but
no one could ever get proficient at working in the entire available
feature-set.&lt;/p&gt;
&lt;p&gt;In Perl, the features were syntactic, so the programs would be unreadable
at a line-by-line level. In C++, the different features have more to do
with code organization, which is harder to make fun of, but I think
more insidious, because a lot of the features are structural.&lt;/p&gt;
&lt;p&gt;Let me explain what I mean. Let&amp;rsquo;s say you&amp;rsquo;re a C++ maintenance programmer,
and you don&amp;rsquo;t like exceptions. You&amp;rsquo;re trying to maintain a program
that uses exceptions heavily, and add new features to it. Not only do
you have to be able to understand exceptions to read the code, you have
to write your own code so that it handles the exceptions where appropriate,
and so that it&amp;rsquo;s exception-safe. Even if you&amp;rsquo;re just using a third-party
library that throws exceptions, you have to understand exceptions to use
that library.&lt;/p&gt;
&lt;p&gt;The entire programming language, with all the features, is part of
the necessary skill-set to program proficiently. Even if it is just
you writing your own project, you still will have to use libraries,
and the features involved with it.  And even if it is just you, if the
project lives long enough, you will have to deal with your previous
decisions. Migrating from dynamic to static polymorphism in C++ is no
joke. Ask me how I know.&lt;/p&gt;
&lt;p&gt;And of course, every feature has to be considered when writing advice.
Every best practices manual for C++ is written for C++, not a subset
of C++ features. The more things it&amp;rsquo;s possible for a future programmer
or future library writer to do, the more things you have to worry
about coding defensively, and the more things that have to be included
in best practices manuals, and finally the more things that a proficient
programmer has to stuff into their brain.&lt;/p&gt;
&lt;h1 id=&#34;specific-c-examples-rust-responses&#34;&gt;Specific C++ Examples, Rust Responses&lt;/h1&gt;
&lt;p&gt;But I&amp;rsquo;m also not trying to advocate for absolute minimalism. There may
be a cost to every feature, and it may be that no feature is optional,
but that doesn&amp;rsquo;t mean that we should have the bare minimum number of
features. Sometimes the cognitive and maintenance cost of a seemingly
extraneous feature is still worth it. Especially in a systems programming
context, different problems often do actually call for different
implementation strategies with different programming language features
to express them.&lt;/p&gt;
&lt;p&gt;C++, however, does this poorly. I&amp;rsquo;m not even sure I&amp;rsquo;d claim that C++
has too many features; it&amp;rsquo;s more that the features are not consistent.
They clash with each other. Different feature-sets make assumptions
that are violated by other feature-sets. C++ is not designed with
the costs of extra features in mind, and as such, the features
cost more than they have to.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s discuss a few specific ways in which C++&amp;rsquo;s features cause
problems and clash with each other. For each of these categories,
I then discuss how Rust handles the same topic, with a more
coherently-designed feature set.&lt;/p&gt;
&lt;h2 id=&#34;value-and-reference-semantics-slicing&#34;&gt;Value and Reference Semantics: Slicing&lt;/h2&gt;
&lt;p&gt;Slicing is a famous beginner error in C++, where the semantics of
combining certain features are surprising with a tendency to break
invariants, but no diagnostics are issued as the code is completely valid.
Perhaps unsurprisingly, this code comes from a mismatch between
two C++ features designed for two C++ programming styles.&lt;/p&gt;
&lt;p&gt;Specifically, C++ has a distinction between value and reference semantics.&lt;/p&gt;
&lt;p&gt;With value semantics, you can use operator overloading to make
your custom class look and act like a built-in type, supporting
operators like &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;+=&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;class complex {
    double re;
    double im;
public:
    complex &amp;amp;operator=(const complex &amp;amp;other) {
        re = other.re;
        im = other.im;
        return *this;
    }

    complex &amp;amp;operator+=(const complex &amp;amp;other) {
        re += other.re;
        im += other.im;
        return *this;
    }

    complex operator+(const complex &amp;amp;other) {
        complex res = *this;
        res += other;
        return res;
    }
};

// Sample usage
Complex a, b;
a = b;
Complex c = a + b;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With reference semantics, you can use polymorphism to create
many different types of object that support the same interface.
You can then access these objects through pointers or references
to the base class.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;class Complex {
protected:
    double re;
    double im;
public:
    virtual double getMagnitude() {
        return sqrt(re * re + im * im);
    }
}

class Quaternion : public Complex {
protected:
    double j;
    double k;
public:
    double getMagnitude() override {
        return sqrt(re * re + im * im + j * j + k * k);
    }
}

// Sample usage
void print_magnitude(Complex &amp;amp;c) {
    std::cout &amp;lt;&amp;lt; c.getMagnitude() &amp;lt;&amp;lt; std::endl;
}

Quaternion a;
Complex b;
print_magnitude(a);
print_magnitude(b);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However, these two programming techniques cannot be combined.
You cannot assign a &lt;code&gt;Complex&lt;/code&gt; object a &lt;code&gt;Quaternion&lt;/code&gt; value:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Quaternion a;
Complex b;
b = a; // Non-sensical
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Why? Well, unlike in Java, &lt;code&gt;Complex b&lt;/code&gt; actually allocates the space for a
&lt;code&gt;Complex&lt;/code&gt; number as a local variable on the stack. This means that it
only has room for the two fields, &lt;code&gt;re&lt;/code&gt; and &lt;code&gt;im&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But, unfortunately, if you include all the methods from both examples,
that code will compile, and run, and &lt;code&gt;b&lt;/code&gt; will have only &lt;code&gt;re&lt;/code&gt; and &lt;code&gt;im&lt;/code&gt;
from &lt;code&gt;a&lt;/code&gt;. This is almost certainly not what you want, and may
in fact break invariants (e.g. for this you might only be dealing
with values of magnitude 1, and this truncation would lower the
magnitude).&lt;/p&gt;
&lt;p&gt;This comes from two alternative paradigms for objects: by value as
&amp;ldquo;primitive replacement,&amp;rdquo; where &lt;code&gt;Complex&lt;/code&gt; can be used like an &lt;code&gt;int&lt;/code&gt;, and
by reference with traditional OOP inheritance and polymorphism. These
paradigms don&amp;rsquo;t use different keywords, however. They can just all
be used in the same objects, causing this trouble.&lt;/p&gt;
&lt;p&gt;Advice on how to prevent this includes rules like &amp;ldquo;give
all parent classes at least one pure virtual function,&amp;rdquo;
which would make &lt;code&gt;Complex b&lt;/code&gt; as a by-value declaration
illegal. But if this rule is recommended in leading &lt;a href=&#34;https://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876&#34;&gt;books on
C++&lt;/a&gt;,
why isn&amp;rsquo;t it enforced in the programming language itself?&lt;/p&gt;
&lt;h3 id=&#34;how-rust-handles-this&#34;&gt;How Rust Handles This&lt;/h3&gt;
&lt;p&gt;C++&amp;rsquo;s slicing is caused by a conflict between two features, inheritance
and assignment. Rust handles both of those features
differently, so that they do not conflict.&lt;/p&gt;
&lt;p&gt;So the most important difference here between Rust and C++ is that
Rust does not have implementation inheritance like C++ does. For
two given C++ concrete types, one of which surrounds the other,
there are two possible relationships between them: is-a, and has-a.
Rust only does has-a for concrete types.&lt;/p&gt;
&lt;p&gt;C++ inheritance is a feature with many use cases, such as sharing
implementation, implementing policy, and implementing interfaces (what Rust
calls traits). Rust, rather than having one big broad feature,
instead implements individual features as appropriate. The closest
feature Rust has to inheritance is traits (including subtraits
and supertraits), but because traits are not concrete types, they
cannot be assigned, and so this issue is avoided.&lt;/p&gt;
&lt;p&gt;But also in assignments, Rust implements a simpler feature that is
easier to reason about: Rust does not allow custom assignment operators.
Rust instead builds assignment out of two operations: move, and drop
(cf. C++ destructors). If drop is implemented correctly, so will
assignment. If you want to copy instead of move, you have to explicitly
call a &lt;code&gt;clone()&lt;/code&gt; method. And moves are &lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;not
customizable either&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So, although Rust has some of the best parts of inheritance in traits,
and still allows assignment of custom types (but through customizing drop,
not assignment &lt;em&gt;per se&lt;/em&gt;), it avoids this particular clash through
restricting the scope of those features.&lt;/p&gt;
&lt;h2 id=&#34;exceptions-and-exception-safety&#34;&gt;Exceptions and &amp;ldquo;Exception Safety&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;It would be impossible to write a post criticizing C++ for
its problematic feature-clashes and not talk some
about exceptions.&lt;/p&gt;
&lt;p&gt;Exceptions are another famous example of a C++ feature you simply can&amp;rsquo;t
&amp;ldquo;not use.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Exceptions are viral by nature. If you call a function that might
throw and don&amp;rsquo;t catch all the exceptions that it throws &amp;ndash; which might
be impossible to determine &amp;ndash; then your function can throw as well.&lt;/p&gt;
&lt;p&gt;And lots of functions can cause exceptions. Allocating memory indicates
failure via exception. Exceptions are the only way for constructors to
signal failure, and C++ idiom encourages constructors to be written in
such a way that success guarantees that the object is usable. The
programming language was clearly not designed to be used without
exceptions.&lt;/p&gt;
&lt;p&gt;But exceptions are gnarly and confusing. I already know people will
comment to this post and say that if you write and structure C++ code
correctly, it will be exception-safe. And that&amp;rsquo;s almost trivially true,
since exception safety is part of correct C++ practice, but it&amp;rsquo;s not
easy and it doesn&amp;rsquo;t follow naturally from easy-to-learn principles,
which is why Herb Sutter, a huge name in C++, felt the need to write
&lt;a href=&#34;https://www.amazon.com/Exceptional-Engineering-Programming-Problems-Solutions/dp/0201615622&#34;&gt;two&lt;/a&gt;
&lt;a href=&#34;https://www.amazon.com/More-Exceptional-Engineering-Programming-Solutions/dp/020170434X&#34;&gt;books&lt;/a&gt;
about it. Of course, in practice, people just write exception-unsafe code,
all the time.&lt;/p&gt;
&lt;p&gt;Every time you call a function &amp;ndash; which can happen in C++ simply by
declaring a variable, or even by ending a scope (though destructors are
supposed to avoid throwing exceptions) &amp;ndash; you have to worry about whether
that function throws an exception, and if you&amp;rsquo;re leaving things within
that function in an inconsistent state. In C++, it is very common to
implement your own unsafe data structures, and exceptions are designed
to be sometimes recoverable from. Lack of exception safety can mean
memory corruption or even exploitable security vulnerabilities.&lt;/p&gt;
&lt;p&gt;No wonder a lot of codebases ban exceptions. Unfortunately, many shops
simply avoid using exceptions instead of banning them, leaving exceptions
possible. Also, code from &amp;ldquo;exception-free&amp;rdquo; codebases can then later
be mixed back in with regular C++, re-opening it to exception-safety
concerns.&lt;/p&gt;
&lt;p&gt;The fact that exceptions are so controversial can lead to
confusion as well. Consider this function signature:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;std::unique_ptr&amp;lt;DatabaseConnection&amp;gt; connect(const ConnectionParameters&amp;amp;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;How does this function indicate failure? From the signature, there are
two possibilities: It could either return &lt;code&gt;nullptr&lt;/code&gt;, or it could throw
an exception. Hopefully the documentation would clarify &amp;ndash; but again,
oftentimes, people don&amp;rsquo;t write documentation, especially for internal
APIs.&lt;/p&gt;
&lt;h3 id=&#34;how-rust-handles-this-1&#34;&gt;How Rust Handles This&lt;/h3&gt;
&lt;h4 id=&#34;normal-error-handling-in-rust&#34;&gt;Normal Error Handling in Rust&lt;/h4&gt;
&lt;p&gt;For recoverable errors, Rust encodes them in the type. Rust&amp;rsquo;s
equivalent to &lt;code&gt;std::unique_ptr&lt;/code&gt; &amp;ndash; &lt;code&gt;Box&lt;/code&gt; &amp;ndash; is not nullable. If we
want to return one, but possibly also signal an error, we use
a sum type or what Rust calls an &lt;code&gt;enum&lt;/code&gt;, and what C++ would call a
&amp;ldquo;tagged union&amp;rdquo; and make you implement by hand:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn connect(param: &amp;amp;ConnectionParameters) -&amp;gt;
    Result&amp;lt;Box&amp;lt;DatabaseConnection&amp;gt;, OurError&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This means that it can return either a database connection or an error.
This is the convention to return any error condition that is recoverable,
which is half of what exceptions are used for in C++. Since &lt;code&gt;Box&lt;/code&gt; is not
nullable, you have to say more than just &lt;code&gt;Box&lt;/code&gt; to signal that it&amp;rsquo;s
possible to return an error, proving that you really mean it.&lt;/p&gt;
&lt;p&gt;For unrecoverable exceptions &amp;ndash; for situations like logic and programming
errors that the program has caught &amp;ndash; Rust has panics, which work
much more like C++ exceptions in practice.&lt;/p&gt;
&lt;h4 id=&#34;panic-safety&#34;&gt;Panic Safety&lt;/h4&gt;
&lt;p&gt;Rust afficionados will know that Rust has not escaped exception
safety, having instead an analogous notion of &amp;ldquo;panic safety.&amp;rdquo; How,
then, can I criticize C++ so boldly?&lt;/p&gt;
&lt;p&gt;There are two notable differences between C++ exceptions and Rust panics.
The first is that Rust panics are used primarily for unrecoverable
errors, such as errors that indicate that a programmer&amp;rsquo;s assumptions
were violated due to a bug or a circumstance that the program cannot
recover from or a misunderstanding from the programmer. These generally
are unrecoverable, and Rust by convention uses a different mechanism,
&lt;code&gt;Result&lt;/code&gt;s, for recoverable errors. So most Rust code doesn&amp;rsquo;t have to
care about maintaining invariants in the face of panics, because most
Rust code can presume that if it panics, that&amp;rsquo;s the end. This is better
scoping for the panic feature, as opposed to exceptions.&lt;/p&gt;
&lt;p&gt;But the fact remains that panics can be recovered from, and do still
do stack unwinding and destructor/drop calls, and safety issues can
still exist. Panics in Rust can cause memory corruption &amp;ndash; in unsafe
code. And that&amp;rsquo;s where panic safety really still matters: in unsafe
code only. By cordoning off the implementations of sophisticated
data structures that require &lt;code&gt;unsafe&lt;/code&gt;, Rust also cordons off who
has to worry about panic safety.&lt;/p&gt;
&lt;p&gt;In C++, every function that calls another function has to be
written in an exception-safe way. In Rust, it&amp;rsquo;s really only unsafe
code that has to worry about it. This, in my mind, is a huge win,
and it comes from both better scoping of panics, and better management
of the situations where panics can break things.&lt;/p&gt;
&lt;h2 id=&#34;c-style-vs-c-style-pointers-and-arrays&#34;&gt;C-style vs C++-style Pointers and Arrays&lt;/h2&gt;
&lt;p&gt;There is a subset of C++ that is almost identical to C, and C++
must maintain compatibility with this subset for tradition&amp;rsquo;s sake.
It also must maintain compatibility with previous versions of itself.
Between the C and the C++, the concepts contained in C++20 stretch from
1972 to 2020, almost 50 years of active change in programming language
technology. This leads to features being duplicated, but differently,
and in ways that unfortunately clash with each other.&lt;/p&gt;
&lt;p&gt;For example: How do you express indirection? How do you alias a
value? There are three different ways to do it, and rather than
breaking down by use case, the biggest difference between them
is era:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pointers, from the original C&lt;/li&gt;
&lt;li&gt;References, a newer innovation that attempts to solve some of
the issues with pointers&lt;/li&gt;
&lt;li&gt;Smart pointers, an even newer innovation that attempts to cover
some of the remaining use cases. For pointers into arrays, iterators
also cover a lot of the same territory as smart pointers, and can
be lumped together for this conversation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These overlap a lot, and there is no single principle that will
tell you when to use which. You can invent some rules, and come
up with some principled reasonings for them, but your colleagues
won&amp;rsquo;t necessary listen, and external libraries and other codebases
you have to interact with certainly won&amp;rsquo;t, not even the standard
library, not even the programming language itself. Fundamentally,
the difference is era.&lt;/p&gt;
&lt;p&gt;Nullability? Part of original pointers. Later, we learned it was harmful
and got rid of it in references, but due to issues with how C++ does
&lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;move semantics&lt;/a&gt; it comes back with a vengeance for
smart pointers. (Of course, you still &lt;em&gt;can&lt;/em&gt; make a null reference,
it&amp;rsquo;s just undefined behavior. Ah well.)&lt;/p&gt;
&lt;p&gt;Pointers and references have special syntax, whereas smart pointers,
because they came from a later era, use the more standard &lt;code&gt;ptr_type&amp;lt;T&amp;gt;&lt;/code&gt;
syntax. Pointers and smart pointers can be used to manage ownership,
and references should not be.&lt;/p&gt;
&lt;p&gt;How should out parameters be expressed? It&amp;rsquo;s easy to say they should
be expressed with references, because otherwise they&amp;rsquo;re nullable,
and you have to worry about whether to check for nulls or not. On
the other hand, expressing out parameters with references mean you
can&amp;rsquo;t tell at the caller whether it&amp;rsquo;s an out parameter, only
at the callee:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int foo_ptr(int in, int *out);
int foo_ref(int in, int &amp;amp;out);
int out;
foo_ptr(3, &amp;amp;out);
foo_ref(4, out); // Surprise, this changes `out`! Can&amp;#39;t tell, though!

foo_ptr(5, nullptr); // Does this crash? Does this work? Who knows!
// Read the docs, I guess *shrug* hope there are docs
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;References should be used, in my practice and in the practice of many
people I respect, in every case where the reference is not owning,
will not be used for arithmetic, and is not optional. Of course, &lt;code&gt;this&lt;/code&gt;
meets all of those requirements, but is a pointer, not a reference
(but a special pointer, where being null is undefined behavior, like a
reference), simply because references were invented after &lt;code&gt;this&lt;/code&gt; was,
and for no stronger reason.&lt;/p&gt;
&lt;p&gt;Similarly, my practice dictated that &lt;code&gt;std::unique_ptr&lt;/code&gt; should be
used for owning pointers.  It&amp;rsquo;s nullable, but at least it auto-frees,
and so you should use it everywhere you&amp;rsquo;re conveying ownership. And
then, &lt;code&gt;Foo *&lt;/code&gt; can be used when you want an optional non-owning
reference.  But old APIs and APIs from C exist all over the place
that will use &lt;code&gt;Foo *&lt;/code&gt; invariably, and some will use &lt;code&gt;Foo *&lt;/code&gt; for
out parameters because of the callee readability issue, or because
of &lt;a href=&#34;https://www.youtube.com/watch?v=rHIkrotSwcc&#34;&gt;concerns&lt;/a&gt; about
&lt;code&gt;std::unique_ptr&lt;/code&gt;, or simply out of old habit, meaning you can&amp;rsquo;t count
on this convention actually being upheld, not at all.&lt;/p&gt;
&lt;p&gt;And of course, converting between these different representations is
sometimes as easy as &lt;code&gt;&amp;amp;&lt;/code&gt; or &lt;code&gt;*&lt;/code&gt;, and sometimes as difficult as having
&lt;code&gt;&amp;amp;&lt;/code&gt; and &lt;code&gt;*&lt;/code&gt; compile and seem to work but result in memory corruption,
and everywhere in between.&lt;/p&gt;
&lt;p&gt;Similarly, &lt;code&gt;T foo[N]&lt;/code&gt; and &lt;code&gt;std::array&amp;lt;T, N&amp;gt; foo&lt;/code&gt; are different ways of
writing the same basic thing. It gets weird when &lt;code&gt;N = 0&lt;/code&gt;, of course;
this is only supported by &lt;code&gt;std::array&lt;/code&gt;. And (on compilers that support
it at all), having &lt;code&gt;N&lt;/code&gt; be dynamic on the stack is only supported by &lt;code&gt;T foo[N]&lt;/code&gt;. And of course, &lt;code&gt;new T[N]&lt;/code&gt; returns a raw pointer to &lt;code&gt;T&lt;/code&gt; whereas
&lt;code&gt;new std::array&amp;lt;T, N&amp;gt;&lt;/code&gt; returns a pointer to a &lt;code&gt;std::array&lt;/code&gt;, which makes
much more sense.&lt;/p&gt;
&lt;p&gt;So, basically, &lt;code&gt;T foo[N]&lt;/code&gt; should be completely deprecated, but keeps on
being used even by new C++ programmers because it looks like it
should be the normal way to write an array, and because it looks like
the arrays from C. But they&amp;rsquo;re completely different types &amp;ndash; one isn&amp;rsquo;t
syntactic sugar for the other.&lt;/p&gt;
&lt;p&gt;This gets unwieldy, because the ways with the syntactic sugar (like
&lt;code&gt;new&lt;/code&gt; and &lt;code&gt;T*&lt;/code&gt; instead of &lt;code&gt;std::make_unique&lt;/code&gt; and &lt;code&gt;std::unique_ptr&lt;/code&gt;)
are the old, more C-style ways, the ways that yield more memory leaks
(you have to explicitly free or delete a &lt;code&gt;T*&lt;/code&gt;) and memory corruption (&lt;code&gt;T foo[]&lt;/code&gt; doesn&amp;rsquo;t even have a safe indexing operation, or proper iterators).&lt;/p&gt;
&lt;p&gt;And of course, even if you use the more modern formulations to save
on cognitive load because they&amp;rsquo;re more consistent with the rest of
the programming language (where &lt;code&gt;std::unique_ptr&lt;/code&gt; does RAII unlike
traditional pointers (spelled &lt;code&gt;*&lt;/code&gt;) and &lt;code&gt;std::array&lt;/code&gt; implements the
expected collections methods unlike traditional arrays (&lt;code&gt;[]&lt;/code&gt;)), you still
have to understand the traditional pointers and arrays completely to call
yourself a C++ programmer. Due to C interop, people not changing their
ways, and old resources, lots of new code is still written with them,
and there are still situations where they&amp;rsquo;re unavoidable, like pointer
arithmetic or &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Besides, even if you do correctly discern that a &lt;code&gt;T*&lt;/code&gt; must be freed,
how do you free it &amp;ndash; &lt;code&gt;free&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt;, or &lt;code&gt;delete[]&lt;/code&gt;? Choose wisely,
because the consequences of mixing &lt;code&gt;malloc&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt; can go beyond
whether destructors are called, and lead to undefined behavior and
general memory corruption. The documentation (or lack thereof), however,
might just assume you know which one to call.&lt;/p&gt;
&lt;h3 id=&#34;how-rust-handles-this-2&#34;&gt;How Rust Handles This&lt;/h3&gt;
&lt;p&gt;Rust also has references and various types of smart pointers and
iterators. It also has raw pointers, from which smart pointers
can be implemented. So in terms of the range of features, it&amp;rsquo;s
actually the same as C++. What&amp;rsquo;s the difference then?&lt;/p&gt;
&lt;p&gt;Well, in Rust, the difference is that they don&amp;rsquo;t overlap in the
same way. Each feature has its own purpose, unlike in C++ where it&amp;rsquo;s
anyone&amp;rsquo;s bet whether references or pointers are used for aliasing or
pass-by-reference, or whether raw pointers or smart pointers are used
to express ownership. Nullability is mostly a separate concern from
day-to-day use of Rust&amp;rsquo;s types, and so it is implemented orthogonally
through &lt;code&gt;Option&lt;/code&gt; and &lt;code&gt;Result&lt;/code&gt;, rather than being available in some types
but not in others haphazardly.&lt;/p&gt;
&lt;p&gt;References are for everyday aliasing and
pass-by-reference. They are not nullable. They represent
the primitive concept of aliasing and pass-by-reference, and
they are the only feature that does so. Unlike C++ references,
you must use the &lt;code&gt;&amp;amp;&lt;/code&gt; operator to create a Rust reference, making
them explicit on the caller.&lt;/p&gt;
&lt;p&gt;Smart pointers are, for the most part, also not nullable, possibly
partially because Rust has &lt;a href=&#34;https://www.thecodedmessage.com/posts/cpp-move/&#34;&gt;destructive moves&lt;/a&gt;.
They represent ownership semantics &amp;ndash; whether &amp;ldquo;unique&amp;rdquo; ownership (&lt;code&gt;Box&lt;/code&gt;),
shared ownership (&lt;code&gt;Rc&lt;/code&gt; or &lt;code&gt;Arc&lt;/code&gt;), or locking (&lt;code&gt;Mutex&lt;/code&gt; or &lt;code&gt;RefCell&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Raw pointers in Rust are very special &amp;ndash; they are for implementing
smart pointers or other low-level data structures. They are for
situations where the structure of memory and the concept of a pointer
is actually key to the situation. They are kept within these narrow
bounds, and outside of everyday application programming, by having
most of their features considered &lt;code&gt;unsafe&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If only that could be done for raw pointers in C++! But there is too
much momentum behind the C++ raw pointer.&lt;/p&gt;
&lt;h2 id=&#34;dynamic-vs-static-polymorphism&#34;&gt;Dynamic vs Static Polymorphism&lt;/h2&gt;
&lt;p&gt;This is the most intense one, and could be a blog post all
on its own &amp;ndash; and probably I&amp;rsquo;ll write it one day.&lt;/p&gt;
&lt;p&gt;In response to comments, I&amp;rsquo;m going to add a caveat here even though
I address it later: In this section, I&amp;rsquo;m discussing the status of C++
pre-concepts, from C++17 and earlier, because that is the form of C++
that most people are still using, and that the vast majority of code is
still written in. It is too early to tell how much concepts will help,
but because they are an optional feature, I&amp;rsquo;m not at all optimistic.&lt;/p&gt;
&lt;p&gt;We have two forms of polymorphism in C++, two very different
systems. One is a Turing-complete macro system that comprises
overloads, templates, and template metaprogramming. The other
is an object-oriented style system of polymorphism through
inheritance.&lt;/p&gt;
&lt;p&gt;They were designed with different purposes in mind, and considering
their original purpose, it&amp;rsquo;s clear to see why they must have
different implementations.&lt;/p&gt;
&lt;p&gt;Templates were designed for collections and algorithms, for being
able to write a vector or linked list that could contain any arbitrary
type, without resorting to a C-style &lt;code&gt;void*&lt;/code&gt; that would require both
indirection and type erasure. The lack of indirection is the point &amp;ndash;
at least it was for C++ &amp;ndash; and so as a consequence templates had to be
carried out statically.&lt;/p&gt;
&lt;p&gt;Dynamic polymorphism, on the other hand, was designed for OOP design
patterns. As such, in line with OOP principles, it supports heterogeneous
containers, especially necessary to support OOP&amp;rsquo;s core use case of GUI
programming.&lt;/p&gt;
&lt;p&gt;But in spite of this deep contrast between static and dynamic, they
overlap in use case. For example, Smalltalk, Objective-C, and
Java (pre Java 5) all show us that you can use dynamic polymorphism
to implement generic containers. If C++ had been less performance-centric,
and could tolerate the indirection, it could have used a similar strategy,
the (old school) Java approach to generic containers without generics
or templates:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Make all classes inherit from a universal base class, &lt;code&gt;Object&lt;/code&gt;.
This way, &lt;code&gt;Object *&lt;/code&gt; (just &lt;code&gt;Object&lt;/code&gt; in Java) can refer to any object.
Make sure, for C++, that this has a virtual destructor, so you can
delete any object through its &lt;code&gt;Object*&lt;/code&gt; handle.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write &amp;ldquo;boxed versions&amp;rdquo; of all primitive types, classes that
extend &lt;code&gt;Object&lt;/code&gt; to correspond to &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;double&lt;/code&gt;, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write all collection classes (&lt;code&gt;std::vector&lt;/code&gt;, &lt;code&gt;std::list&lt;/code&gt;) in terms
of &lt;code&gt;Object *&lt;/code&gt;, writing &lt;code&gt;Object *&lt;/code&gt; instead of &lt;code&gt;T&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use RTTI and &lt;code&gt;dynamic_cast&lt;/code&gt; (or in Java terms, casts) to allow
the user to get whatever object type they want out of them.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Voilà! You can now store anything in your collections without need
for generics or templates, using &lt;code&gt;dynamic_cast&lt;/code&gt;, an obscure feature of
the OOP-style dynamic polymorphism that C++ has. And this system is in
fact still the basis of Java generics, and so we can project that C++
would have used something similar if performance weren&amp;rsquo;t a concern and
indirections and RTTI were acceptable.&lt;/p&gt;
&lt;p&gt;So that shows the overlap between templates and runtime polymorphism
in a theoretical sense, but do these very differently implemented
features in fact overlap in practice?&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve seen skepticism. I once interviewed
people for a job, and I asked candidates to explain to me the
similarities and differences between dynamic polymorphism and
templates. The candidate said there was no overlap; templates
were for generic programming (e.g. collections and algorithms and STL),
and dynamic polymorphism was for object-oriented programming.&lt;/p&gt;
&lt;p&gt;But they do overlap in practice. I know, because I spent a lot of
time transitioning object-oriented dynamic code into static form,
and teaching the static equivalents to dynamic polymorphism patterns.
It wasn&amp;rsquo;t easy, because even though the overlap is huge, the
semantics are vastly different.&lt;/p&gt;
&lt;p&gt;Let me give an example. Let&amp;rsquo;s start with one of my favorite patterns:
the policy pattern.  Let&amp;rsquo;s imagine we have a function that sends messages
in a way that can fail, and let&amp;rsquo;s also imagine that we have a policy
that indicates how we should delay and retry sending this message. I&amp;rsquo;ll
start out writing it the object-oriented way, something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;struct RetryPolicy {
    virtual bool should_retry(mesg_send_err_t error_code) = 0;
    virtual uint32_t delay_microseconds() = 0;
};

mesg_send_err_t retry_send_message(Message &amp;amp;mesg, RetryPolicy &amp;amp;policy) {
    while (true) {
        auto err = send_message_once(mesg);
        if (err == mesg_send_err_t::SUCCESS) {
            return mesg_send_err_t::SUCCESS;
        } else if (!policy.should_retry(err)) {
            return err;
        } else {
            usleep(policy.delay_microseconds());
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The policy can then do things like &amp;ldquo;retry 5 times, waiting 0.01 seconds
between each retry&amp;rdquo; or &amp;ldquo;exponential back-off, so that each retry waits
twice as long as the previous.&amp;rdquo; It can also deem certain errors as
fatal, but others as worth sleeping and retrying for. Here&amp;rsquo;s
an example of using this interface:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;struct WaitOneSecondAndTryFiveTimes : RetryPolicy {
    int retry_count = 0;

    bool should_retry(mesg_send_err_t error_code) override {
        if (error_code == mesg_send_err_t::MALFORMED_MESG) {
            return false;
        }

        retry_count++;
        if (retry_count == 5) {
            return false; // do not retry
        }

        return true; // do retry
    }

    uint32_t delay_microseconds() override {
        return 1000000;
    }
};

WaitOneSecondAndTryFiveTimes policy;
auto err = retry_send_message(mesg, policy);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, it turns out we can do this exact same pattern with static polymorphsim.
The callee code now looks like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;template &amp;lt;typename T&amp;gt;
mesg_send_err_t retry_send_message(Message &amp;amp;mesg, T policy) {
    while (true) {
        auto err = send_message_once(mesg);
        if (err == mesg_send_err_t::SUCCESS) {
            return mesg_send_err_t::SUCCESS;
        } else if (!policy.should_retry(err)) {
            return err;
        } else {
            usleep(policy.delay_microseconds());
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is no longer a function. It is a function template, which is a type
of macro. Its implementation must now move from the &lt;code&gt;.cpp&lt;/code&gt; file to the
&lt;code&gt;.h&lt;/code&gt; or &lt;code&gt;.hpp&lt;/code&gt; file, for reasons that only make sense if you think about
how the programming language is implemented.&lt;/p&gt;
&lt;p&gt;No longer is the policy interface spelled out separately. The only
thing the function signature says about the type of &lt;code&gt;policy&lt;/code&gt; is
that it is &lt;code&gt;T&lt;/code&gt; &amp;ndash; which can be any type. Only in the implementation,
in the body, do we see that &lt;code&gt;should_retry()&lt;/code&gt; and &lt;code&gt;delay_microseconds()&lt;/code&gt;
must be implemented on it. This is an implicit interface, defined by
usage, very similar to Python and Ruby&amp;rsquo;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Duck_typing&#34;&gt;duck
typing&lt;/a&gt;. More importantly,
it is completely unrelated to the OOP-style explicit interface
using inheritance and virtual functions.&lt;/p&gt;
&lt;p&gt;The errors are completely different, because the rules are completely
different.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;test.cpp:57:34: error: variable type &amp;#39;WaitOneSecondAndTryFiveTimes&amp;#39; is an abstract class
    WaitOneSecondAndTryFiveTimes policy;
                                 ^
test.cpp:22:22: note: unimplemented pure virtual method &amp;#39;delay_microseconds&amp;#39; in &amp;#39;WaitOneSecondAndTryFiveTimes&amp;#39;
    virtual uint32_t delay_microseconds() = 0;
                     ^
1 error generated.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;With the template version, you get:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;test.cpp:34:27: error: no member named &amp;#39;delay_microseconds&amp;#39; in &amp;#39;WaitOneSecondAndTryFiveTimes&amp;#39;
            usleep(policy.delay_microseconds());
                   ~~~~~~ ^
test.cpp:59:16: note: in instantiation of function template specialization &amp;#39;retry_send_message&amp;lt;WaitOneSecondAndTryFiveTimes&amp;gt;&amp;#39; requested here
    auto err = retry_send_message(mesg, policy);
               ^
1 error generated.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The ad-hoc nature of template requirements should not be underestimated.
It means that objects that are designed to work with a whole library might
only work with the exact combinations of functions they&amp;rsquo;ve been used
with so far. It means that documentation, if it wants to be rigorous,
must do the work of defining the protocols itself of every argument
taken by every function. It means that it&amp;rsquo;s not clear when you&amp;rsquo;re
putting new requirements on arguments to a function, as there is no
warning and no clear red-line step to tell you that you&amp;rsquo;re breaking
backwards-compatibility.&lt;/p&gt;
&lt;p&gt;Concepts have been introduced recently to clean it up, and I think
it&amp;rsquo;s still early to tell how good a job they will do. But even if
they do a great job, the polymorphism will still look very
different from the OOP style, and the old template-based code
will still exist, and so in the meantime the C++ programming language
has simply continued to grow.&lt;/p&gt;
&lt;p&gt;And the concrete consequences: It&amp;rsquo;s a perfectly reasonable decision to
use OOP-style polymorphism, for the benefits of cleaner structure and
explicit specification of the interface, even when the dynamic nature of
the polymorphism &amp;ndash; and its concomittant performance costs &amp;ndash; is never
actually called for. Meanwhile, using static polymorphism to accomplish
the same goals is simply harder, requiring much more skill and training.&lt;/p&gt;
&lt;h3 id=&#34;how-rust-handles-this-3&#34;&gt;How Rust Handles This&lt;/h3&gt;
&lt;p&gt;Like C++, Rust has both static (compile-time) polymorphism, and dynamic
(run-time) polymorphism. Unlike C++, Rust integrates them closely into
a single feature, inspired by Haskell&amp;rsquo;s typeclasses: traits.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s use the same example again, but in Rust, using static polymorphism,
which is the more Rusty way to write such a function:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;trait RetryPolicy {
    // Return None to not retry at all
    // Takes `self` as `&amp;amp;mut` to implement counting and back-off
    fn retry_microseconds(&amp;amp;mut self, error: MesgSendError) -&amp;gt; Option&amp;lt;Duration&amp;gt;;
}

fn retry_send_message(mesg: &amp;amp;Message, mut policy: impl RetryPolicy) -&amp;gt; Result&amp;lt;(), MesgSendError&amp;gt; {
    loop {
        match send_message_once(mesg) {
            Ok(()) =&amp;gt; {
                return Ok(());
            }
            Err(err) =&amp;gt; match policy.retry_microseconds(err) {
                None =&amp;gt; {
                    return Err(err);
                }
                Some(delay) =&amp;gt; sleep(delay),
            },
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I changed the example a little to showcase some other differences with
Rust. Instead of querying two functions, for example, to know whether
to try again and how long to delay, I feel in Rust it is more natural
to use sum types (and in particular &lt;code&gt;Option&lt;/code&gt;) to fold them into a single
function. Similarly, rather than a &lt;code&gt;u32&lt;/code&gt; count of microseconds,
&lt;code&gt;std::thread::sleep&lt;/code&gt; takes a &lt;code&gt;Duration&lt;/code&gt;, and so I felt the policy trait
should reflect that as well. Also, last but not least, in Rust it is
not necessary to consider &lt;code&gt;SUCCESS&lt;/code&gt; to be one of the error options,
and so the types are more well-honed to the situation.&lt;/p&gt;
&lt;p&gt;Notice, however, that this is the more performant static version,
and it has an explicit in-code specification of what the interface
is for the policy. However, the policy code and the generic code
are fully integrated just like in the C++ templated version,
through a process known as monomorphization. Fundamentally,
monomorphization exhibits the same behavior to C++ template
instantiation, but in a more principled, constrained fashion.&lt;/p&gt;
&lt;p&gt;Here is the example of the usage of such a polymorphic function:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;struct WaitOneSecondAndTryFiveTimes {
    retry_count: u32,
}

impl WaitOneSecondAndTryFiveTimes {
    fn new() -&amp;gt; Self {
        Self {
            retry_count: 0,
        }
    }
}

impl RetryPolicy for WaitOneSecondAndTryFiveTimes {
    fn retry_microseconds(&amp;amp;mut self, err: MesgSendError) -&amp;gt; Option&amp;lt;Duration&amp;gt; {
        if err == MesgSendError::MalformedMessage {
            return None;
        }

        self.retry_count += 1;
        if self.retry_count == 5 {
            return None;
        }

        Some(Duration::from_secs(1))
    }
}

let policy = WaitOneSecondAndTryFiveTimes::new();
let res = retry_send_message(&amp;amp;mesg, policy);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we wanted to use dynamic polymorphism for some reason &amp;ndash; for example,
if we wanted to look the policy up in some sort of map based on a
user-supplied keyword, or load the policy from a dynamic library &amp;ndash; we
could, easily.&lt;/p&gt;
&lt;p&gt;Unlike in C++, barely anything has to change. In fact,
only three lines have to change.&lt;/p&gt;
&lt;p&gt;The function signature has to change, to indicate that it&amp;rsquo;s using
dynamic polymorphism now. Dynamic polymorphism, due to its nature,
can only be done through indirection, so we have to add that (though
it does not affect the function body):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn retry_send_message(mesg: &amp;amp;Message, policy: &amp;amp;mut dyn RetryPolicy) -&amp;gt; Result&amp;lt;(), MesgSendError&amp;gt; {
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Similarly, the call site has to change, to implement the indirection:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;let mut policy = WaitOneSecondAndTryFiveTimes::new();
let res = retry_send_message(&amp;amp;mesg, &amp;amp;mut policy);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And that&amp;rsquo;s it! Now it&amp;rsquo;s dynamic polymorphism!&lt;/p&gt;
&lt;p&gt;When I first saw this is when I was truly convinced that Rust would
eclipse C++.&lt;/p&gt;
&lt;h1 id=&#34;discussion-and-conclusion&#34;&gt;Discussion and Conclusion&lt;/h1&gt;
&lt;p&gt;So, assuming I&amp;rsquo;ve convinced you that Rust has a better organized
feature-set than C++, we have to discuss what, in the big picture,
C++ has done wrong and Rust has done right.&lt;/p&gt;
&lt;p&gt;The first and most obvious thing Rust did right was learn from the
mistakes of the past. Each new version of C++ has to be compatible with
previous versions to a great extent, including (in a lot of ways) C,
giving it a legacy back into the early 70&amp;rsquo;s. Rust started maintaining
compatibility in 2015, and so it&amp;rsquo;s only had 7 years or so of cruft,
but knew about all of C++&amp;rsquo;s later add-ons from the beginning.&lt;/p&gt;
&lt;p&gt;And one of the things Rust learned from the experience of others is
how to mitigate this effect, so we can hope Rust retains its youthful
freshness for longer going forward. Rust has an edition system, so
that features actually can be deprecated and phased out, while still
maintaining compatibility.&lt;/p&gt;
&lt;p&gt;But also, Rust&amp;rsquo;s goal of separating safe and unsafe features &amp;ndash; and
keeping unsafe code encapsulated using the &lt;code&gt;unsafe&lt;/code&gt; keyword &amp;ndash; forces
Rust&amp;rsquo;s feature set to be more coherent. If two features clash in C++,
the standards committee can put the work of reconciling them on the
programmer, but in Rust, they often have to do the work to make
them make sense together, so they can continue to guarantee that
safe code can&amp;rsquo;t cause undefined behavior.&lt;/p&gt;
&lt;p&gt;Additionally, Rust believes in, and has, invariants. In C++, some
structs can be trivially copied. In Rust, all data types can
be trivially moved (&lt;code&gt;Pin&lt;/code&gt; is almost but not quite an exception,
and the work that went into making &lt;code&gt;Pin&lt;/code&gt; not break everything
shows how important the invariant is.) In Rust, a mutable reference
always means that a block of code has exclusive access to a value.
These invariants also structure other features, and force them
to work in concert.&lt;/p&gt;
&lt;p&gt;Enough about Rust, though. I think there&amp;rsquo;s deeper lessons to be learned
from the flaws in C++. Bjarne Stroustrup famously said, &amp;ldquo;Within C++,
there is a much smaller and cleaner language struggling to get out.&amp;rdquo; I
think he regrets the quote, which he clarified is about the modern
semantics of C++, held down by the outdated syntax of C.  It&amp;rsquo;s such a
compelling quote, though, because C++ is so messy and dirty, so we want
to believe in a small clean underlying core.&lt;/p&gt;
&lt;p&gt;The truth, however, is that there isn&amp;rsquo;t &lt;em&gt;one&lt;/em&gt; smaller and cleaner
programming language struggling to get out. There&amp;rsquo;s multiple. And
from the beginning, C++ was a glomming-together of multiple ideas: a
Simula-like OOP system glued awkwardly to C, without a unified motivating
vision. Operator overloading was intended to help integrate the two
parts, which it did but at the expense of creating its own entire
sub-paradigm. And then came templates, which tried to add generic
containers and algorithms but unexpectedly exploded into their own
programming paradigm.&lt;/p&gt;
&lt;p&gt;So inside C++, struggling to get out, is of course C, the original
&amp;ldquo;portable assembly,&amp;rdquo; which does its very simple job well. There&amp;rsquo;s also
Java/C# in there, if we take the OOP features on their own.  For the
operator overloading and RAII and templates, the closest I can really
imagine is Rust, which I think if Bjarne was being fair, he would have
to admit is close to what he specified when he clarified his quote:
Rust does emphasize &amp;ldquo;programming styles, libraries and programming
environments that emphasized the cleaner and more effective practices
over archaic uses focused on the low-level aspects of C.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s understandable that Bjarne glommed OOP, a foreign paradigm, onto
the otherwise-stable base of C.  OOP was extremely popular for a long
time, and has been awkwardly glommed on to many programming languages,
and I think Rust benefits from not even trying to be an OOP language in
the traditional 3-pillar sense (Rust doesn&amp;rsquo;t have inheritance at all,
and has non-OOP concepts of encapsulation and polymorphism).&lt;/p&gt;
&lt;p&gt;C++ wasn&amp;rsquo;t even the only programming language to result from glomming
on object-oriented programming to C, and of the two big ones, it is
the more coherently integrated. Objective-C comes from a more dynamic
tradition of object-oriented programming, and it really feels like
two programming languages glued together, in this case C and Smalltalk.&lt;/p&gt;
&lt;p&gt;I programmed Objective-C professionally for a while, and most of the
time, the C only came out when you had to do a little bit of pure logic
outside of the object-oriented framework. In the meantime, all of the OOP
code had to be written using the little whisps of syntax C left behind,
especially &lt;code&gt;@&lt;/code&gt;, which basically served as a sigil to indicate that what
followed was to be interpreted in an Objective-C way &amp;hellip; which in an
Objective-C codebase basically should have been the default.&lt;/p&gt;
&lt;p&gt;At the time, I dreamed of the leaner programming language inside
Objective-C (the non-C one), and even started designing a Smalltalk
dialect designed to interact with Apple&amp;rsquo;s Cocoa APIs: CocoaTalk, I
think it was called. Ultimately, Apple unveiled their concept of it,
sharing many ideas with Rust, known as Swift. I felt very vindicated
the day Swift was announced.&lt;/p&gt;
&lt;p&gt;Rust is C++&amp;rsquo;s chance to get a leaner, cleaner programming language.
The syntax is heavily influenced by C++, even as the semantics come
from a variety of sources. The design was done &lt;em&gt;de novo&lt;/em&gt; with guiding
principles that allowed all of C++&amp;rsquo;s vast repertoire of features to
be reimagined but working in concert with each other.  As someone who
used to love programming in C++, which enabled programming techniques
no other programming language could, I continue to be deeply impressed
by the feature design of Rust.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>A Checklist of Dev-Ops Disciplines</title>
      <link href="https://www.thecodedmessage.com/posts/process-checklist/" />
      <id>https://www.thecodedmessage.com/posts/process-checklist/</id>
      <updated>2022-05-09T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I have worked on a lot of programming projects in my time, and while I
was a programming consultant I have worked in a lot of different corporate
environments. At some of them, it was easy to be concretely productive:
I was able to contribute immediately, and at a rapid rate. At others,
actual useful contributions would be impossible until I had a month or
more of experience with a codebase, and even then every change would be
a long slog. The difference can be overwhelming and palpable.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I have worked on a lot of programming projects in my time, and while I
was a programming consultant I have worked in a lot of different corporate
environments. At some of them, it was easy to be concretely productive:
I was able to contribute immediately, and at a rapid rate. At others,
actual useful contributions would be impossible until I had a month or
more of experience with a codebase, and even then every change would be
a long slog. The difference can be overwhelming and palpable.&lt;/p&gt;
&lt;p&gt;The biggest contributors to this difference wasn&amp;rsquo;t what programming
language was chosen (though I do &lt;a href=&#34;https://www.thecodedmessage.com/posts/hello-rust/&#34;&gt;care a lot&lt;/a&gt; about
that), nor how well the code was factored (though that&amp;rsquo;s also very
important), but rather the organizational structure that surrounded
the code: the build system, the repo configuration, the tests, the
documentation, the ticketing system &amp;ndash; the stuff outside of the code
itself that was essential to how programmers interacted with the code.
Most, but not quite all, of what I&amp;rsquo;m talking about falls under the header
of &lt;a href=&#34;https://en.wikipedia.org/wiki/DevOps&#34;&gt;Dev Ops&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After having read (some of) &lt;a href=&#34;https://www.amazon.com/Code-That-Fits-Your-Head/dp/0137464401/&#34;&gt;&lt;em&gt;Code That Fits in Your
Head&lt;/em&gt;&lt;/a&gt;, I
have come to believe in the importance of check-lists, so I&amp;rsquo;ll share
with you my personal check-list of important dev-ops and dev-ops
adjacent considerations when setting up a new project, so that
developers can work rapidly, effectively, and with fewer mistakes.&lt;/p&gt;
&lt;p&gt;The stakes are high &amp;ndash; if it takes forever to make a change, if the
process between modifying your code and running your code is too long,
programmers won&amp;rsquo;t be able to work unless they&amp;rsquo;re much more confident,
biasing them towards overly simple fixes and against more complicated
refactors. If there&amp;rsquo;s no tests, programmers will be overly careful
modifying the code to avoid breaking things, and so the code won&amp;rsquo;t
be able to evolve. New team members will take much longer to gear up,
and everyone will be much less productive.&lt;/p&gt;
&lt;p&gt;The worst thing is, managers are liable to dismiss developers&amp;rsquo; complaints,
and developers are unlikely to have the confidence to raise them. It&amp;rsquo;s
easy to be unsympathetic to the complaint that a job is tedious or
inconvenient. It sounds to many programmers and managers alike like
laziness, and the obvious answer is &amp;ldquo;Well, that&amp;rsquo;s why we pay you the
big bucks.&amp;rdquo;  Obviously development at these shops is still possible,
and the old hands at the company, who are used to whatever system&amp;rsquo;s in
place, have accepted the costs already.&lt;/p&gt;
&lt;p&gt;But make no mistake: Developer convenience and happiness is closely
connected to developer productivity and accuracy. So let&amp;rsquo;s discuss
how to make a development environment convenient for a developer.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s how we can make programming convenient, as a check-list with
some explanation for each item. Many of these items I learned from
colleagues and leaders along the way in my programming career; this
is my first attempt to collect all of them.&lt;/p&gt;
&lt;h1 id=&#34;development-environment&#34;&gt;Development Environment&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Let programmers use their own preferred development environment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many developers have life-long habits and long-accumulated configurations
for their favorite editors. I know I do! Standardizing IDEs or even
operating systems can be tempting, but in general it isn&amp;rsquo;t worth
it. Programming includes a lot of little steps, and making all of them
take longer by changing a programmer&amp;rsquo;s environment can destroy momentum.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide standards for developer workstations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This might seem to contradict the previous point, but I honestly think you
need both. It should be super easy to figure out what kind of operating
system requirements and dependencies are necessary to build all the
projects, because, as we&amp;rsquo;ll get to soon, developers should be able to
build projects locally.&lt;/p&gt;
&lt;p&gt;For example, most Linux distributions are customizable enough that
programmers will be able to find a development environment within that
distribution that suits them. The dependencies of a project can then be
specified as a package list within that distribution, but the developers
can then customize the rest of their interface. Commonly used distributions
should be preferred if developers are doing their own IT, so that they
can easily find help online.&lt;/p&gt;
&lt;h1 id=&#34;build-system&#34;&gt;Build System&lt;/h1&gt;
&lt;p&gt;You&amp;rsquo;ve changed a line of code. Congratulations! Now how long will it be
until you can see the results of your change in action? How many steps
do you have to take to see if it fixed your issue? If it broke compilation?
If it passes tests?&lt;/p&gt;
&lt;p&gt;If the amount of time or number of steps is low, then people will be able
to try out various solutions, use trace statements to debug issues, and
otherwise interact with their code like a live system. If it&amp;rsquo;s high,
they have to rely more on their own reasoning, which is fallible, more
likely to lead to bugs, and more likely to lead to timid, overly-conservative
changes, that work around problems rather than addressing them.&lt;/p&gt;
&lt;p&gt;So how do we accomplish this?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Projects should run natively and directly on developer workstations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In my mind, this is almost a deal-breaker for development. If you have
to deploy to a dev environment or install on a physical piece of embedded
hardware to test your software, your dev cycle will be far too long. Dev
environments and physical hardware are of course essential for testing,
but using them for absolutely all development introduces resource
constraints where there don&amp;rsquo;t have to be, and lengthens dev cycles.&lt;/p&gt;
&lt;p&gt;Even if the local dev environment is different from the prod environment,
that&amp;rsquo;s fine. Even if some of the code won&amp;rsquo;t run and make sense, it&amp;rsquo;s still
important to be able to run the rest of code locally. Even if it&amp;rsquo;s running
on an embedded platform and operating system with no proper simulator,
some of the code will work on Linux or macOS. Those components should
be testable on the developer workstation itself.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Building a project locally should be a single command&lt;/li&gt;
&lt;li&gt;Building and running automated tests for a project should be a single command&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When I say a single command, I mean it. Exactly one. Two is far too
many. Once you try it, you&amp;rsquo;ll never go back. If your workplace doesn&amp;rsquo;t do
this, write a script. Check the script in.&lt;/p&gt;
&lt;p&gt;Of course, if different developers have different computers, this
might be difficult, but if you assume a standard set of dependencies,
(or use a reproducible build system like NixOS), this command can
just be an invocation of the build system.&lt;/p&gt;
&lt;p&gt;In situations where it&amp;rsquo;s more complicated, a shell script should be
written to encapsulate the complexity. This shell script should be included
in the repo and maintained and checked by CI along with the other code,
so that it always works. The exact invocation of the command should
be completely invariate, and documented in the projects &lt;code&gt;README.md&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;Programmers don&amp;rsquo;t need to be distracted by complicated multi-part
instructions that haven&amp;rsquo;t worked exactly right in years, or that work
on some machines and not others or by twiddling with their Docker
settings. They should be focused on actually improving and fixing
code.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Building and running a project locally should be a single command&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is similar to the above but might require sample configuration to
be checked in along with the repo.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Builds should be reasonably fast&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Developers should program on sufficiently powerful computers for their
builds. Build scripts should use options like &lt;code&gt;-j&lt;/code&gt; and if helpful send
builds seamlessly to build farms (the seamlessness is important; it
should still be a single command for the developer and result in a local
build and run). Private caches should be set up, if this is possible
with your build system.&lt;/p&gt;
&lt;p&gt;If programming in C or C++, header file hygiene can be
an important consideration in build speeds &amp;ndash; invest time into it.
Use incrementality features of your build systems rather than having
scripts that clean every time. Structure the code so that incremental
builds are possible.&lt;/p&gt;
&lt;p&gt;If necessary, allow developers to build only part of the project (while
still making it simple to build the entire project).&lt;/p&gt;
&lt;h1 id=&#34;version-control&#34;&gt;Version Control&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Use version control for all projects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is hopefully obvious to all modern teams, but I wanted to make sure
I said it anyway to talk some about why it&amp;rsquo;s important.&lt;/p&gt;
&lt;p&gt;The first and more obvious upshot of version control is being able
to undo and research mistakes. If the code changed how it works, developers
should be able to ask &amp;ldquo;when did it break&amp;rdquo; before asking &amp;ldquo;how did it break.&amp;rdquo;
If the changes in the log are fine-grained enough, this might prevent the
need for investigating the &amp;ldquo;how.&amp;rdquo; (Note that bisecting often requires
fast dev turn-around as well &amp;ndash; these are interconnected.) Version
control should always be used. Even informal, one-person projects, such
as writing test programs to try out APIs, should exist within a
version-controlled repo.&lt;/p&gt;
&lt;p&gt;The second upshot is that it enables collaboration. This also makes it
important even for very small projects, because it enables you to easily
ask your colleagues for help, and your colleagues can then look at the
code with their own preferred development environment and try out fixes
on their own machine.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Developers should be proficient in Git&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s not enough to &lt;a href=&#34;https://xkcd.com/1597/&#34;&gt;cargo cult&lt;/a&gt; Git knowledge
or focus on that &amp;ldquo;one guy who understands Git.&amp;rdquo; Everyone should put the
effort in to be that &amp;ldquo;one guy.&amp;rdquo; If you don&amp;rsquo;t know what &amp;ldquo;reflog&amp;rdquo; means
or how rebasing differs from merging or how to edit commits deep in
the history, you&amp;rsquo;re not a sufficiently proficient git user. Many, perhaps
even most, programmers aren&amp;rsquo;t.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use and Enforce a Branching Discipline&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Even on relatively small projects, no one should be committing and pushing
directly to the &lt;code&gt;trunk&lt;/code&gt;/&lt;code&gt;main&lt;/code&gt;/&lt;code&gt;master&lt;/code&gt; branch. If people push directly
to &lt;code&gt;master&lt;/code&gt;, every commit is automatically collaborative. This will make
developers commit less frequently than they otherwise should, and will
decrease the effectiveness of version control by having fewer versions
to go back to.&lt;/p&gt;
&lt;p&gt;It will also, obviously, lead to people accidentally &amp;ldquo;breaking the build&amp;rdquo;
as projects get bigger. Committing a small change and merging that
change into &lt;code&gt;trunk&lt;/code&gt; or &lt;code&gt;develop&lt;/code&gt; should be two different actions. The
first should be done extremely often, and the second should only be
allowed if a certain number of hoops have been jumped through.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enforce CI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before code can be merged into master, it should build. By default, merging
into master should be impossible unless the repository has verified the
build with CI. This is where we can easily test that it builds in a
deployment setting in addition to a development setting, where
artifacts can be created to deploy to servers or embedded devices
(though this should also be possible to do locally) and where
we can run automated tests. Coding standards should be enforced here,
through lints. &lt;code&gt;clippy&lt;/code&gt; and &lt;code&gt;cargo fix&lt;/code&gt; are great tools for Rust.&lt;/p&gt;
&lt;p&gt;Ideally, your CI scripts should be checked into the same repo as the systems
they test, as is supported by GitLab with its &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; files.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Have tests in the repo&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is related. I&amp;rsquo;m not going to go into how to write tests and test
coverage and all of that here; that&amp;rsquo;s again a separate topic for many
many books. But there should be tests, and the important tests should
be in the repo, and they should automatically be run by CI.&lt;/p&gt;
&lt;p&gt;Remember: Tests aren&amp;rsquo;t just a tool for making sure the developers didn&amp;rsquo;t
mess up after a fact. They&amp;rsquo;re there so developers can make sweeping
changes with confidence.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Avoid mono repos&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This one&amp;rsquo;s simple: The git log is too spammy and CI for the whole thing
takes too long to run. Also, we have the technology of submodules, or,
if on Nix, &lt;a href=&#34;https://github.com/obsidiansystems/nix-thunk&#34;&gt;&lt;code&gt;nix-thunk&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Require code review&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This should be enforced by your Git system. As for how to actually do code
review, this is a big enough topic to be its own section, which is coming up.&lt;/p&gt;
&lt;h1 id=&#34;code-review&#34;&gt;Code Review&lt;/h1&gt;
&lt;p&gt;The main point of code review is not to make sure bugs don&amp;rsquo;t get into
the code, although it helps with that. The main point of code review is
to mitigate &lt;a href=&#34;https://en.wikipedia.org/wiki/Bus_factor&#34;&gt;bus factor&lt;/a&gt;, that
is, to make sure there&amp;rsquo;s more than one person who is ready to maintain
the code. All other guidance flows from here.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;At least the person who maintains the code should also review&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the MR is written by the primary maintainer of the codebase,
it should reviewed by whoever would have to step up if they
were abruptly &amp;ldquo;hit by a bus.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This ensures that everyone maintaining the code is in agreement
with not just style and correctness concerns, but in the general
design, architecture, and organization of the code.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The standard should be &amp;ldquo;Would I take responsibility to maintain this?&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the answer is no, why not? Asking myself this question motivates me
to make more suggestions about how the code should be factored, so I
can jump in and make changes easily like I can with my own codebases,
rather than just simply verify that it looks like it works and doesn&amp;rsquo;t
have any &lt;code&gt;unwrap()&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;This question leads to some natural sub-questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How hard is it to find bugs in?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It shouldn&amp;rsquo;t just not have bugs, it should be obvious it doesn&amp;rsquo;t
have bugs. This way, when a bug is actually discovered, code that isn&amp;rsquo;t
buggy but is complicated won&amp;rsquo;t distract the poor developer trying to find
the cause.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How hard is it to modify to do something else?&lt;/li&gt;
&lt;li&gt;How easy is it to mess up?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where DRY (don&amp;rsquo;t repeat yourself) comes in. If I repeat
the same pattern of code more than 2 times, and someone modifies it, they
might only modify some of the instances of the pattern. This can
also be mitigated not through abstraction but by putting all the instances
next to each other, which is sometimes appropriate.&lt;/p&gt;
&lt;p&gt;The code, however, should also not do premature abstraction, because
then it will be impossible to find issues among all the spaghetti of
function calls and variable references, so this is a balancing act.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If a bug is found to be caused by this change, will we know which
part to revert?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Remember, programmers should be able to
&lt;a href=&#34;https://git-scm.com/docs/git-bisect&#34;&gt;bisect&lt;/a&gt; instead of having to read
an entire codebase when they want to find a bug. If you found out that
the bug was caused by this change set, would you be relieved to know or would
you still have a lot of work ahead of you?&lt;/p&gt;
&lt;h1 id=&#34;documentation&#34;&gt;Documentation&lt;/h1&gt;
&lt;p&gt;Last but not least, documentation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documentation should say how to build the project&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It should, as mentioned, be one command, and it should not depend on very much
set up beyond &amp;ldquo;having a standard development workstation.&amp;rdquo;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documentation should say how to run the project&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What flags or configuration does it take? How do you tell it to re-read
the configuration? Does it use any environment variables?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Documentation should say what the project &lt;a href=&#34;https://www.thecodedmessage.com/posts/buried-lede&#34;&gt;is for&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This should be before how to build it and run it, and should
explain who might want to run it and where it fits into the broader
organization, and the first things a programmer might want to know
before looking at it. This will help people understand the stakes
of modifying it, and where to start looking for features. This
should be covered in the lede paragraph.&lt;/p&gt;
&lt;p&gt;Which leads me to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There should be a lede paragraph&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This should introduce the repo to someone who&amp;rsquo;s never heard of it
and doesn&amp;rsquo;t have any context for what they&amp;rsquo;ve stumbled across. It should
include its role in the company&amp;rsquo;s tech stack, its status, and what
technologies it uses.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s some examples:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is the main repo for our flagship product, and it is one of
our few repos that is not open source.
Customers use it directly to control the widget machines, which it
contains all the drivers for, and also Node.js code to serve
the user-facing web interface.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This is run as a twice-daily batch job to automate pruning the
widget description files. It is run on customer machines, and is
open source as local administrators might want to customize it.
It is written entirely in Perl 4 except for one module that is
written in APL. Sometimes, it doesn&amp;rsquo;t work correctly, and we have
to manually run an earlier version written in JCL and Cobol (link).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;This implements the new DSL for widget description. Currently, it only
supports translation to old widget descriptions, but it is hoped that
it will eventually be integrated into the main repo. It is a research
project still under active development. It is written in Haskell
and Idris, and contains, as a component, a custom Prolog interpreter.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Documentation should be discoverable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It should either be in the &lt;code&gt;README.md&lt;/code&gt; of the relevant repo or linked
to directly from there.&lt;/p&gt;
&lt;h1 id=&#34;ticket-systems&#34;&gt;Ticket Systems&lt;/h1&gt;
&lt;p&gt;I guess I lied when I said that documentation was last. Project management
is, I think, a topic for a different blog post, but what I wanted to
say about this is: It should be &lt;em&gt;very easy&lt;/em&gt; to add a new TODO item that
the programmer doesn&amp;rsquo;t have to remember anymore. If it takes too long to
make a ticket, developers will lose their flow on the project they were
trying to work on, or will produce fewer tickets, in a bad way.&lt;/p&gt;
&lt;p&gt;Ideal is &amp;ldquo;type a single sentence and press a single button&amp;rdquo; either
in web or (preferably) command line. The resultant TODO items can then
be fleshed out in a separate grooming meeting.&lt;/p&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;Paying attention to these things is a bigger multiplier on developer
productivity than finding &amp;ldquo;10x developers,&amp;rdquo; and is essential for
attracting and retaining good developers. Improving these things is hard,
especially at organizations that are set in their ways, but it is
far more important than it might look. Dedicated dev-ops professionals
are essential in such things.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Can you reproduce it?</title>
      <link href="https://www.thecodedmessage.com/posts/reproducibility/" />
      <id>https://www.thecodedmessage.com/posts/reproducibility/</id>
      <updated>2022-03-22T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;&lt;em&gt;NOTE: This post has the #programming tag, but is intended to be comprehensible
by everyone, programmer or not. In fact, I hope some non-programmers
read it, as my goal with this post is to explain some of what it means
to be a programmer to non-programmers. Therefore, it is also
tagged with &amp;ldquo;nontechnical&amp;rdquo;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;What is the most important skill for a software engineer?  It&amp;rsquo;s
definitely not any particular programming language; they &lt;a href=&#34;https://www.biblegateway.com/passage/?search=Ecclesiastes%201%3A4&amp;amp;version=KJV&#34;&gt;come and
go&lt;/a&gt;,
and a good programmer can pick them up as they work. It&amp;rsquo;s not estimating
how long a project will take, as important and elusive as that skill
is &amp;ndash; because fundamentally, no one can, and many, many programmers are
successful without having fully built up that skill.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;&lt;em&gt;NOTE: This post has the #programming tag, but is intended to be comprehensible
by everyone, programmer or not. In fact, I hope some non-programmers
read it, as my goal with this post is to explain some of what it means
to be a programmer to non-programmers. Therefore, it is also
tagged with &amp;ldquo;nontechnical&amp;rdquo;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;What is the most important skill for a software engineer?  It&amp;rsquo;s
definitely not any particular programming language; they &lt;a href=&#34;https://www.biblegateway.com/passage/?search=Ecclesiastes%201%3A4&amp;amp;version=KJV&#34;&gt;come and
go&lt;/a&gt;,
and a good programmer can pick them up as they work. It&amp;rsquo;s not estimating
how long a project will take, as important and elusive as that skill
is &amp;ndash; because fundamentally, no one can, and many, many programmers are
successful without having fully built up that skill.&lt;/p&gt;
&lt;p&gt;No, in my learned and considered opinion, the most important skill in
a software engineer is solving &amp;ndash; and preventing! &amp;ndash; problems. It is
squashing and preventing &amp;ldquo;bugs&amp;rdquo; &amp;ndash; those situations where the software
behaves in an undesirable fashion, where it fails to meet expectations,
whether or not you knew about those expectations ahead of time. That
is the crux of the software engineering skillset. Preventing and fixing
bugs is the goal which the other skills uphold, and the criterion by
which software engineering principles and practices should be evaluated.&lt;/p&gt;
&lt;p&gt;My other programming posts can be understood through that lens. All my
posts on why Rust is a better programming language than C++ &amp;ndash; the point
is that Rust, as a programming language, is top-notch bug repellant
technology. For any post about code organization and readability, the
reason it&amp;rsquo;s important for code to be organized and readable is so that
another programmer trying to find a bug is able to find it quickly,
or that a programmer trying to add a feature doesn&amp;rsquo;t end up also adding
more bugs, due to a misunderstanding of how the code works.&lt;/p&gt;
&lt;p&gt;But today, I wanted to talk less about the prevention, and more
about the squashing, about what to do when you&amp;rsquo;ve found a bug.&lt;/p&gt;
&lt;p&gt;So how do you squash bugs?&lt;/p&gt;
&lt;p&gt;First, I want to note that the most important bug-squashing tool is the
human brain.&lt;/p&gt;
&lt;p&gt;There is a tool, a type of program, called a &amp;ldquo;debugger,&amp;rdquo; but that is
less essential than you might think from the name. A debugger won&amp;rsquo;t fix
bugs for you, and unless the bug is a crash that actually happened, it
can&amp;rsquo;t even find them.  If a debugger could fix &amp;ndash; or even just find &amp;ndash;
all your bugs, that would be almost equivalent to a program that could
write programs, because, as mentioned before, preventing, finding, and
fixing bugs is the crux of the entire job, and I know it hasn&amp;rsquo;t been
automated, because I still get a paycheck.&lt;/p&gt;
&lt;p&gt;What a debugger &lt;em&gt;can&lt;/em&gt; do is attach to a running program, let you run it one
line at a time instead of all at once, and let you inspect the program&amp;rsquo;s
internal state to make sure it is what you think it is. Additionally,
if there is a crash, the debugger can inspect the crash data, sometimes
in the form of what&amp;rsquo;s known as a &amp;ldquo;core dump,&amp;rdquo; and tell you what line
of code was running when the crash happened, a &amp;ldquo;backtrace&amp;rdquo; of how the
program got there, and what values were in what variables then.&lt;/p&gt;
&lt;p&gt;This is all useful in the debugging process, but not essential.  The
program ought to be called an &amp;ldquo;inspector&amp;rdquo; &amp;ndash; or perhaps the &amp;ldquo;debugger&amp;rsquo;s
companion,&amp;rdquo; because as a programmer, the true debugger is you, and much
of what the &amp;ldquo;debugger&amp;rdquo; tool can do, you can do without it as well, using
(for example) more verbose log lines and error messages, and just good
old-fashioned reasoning power.&lt;/p&gt;
&lt;p&gt;So what do you do, when you have a bug? Where do you start?&lt;/p&gt;
&lt;p&gt;You might assume that the first thing to do when you see a bug is to try
to find out what caused it. But not only is that going to be difficult
without some initial steps, it can lead to problems, where you think
you&amp;rsquo;ve got it, you go and do your fix, think it&amp;rsquo;s better, and actually
the bug turns out to still be there.&lt;/p&gt;
&lt;p&gt;No, more important than trying to guess what might have caused a bug is
figuring out how to tell when the bug is actually fixed. If all we know is
&amp;ldquo;sometimes, the app crashes,&amp;rdquo; and we change something, and the app doesn&amp;rsquo;t
crash right away, well, is that because we fixed it, or is that because
it just happened to be one of those times where the app doesn&amp;rsquo;t crash?
If I had a nickel for every time a programmer &lt;em&gt;thought&lt;/em&gt; they&amp;rsquo;d fixed
a bug&amp;hellip;&lt;/p&gt;
&lt;p&gt;And this is where, although programming &lt;a href=&#34;https://www.hillelwayne.com/post/are-we-really-engineers/&#34;&gt;definitely
is&lt;/a&gt; a type of
engineering &amp;ndash; software engineering &amp;ndash; it has an advantage over other
engineering fields. With software, we can run the same program over
and over again, often almost for free, in a way that we can&amp;rsquo;t rebuild
a bridge or dig a new mine tunnel. With software, often &amp;ndash; not always,
but usually &amp;ndash; we can re-run a program, do a few things, and see if the
bug arises again. And then, through experimentation, we can come up with a
procedure that allows us to &lt;em&gt;always&lt;/em&gt; trigger the bug.&lt;/p&gt;
&lt;p&gt;In this way, &amp;ldquo;sometimes the app crashes&amp;rdquo; can be refined through experiment to
&amp;ldquo;when you go to the settings page in particular, sometimes, the app
crashes&amp;rdquo; which can then be refined to &amp;ldquo;when you go to the settings page,
and you&amp;rsquo;re not logged in, and you&amp;rsquo;re on an iPhone from the past 3 years,
it crashes &lt;em&gt;every time&lt;/em&gt;.&amp;rdquo; And now, you have a way of knowing when you&amp;rsquo;ve
fixed it. If you do those exact things, and it doesn&amp;rsquo;t crash, then you can
be confident that your fix actually took.&lt;/p&gt;
&lt;p&gt;Refining the conditions in which your bug is a bug, or rather, coming
up with a list of instructions to make the bug happen on purpose &amp;ndash;
ideally as short a list as possible &amp;ndash; is known in the business as
&amp;ldquo;reproducing the bug.&amp;rdquo; And it is the most important skill-set in
people who are testing software.&lt;/p&gt;
&lt;p&gt;Because if I&amp;rsquo;ve written some code, and someone else is testing it,
and they&amp;rsquo;ve gotten it to crash, but don&amp;rsquo;t know how or why it crashed
&amp;ndash; or especially if they don&amp;rsquo;t even know what they were doing when it
crashed &amp;ndash; well, that doesn&amp;rsquo;t do very much for me. I have no idea where
to even start. Because I haven&amp;rsquo;t experienced any crashes, I can&amp;rsquo;t
look at your crashes. It works on my machine. How can I solve a problem
I can&amp;rsquo;t even see?&lt;/p&gt;
&lt;p&gt;So this was a problem for me when I was a lowly iPhone programmer working
in a small three-person company. My app would have error messages pop
up &amp;ndash; and this was frequent, as my boss, who was not a programmer,
didn&amp;rsquo;t let me spend time improving how the app worked unless I was
making continuous visible progress. My boss would tell me that he&amp;rsquo;d
gotten an error message while using the app. Can I look into that?&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t know what to do. I always looked into it when I got error
messages, and was often able to reproduce them, find them, and fix them,
but obviously my boss was better at QAing my app than I was &amp;ndash;
at least in the triggering bugs department. So I told him so. &amp;ldquo;I don&amp;rsquo;t
know what to do &amp;ndash; I can&amp;rsquo;t fix it unless you can reproduce it.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;What happened subsequently confused me. My boss would text me, giddy,
for some reason acting as if he was winning an argument against me,
saying &amp;ldquo;I reproduced it.&amp;rdquo; And then he&amp;rsquo;d send me a screenshot of the
problem. He did this repeatedly. He seemed to think &amp;ldquo;reproducing the
bug&amp;rdquo; meant screenshotting the bug in action.&lt;/p&gt;
&lt;p&gt;Later I saw him in person, and he asked me about whether I&amp;rsquo;d fixed the
bug yet.  I tried to explain that that wasn&amp;rsquo;t enough; what I needed was
a step by step explanation of how to make the bug happen.  And he said
something along the lines of, &amp;ldquo;How can you still not believe me? I sent
the screenshot.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;I was flabbergasted. I said, &amp;ldquo;Wait. I&amp;rsquo;m not literally doing this as
a policy, where I don&amp;rsquo;t work on it unless you prove to me there&amp;rsquo;s an
actual problem. It&amp;rsquo;s not because I don&amp;rsquo;t believe you.  It&amp;rsquo;s not because
you have to convince me it&amp;rsquo;s real before I work on it.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;And my boss responded, with an affected, over-the-top laugh, &amp;ldquo;Haha,
no I get it.&amp;rdquo; And then paused a second and continued, &amp;ldquo;But you kinda
are though. That&amp;rsquo;s exactly what you&amp;rsquo;re doing.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Apparently, when I said &amp;ldquo;I can&amp;rsquo;t,&amp;rdquo; my boss heard &amp;ldquo;I won&amp;rsquo;t.&amp;rdquo; My boss
thought this was about me standing up for myself against potential
spurious work, and being overly strict about burdens of proof, rather
than me literally asking questions that would make it possible for me
to do my job and troubleshoot these issues.&lt;/p&gt;
&lt;p&gt;At this point, I was just shocked. How did he think I was going to
do my job?  Obviously I have to figure out what was going wrong. And
obviously &amp;ndash; or at least it was obvious to me &amp;ndash; that required follow-up
questions. Why was he so affronted by my follow-up questions? What
did he think fixing the issue looked like? Did he think I&amp;rsquo;d just say,
&amp;ldquo;Oh, error messages.  I must have left some extras in. I&amp;rsquo;ll go take them
out.&amp;rdquo; No, the error messages were the visible result that happened when
the code didn&amp;rsquo;t know how to proceed to accomplish its tasks, and I had
to go deeper in to find out why that was happening.&lt;/p&gt;
&lt;p&gt;Luckily, I was able to compose myself, and think quickly on my feet. I
knew I wasn&amp;rsquo;t going to be able to actually explain reproducibility
to him &amp;ndash; after all, I just had, and he somehow misinterpreted it as
insubordination &amp;ndash; so I fibbed a little.&lt;/p&gt;
&lt;p&gt;The debugger that came with Macs for debugging iPhones looked very
sophisticated, and to use it with the app, you had to connect the phone to
the computer with a cable. This would allow you to, as I said before,
inspect the current program state, and so on. It looked like a very
useful tool &amp;ndash; and it was. Just not as useful as the human brain,
and not something you could use to skip steps.&lt;/p&gt;
&lt;p&gt;But even though what I really needed was instructions on how to make
the bug happen, I told my boss that what I needed was for the bug
to actually happen &lt;em&gt;while&lt;/em&gt; the phone was plugged into the debugger.&lt;/p&gt;
&lt;p&gt;This served two purposes: It made him believe me that I wasn&amp;rsquo;t just
messing with him, and it gave him a concrete reason to reproduce
the bug. Now that he had the goal of making the error message pop
up while it&amp;rsquo;s plugged in, he was able to figure out for himself
that the easiest way to do that was to come up with a way to make
it happen on purpose.&lt;/p&gt;
&lt;p&gt;Now, when he found a new bug, he wouldn&amp;rsquo;t bring it to me until he was
prepared to make it happen while it was plugged in. Some of them, he
already knew how to trigger; he just hadn&amp;rsquo;t heard an adequate explanation
for why he should tell me. Other bugs, he would figure out. In either
case, once he was done, he would make the bug happen while it was
plugged in.&lt;/p&gt;
&lt;p&gt;And when this happened, I could either ask him how he got it to happen,
casually, while pretending that the more important thing is that it&amp;rsquo;s
plugged in, and while he sees that I&amp;rsquo;m using a computer and therefore
&amp;ldquo;working&amp;rdquo; &amp;ndash; or, if the steps were inconsistent or unclear, or if we&amp;rsquo;d
just gotten lucky to see an error message while attached to the debugger,
I could use information from the debugger to figure out what the program
had been doing before the error &amp;ndash; and use this, not to fix the bug
immediately, but to figure out how to reproduce it myself.&lt;/p&gt;
&lt;p&gt;So what did I learn from this experience? Well, even though the most
important tool in programming (and bug-squashing) is the human brain,
I learned that people, especially non-programmers, are more comfortable
when they see you using other, concrete, fancy-looking tools. And if
your human brain needs input to complete a task, people might be more
likely to give it to you if you pretend the computer needs that input.&lt;/p&gt;
&lt;p&gt;For those of us who work primarily with our brains, this can be
frustrating and disappointing, and can lead to the need to fib a little
sometimes to accommodate these biases.&lt;/p&gt;
&lt;p&gt;And additionally, I learned about the depths of the disconnect between
different levels of expertise. I thought it was obvious that to fix a
problem with some code, you had to understand it at least well enough
to make it happen again. This seemed to follow directly from first
principles, to be the only logical way that it could work, if you thought
about it. But my boss hadn&amp;rsquo;t thought about it, and didn&amp;rsquo;t understand
this. The gap in our perspective didn&amp;rsquo;t come from his lack of detailed
technical knowledge or specific technologies, but rather from his lack
of a developed intuition for how programming works.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>A Rust Gem: The Rust Map API</title>
      <link href="https://www.thecodedmessage.com/posts/rust-map-entry/" />
      <id>https://www.thecodedmessage.com/posts/rust-map-entry/</id>
      <updated>2022-03-12T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;For my next entry in my &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;series&lt;/a&gt; comparing Rust
to C++, I will be discussing a specific data structure API: the Rust
map API. Maps are often one of the more awkward parts of a collections
library, and the Rust map API is top-notch, especially its
&lt;a href=&#34;https://doc.rust-lang.org/book/ch08-03-hash-maps.html?highlight=entry#only-inserting-a-value-if-the-key-has-no-value&#34;&gt;entry API&lt;/a&gt; &amp;ndash; I literally squealed
when I first learned about entries.&lt;/p&gt;
&lt;p&gt;And as we shall discuss, this isn&amp;rsquo;t just because Rust made better choices
than other standard libraries when designing the maps API. Even more so,
it&amp;rsquo;s because the Rust programming language provides features that better
expresses the concepts involved in querying and mutating maps. Therefore,
this serves as a window into some deep differences between C++ and Rust
that show why Rust is better.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;For my next entry in my &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;series&lt;/a&gt; comparing Rust
to C++, I will be discussing a specific data structure API: the Rust
map API. Maps are often one of the more awkward parts of a collections
library, and the Rust map API is top-notch, especially its
&lt;a href=&#34;https://doc.rust-lang.org/book/ch08-03-hash-maps.html?highlight=entry#only-inserting-a-value-if-the-key-has-no-value&#34;&gt;entry API&lt;/a&gt; &amp;ndash; I literally squealed
when I first learned about entries.&lt;/p&gt;
&lt;p&gt;And as we shall discuss, this isn&amp;rsquo;t just because Rust made better choices
than other standard libraries when designing the maps API. Even more so,
it&amp;rsquo;s because the Rust programming language provides features that better
expresses the concepts involved in querying and mutating maps. Therefore,
this serves as a window into some deep differences between C++ and Rust
that show why Rust is better.&lt;/p&gt;
&lt;p&gt;And for this post, specifically, we&amp;rsquo;ll also be discussing Java, so
this will be a three-way comparison, between Java, C++ and Rust.&lt;/p&gt;
&lt;h2 id=&#34;reading-from-a-map&#34;&gt;Reading from a Map&lt;/h2&gt;
&lt;p&gt;So, let&amp;rsquo;s talk about map APIs. But before we get to &lt;code&gt;Entry&lt;/code&gt; and friends,
let&amp;rsquo;s discuss something a little simpler: getting an item from a
map. Let&amp;rsquo;s say we have a sorted map of strings to integers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In Java, &lt;code&gt;TreeMap&amp;lt;String, Integer&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In C++, &lt;code&gt;std::map&amp;lt;std::string, int&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;In Rust, &lt;code&gt;BTreeMap&amp;lt;&amp;amp;str, i32&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s also say we have a string &lt;code&gt;&amp;quot;foo&amp;quot;&lt;/code&gt;, and want to know what integer
corresponds to it. Now, if we&amp;rsquo;re always sure that the string we&amp;rsquo;re
looking up is always in the map, then we know what we want: we want
to get an integer.&lt;/p&gt;
&lt;p&gt;But what if we&amp;rsquo;re not sure? There are plenty of situations where we want
to read a value corresponding to the key &amp;ndash; or do something else when
that key is not present. Maybe the value is a count, and an absent key
means 0. Or maybe the absent key means that the user has made a typo,
and needs to be informed. Or maybe the map is a cache, and the absent
key means we need to read a file or query a database. In all of these
cases, we need to know either the value, or the fact that the key
is absent.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see how this is handled in our three programming languages, and
how fundamental design choices in these programming languages lead to
such APIs.&lt;/p&gt;
&lt;h3 id=&#34;java-get-a-nullable-reference&#34;&gt;Java &lt;code&gt;get&lt;/code&gt; a (Nullable) Reference&lt;/h3&gt;
&lt;p&gt;A long time ago, Java made an extreme choice in the name of simplicity:
It divided all values into a dichotomy of &amp;ldquo;primitives&amp;rdquo; and &amp;ldquo;objects.&amp;rdquo;
Primitives are passed around by implicit copy, whereas objects are
aliased through many mutable references. Objects always have optionality
built in &amp;ndash; any object reference is automatically &amp;ldquo;nullable,&amp;rdquo; which
means you can store the special sentinal/invalid value &lt;code&gt;null&lt;/code&gt; in it,
the interpretation of which varies wildly. Primitives are not optional
in this way.&lt;/p&gt;
&lt;p&gt;Also for the sake of simplicity, and very relevantly to the topic at hand,
generics are only supported for object types, not primitives. That means
that map values can only ever be object types. And that means that our
map from strings to integers in Java doesn&amp;rsquo;t use Java&amp;rsquo;s primitive integer
type &lt;code&gt;int&lt;/code&gt;, but rather this special wrapper/adapter type &lt;code&gt;Integer&lt;/code&gt;,
which auto-casts to and from &lt;code&gt;int&lt;/code&gt;, and which, like any object type,
is managed through mutable, &lt;em&gt;nullable&lt;/em&gt; references. (At this point, I
for one am beginning to suspect they missed the mark on their simplicity).&lt;/p&gt;
&lt;p&gt;So what&amp;rsquo;s that mean for our map? How do we find out what value
corresponds to &lt;code&gt;&amp;quot;foo&amp;quot;&lt;/code&gt; in our map, or else that there is none?
Well, the method for this is called &lt;code&gt;get&lt;/code&gt;, and that returns the
value in question if there is one. And when there isn&amp;rsquo;t? Well,
Java here leverages nullability, and returns &lt;code&gt;null&lt;/code&gt; when there
is no value.&lt;/p&gt;
&lt;p&gt;So we can write something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Integer value = map.get(&amp;#34;foo&amp;#34;);
if (value == null) {
    System.out.println(&amp;#34;No value for foo&amp;#34;);
} else {
    int i_value = value;
    System.out.println(&amp;#34;Value for foo was: &amp;#34; + i_value);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So far, so good. But there are problems. And perhaps I&amp;rsquo;m missing some
&amp;ndash; now is a good time to take a second, look at the code, and try to
imagine in your mind what problems there may be with this system (you
know, besides the fact that I have to use &lt;code&gt;i_&lt;/code&gt; as improvized Hungarian
notation due to lack of support in Java for shadowing).&lt;/p&gt;
&lt;p&gt;You have some? I&amp;rsquo;ll now list what I&amp;rsquo;ve got.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Problem the first:&lt;/em&gt; The signature of &lt;code&gt;get&lt;/code&gt; doesn&amp;rsquo;t really alert
us to the possibility of a value not being in a map. This is
the sort of &amp;ldquo;edge case&amp;rdquo; that programmers regularly forget to handle;
a programmer may know, due to their situation-specific knowledge,
that the key ought to be present, and forget to consider that the
key might not be.&lt;/p&gt;
&lt;p&gt;Compilers of strongly typed languages generally work to ensure that
programmers don&amp;rsquo;t miss edge cases like this, don&amp;rsquo;t make simple &amp;ldquo;thinkos&amp;rdquo;
(typos but with thought)
or &amp;ldquo;stupid mistakes.&amp;rdquo; How&amp;rsquo;s Java hold up? Well, remember how we mentioned
that primitives can&amp;rsquo;t be &lt;code&gt;null&lt;/code&gt;, but these wrapper types like &lt;code&gt;Integer&lt;/code&gt;
are coercible to primitives? Well, this compiles without a word of
complaint from the compiler:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;TreeMap&amp;lt;String, Integer&amp;gt; map = new TreeMap&amp;lt;String, Integer&amp;gt;();

map.put(&amp;#34;foo&amp;#34;, 3);

int foo = map.get(&amp;#34;foo&amp;#34;);
System.out.println(&amp;#34;int foo: &amp;#34; + foo);

int bar = map.get(&amp;#34;bar&amp;#34;);
System.out.println(&amp;#34;int bar: &amp;#34; + bar);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And what happens at run-time? Similar behavior to Rust&amp;rsquo;s infamous
&lt;code&gt;unwrap&lt;/code&gt; function. The conversion from the nullable &lt;code&gt;Integer&lt;/code&gt;
and the non-nullable &lt;code&gt;int&lt;/code&gt; crashes when the &lt;code&gt;Integer&lt;/code&gt; is in
fact &lt;code&gt;null&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int foo: 3
Exception in thread &amp;#34;main&amp;#34; java.lang.NullPointerException: Cannot invoke &amp;#34;java.lang.Integer.intValue()&amp;#34; because the return value of &amp;#34;java.util.TreeMap.get(Object)&amp;#34; is null
        at test.main(test.java:12)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So you might try to fix this by querying if the key exists first:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;TreeMap&amp;lt;String, Integer&amp;gt; map = new TreeMap&amp;lt;String, Integer&amp;gt;();

if (map.containsKey(&amp;#34;bar&amp;#34;)) {
    int bar = map.get(&amp;#34;bar&amp;#34;);
    System.out.println(&amp;#34;int bar: &amp;#34; + bar);
} else {
    System.out.println(&amp;#34;bar not present&amp;#34;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But now we&amp;rsquo;ve reached &lt;em&gt;problem the second&lt;/em&gt;. Unfortunately, even though
this looks like it addresses the issue, this won&amp;rsquo;t prevent the crash
either. There is nothing stopping you from putting a &lt;code&gt;null&lt;/code&gt; into the map,
so this code also crashes given the right context:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;        TreeMap&amp;lt;String, Integer&amp;gt; map = new TreeMap&amp;lt;String, Integer&amp;gt;();
        map.put(&amp;#34;bar&amp;#34;, null);
        if (map.containsKey(&amp;#34;bar&amp;#34;)) {
            int bar = map.get(&amp;#34;bar&amp;#34;);
            System.out.println(&amp;#34;int bar: &amp;#34; + bar);
        } else {
            System.out.println(&amp;#34;bar not present&amp;#34;);
        }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So for a given key in a Java map, there are actually three possible
situations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The key is absent.&lt;/li&gt;
&lt;li&gt;The key corresponds to an integer.&lt;/li&gt;
&lt;li&gt;The key corresponds to one of these special &lt;code&gt;null&lt;/code&gt;-values.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;get&lt;/code&gt; can distinguish 2 from 1 and 3, but cannot distinguish between
1 and 3. &lt;code&gt;containsKey&lt;/code&gt; can distinguish 1 from 2 and 3, but cannot
distinguish 2 from 3. To distinguish all 3 scenarios, and handle
all the representable values, you need to call &lt;em&gt;both&lt;/em&gt; &lt;code&gt;get&lt;/code&gt;
and &lt;code&gt;containsKey&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if (map.containsKey(&amp;#34;bar&amp;#34;)) {
    Integer bar = map.get(&amp;#34;bar&amp;#34;);
    if (bar == null) {
        System.out.println(&amp;#34;bar present and null&amp;#34;);
    } else {
        int i_bar = map.get(&amp;#34;bar&amp;#34;);
        System.out.println(&amp;#34;int bar: &amp;#34; + i_bar);
    }
} else {
    System.out.println(&amp;#34;bar not present&amp;#34;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In addition to this precaution not being enforced to the compiler,
it leads to &lt;em&gt;problem the third&lt;/em&gt;: We are now querying the map twice.
We are walking the tree twice with our &lt;code&gt;containsKey&lt;/code&gt; followed by
&lt;code&gt;get&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At this point, we find ourselves scrolling through the &lt;code&gt;Map&lt;/code&gt; methods
in &lt;a href=&#34;https://docs.oracle.com/javase/8/docs/api/java/util/Map.html&#34;&gt;Java&amp;rsquo;s documentation&lt;/a&gt;, trying to find a more general solution. &lt;code&gt;getOrDefault&lt;/code&gt; might
help in some situations &amp;ndash; when there&amp;rsquo;s a value that makes sense as the
default. &lt;code&gt;compute&lt;/code&gt; might be useful &amp;ndash; if we&amp;rsquo;re OK with modifying
the map in the process.&lt;/p&gt;
&lt;p&gt;But in general, nothing clean exists to tidy up these problems.  And the
blame lies squarely on Java&amp;rsquo;s decision to make almost all types &amp;ndash;
and all types that can be map values &amp;ndash; nullable.&lt;/p&gt;
&lt;p&gt;But wait! &amp;ndash; you might object &amp;ndash; Can&amp;rsquo;t we just maintain an invariant on the
map that it contains no &lt;code&gt;null&lt;/code&gt; values? If we have a map without &lt;code&gt;null&lt;/code&gt;
values, all these issues &amp;ndash; well, many of these issues &amp;ndash; dry up.&lt;/p&gt;
&lt;p&gt;And this is true. Maintaining such an invariant makes for a much cleaner
situation. Pretend you aren&amp;rsquo;t allowed to put nulls in maps, and arrange
not to do it.&lt;/p&gt;
&lt;p&gt;But, first off, maintaining an invariant like this is easier said than
done. Programmers often do this sort of thing implicitly in their
head, but it&amp;rsquo;s much better to comment. Either way, you have to
trust future programmers &amp;ndash; even future versions of the same programmers
&amp;ndash; to know about the invariant, either by intuiting it (all too common)
or by reading the relevant comment (which, even if there is one, might not
happen). And you have to trust them to not intentionally violate the
invariant, and also to not accidentally violate the invariant: Are
they sure that all those values they add to the map can never be null?&lt;/p&gt;
&lt;p&gt;And second off, somewhat shockingly, sometimes people do assign special
meanings to &lt;code&gt;null&lt;/code&gt;. I said before &lt;code&gt;null&lt;/code&gt; has a wide range of meanings,
and it&amp;rsquo;s not uncommon to use &lt;code&gt;null&lt;/code&gt; to mean special things. Maybe
&amp;ldquo;not mapped&amp;rdquo; means &amp;ldquo;load from cache,&amp;rdquo; but &amp;ldquo;null&amp;rdquo; means &amp;ldquo;there actually
is no value and we know it.&amp;rdquo; Or maybe the opposite convention applies.
&lt;code&gt;null&lt;/code&gt; is frustratingly without intrinsic meaning.&lt;/p&gt;
&lt;p&gt;For such situations, programmers should probably compose the map with &lt;a href=&#34;https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html&#34;&gt;other
types&lt;/a&gt;
or better yet, write custom types that make the semantics of these
situations abundantly clear. But let&amp;rsquo;s not put all the blame on
the programmers. If Java had really wanted to protect people from
distinguishing these &amp;ldquo;not mapped&amp;rdquo; and &amp;ldquo;mapped to null&amp;rdquo; situations, Java
maps shouldn&amp;rsquo;t have made the distinction representable at all.  It&amp;rsquo;s bad
programming language design to put features in a library that can only
be abused, and it&amp;rsquo;s bad understanding of human nature to then solely
blame the programmers for misusing them.&lt;/p&gt;
&lt;h3 id=&#34;c-no-nulls-no-more&#34;&gt;C++: No Nulls No More&lt;/h3&gt;
&lt;p&gt;So now we move on to C++.&lt;/p&gt;
&lt;p&gt;In C++, fewer types are nullable, and non-nullable types like &lt;code&gt;int&lt;/code&gt;
&lt;em&gt;can&lt;/em&gt; be used as the value type of a map.  For our map, of type
&lt;code&gt;std::map&amp;lt;std::string, int&amp;gt;&lt;/code&gt;, we no longer have the trichotomy of
&amp;ldquo;key not present, value null, or value non-null,&amp;rdquo; but the much more
reasonable dichotomy of either the key is present and there is an &lt;code&gt;int&lt;/code&gt;,
or it&amp;rsquo;s absent and there isn&amp;rsquo;t one.&lt;/p&gt;
&lt;p&gt;This is, in my mind, the bare minimum a strongly typed language should
be able to provide, but after the context of Java it&amp;rsquo;s worth pointing out.&lt;/p&gt;
&lt;p&gt;There are three (3) methods in C++ that look like they might be usable
as a &lt;code&gt;get&lt;/code&gt; operation, an operation where we either get an &lt;code&gt;int&lt;/code&gt; value
or learn that the key is absent:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.cppreference.com/w/cpp/container/map/at&#34;&gt;&lt;code&gt;at&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.cppreference.com/w/cpp/container/map/operator%5Fat&#34;&gt;&lt;code&gt;operator[]&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://en.cppreference.com/w/cpp/container/map/find&#34;&gt;&lt;code&gt;find&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See if you can identify which one is the right one to use.&lt;/p&gt;
&lt;p&gt;Spoiler alert! It&amp;rsquo;s &lt;code&gt;find&lt;/code&gt;, the one whose name superficially looks least like
it&amp;rsquo;ll be the right one. &lt;code&gt;at&lt;/code&gt; throws an exception if the key is absent,
and &lt;code&gt;operator[]&lt;/code&gt;, the one with the most appealing name, is an eldritch
abhomination which we&amp;rsquo;ll discuss and condemn later.&lt;/p&gt;
&lt;p&gt;But all well-deserved teasing aside, &lt;code&gt;find&lt;/code&gt; is much better than
Java&amp;rsquo;s &lt;code&gt;get&lt;/code&gt;. It returns a special object &amp;ndash; an iterator &amp;ndash; that
can be easily tested to see whether we&amp;rsquo;ve found an &lt;code&gt;int&lt;/code&gt;, and easily
probed to extract the &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;auto it = map.find(key);
if (it == map.end()) {
    std::cout &amp;lt;&amp;lt; key &amp;lt;&amp;lt; &amp;#34; not present&amp;#34; &amp;lt;&amp;lt; std::endl;
} else {
    std::cout &amp;lt;&amp;lt; key &amp;lt;&amp;lt; &amp;#34; &amp;#34; &amp;lt;&amp;lt; it-&amp;gt;second &amp;lt;&amp;lt; std::endl;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is actually pretty good! The &lt;code&gt;-&amp;gt;&lt;/code&gt; operator also serves as a signal
to experienced C++ programmers that we&amp;rsquo;re assuming that &lt;code&gt;it&lt;/code&gt; is valid:
generally &lt;code&gt;-&amp;gt;&lt;/code&gt; or &lt;code&gt;*&lt;/code&gt; means that the object being operated on is
&amp;ldquo;nullable&amp;rdquo; in some way.&lt;/p&gt;
&lt;p&gt;So when a C++ programmer reads something like this, they have a little
bit of warning that they&amp;rsquo;re doing something that might crash:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int foo = map.find(key)-&amp;gt;second;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And certainly, they have more warning than the Java programmer with
the equivalent Java:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int foo = map.get(foo);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Of course, this is awkward. &lt;code&gt;find&lt;/code&gt; returns an &lt;em&gt;iterator&lt;/em&gt;, which isn&amp;rsquo;t
exactly the type we&amp;rsquo;d expect for this &amp;ldquo;optional value&amp;rdquo; situation. And
to determine if the value isn&amp;rsquo;t present, we compare it to &lt;code&gt;map.end()&lt;/code&gt;,
which is a weird value to compare it to. Nothing about what these things
are named is specifically intuitive, and people would be forgiven for
using the accursed &lt;code&gt;operator[]&lt;/code&gt;. &lt;code&gt;map[&amp;quot;foo&amp;quot;]&lt;/code&gt; just &lt;em&gt;looks&lt;/em&gt; like an
expression for doing boring map indexing, doesn&amp;rsquo;t it?&lt;/p&gt;
&lt;p&gt;And what does &lt;code&gt;operator[]&lt;/code&gt; do, if the key isn&amp;rsquo;t present? It inserts the
key, with a default-constructed value. No configuration is possible of
what value gets inserted, short of defining a new type for the object
values. This is sometimes what you want &amp;ndash; like if your value type has a
good default (especially if you defined it yourself), or if you&amp;rsquo;re about
to overwrite the value anyway. But in most cases, you want some other
behavior if the value is not present &amp;ndash; &lt;code&gt;operator[]&lt;/code&gt; doesn&amp;rsquo;t really tell
you that it inserted the item, so if you need to make a network query
or read a file or print an error, you&amp;rsquo;re out of luck.  &lt;code&gt;operator[]&lt;/code&gt;,
as innocuous as it looks, has surprising behavior, and that is not good.&lt;/p&gt;
&lt;p&gt;But all in all, as far as getting values goes, as far as querying the map
goes, C++ is doing OK. Solid B result on this exam, I think. Decent work,
C++. Especially since we just looked at Java.&lt;/p&gt;
&lt;h3 id=&#34;the-rust-option&#34;&gt;The Rust &lt;code&gt;Option&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;So now on to Rust: we want to query our &lt;code&gt;BTreeMap&amp;lt;&amp;amp;str, i32&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;(Or&amp;hellip; it might be a &lt;code&gt;BTreeMap&amp;lt;String, i32&amp;gt;&lt;/code&gt;, depending on whether we
want to own the strings. This is a decision we also have to make in C++
(where we could have used &lt;code&gt;string_view&lt;/code&gt;s as the keys), but do not have
to make in Java.  At least in Rust, we know that whichever decision we
make, we will not accidentally introduce undefined behavior. But that&amp;rsquo;s
a distraction!)&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s apply the same test to Rust as we&amp;rsquo;ve applied before.
Here, the &lt;a href=&#34;https://doc.rust-lang.org/std/collections/struct.BTreeMap.html#method.get&#34;&gt;method in
question&lt;/a&gt; is given an obvious name, &lt;code&gt;get&lt;/code&gt; rather than &lt;code&gt;find&lt;/code&gt;. So let&amp;rsquo;s
see how it does in our test, of allowing us to read a value if present,
but know if not:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if let Some(val) = map.get(key) {
    println!(&amp;#34;{key}: {val}&amp;#34;);
} else {
    println!(&amp;#34;{key} not present&amp;#34;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;See, &lt;code&gt;get&lt;/code&gt; returns an &lt;code&gt;Option&lt;/code&gt; type. Therefore, unlike in C++, we can test
for the presence of the value and extract the value inside the same &lt;code&gt;if&lt;/code&gt;
statement. Unlike in C++, the return value of &lt;code&gt;get&lt;/code&gt; isn&amp;rsquo;t a map-specific
type, but rather the completely normal way to express a maybe-present
value in Rust. This means that if we want to implement defaulting, we
get that for free by using the &lt;code&gt;Option&lt;/code&gt; type in Rust, which implements
that already:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// Let&amp;#39;s say missing keys means the count is 0:
let value = *map.get(&amp;#34;foo&amp;#34;).unwrap_or(&amp;amp;0);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Similarly, calling &lt;code&gt;is_none()&lt;/code&gt; or pattern-matching against &lt;code&gt;None&lt;/code&gt; is
much more ergonomic than comparing an iterator to &lt;code&gt;map.end()&lt;/code&gt;. It requires
some more intimate knowledge &amp;ndash; or some follow-up reading &amp;ndash; to learn that
the concept of &amp;ldquo;end of collection&amp;rdquo; and &amp;ldquo;not found&amp;rdquo; are for various reasons
combined into one in C++.&lt;/p&gt;
&lt;p&gt;So while C++ avoids the problematic elements of Java maps, Rust does so
more ergonomically, because it has a well-established &lt;code&gt;Option&lt;/code&gt; type. C++
now has one as well, &lt;code&gt;std::optional&lt;/code&gt;, but it hasn&amp;rsquo;t yet reached its
&lt;code&gt;map&lt;/code&gt; API, because it was only added very recently, in C++17.&lt;/p&gt;
&lt;p&gt;And &lt;code&gt;Option&lt;/code&gt; integrates even better than &lt;code&gt;std::optional&lt;/code&gt; with the programming
language, because &lt;code&gt;Option&lt;/code&gt; is just a garden-variety sum type, a
Rust &lt;code&gt;enum&lt;/code&gt;, which lets you do things like &lt;code&gt;if let Some(x) = ...&lt;/code&gt;,
and combine testing and unpacking in the same statement. C++ could
not design a map API this ergonomic, because they lack this fundamental
feature.&lt;/p&gt;
&lt;p&gt;Also, unlike with &lt;code&gt;null&lt;/code&gt; in Java, if you want to use &lt;code&gt;Option&lt;/code&gt;
as a meaningful distinction in your map, you still can. The &lt;code&gt;get&lt;/code&gt;
function would then return &lt;code&gt;Option&amp;lt;Option&amp;lt;...&amp;gt;&amp;gt;&lt;/code&gt; instead of
just &lt;code&gt;Option&lt;/code&gt; &amp;ndash; the outer one representing presence, the inner one
representing whether the value was &lt;code&gt;None&lt;/code&gt; or &lt;code&gt;Some(...)&lt;/code&gt;. &lt;code&gt;Option&lt;/code&gt;
is composable in a way that &lt;code&gt;null&lt;/code&gt; is not.&lt;/p&gt;
&lt;p&gt;For the record, the Rust equivalent to &lt;code&gt;operator[]&lt;/code&gt; &amp;ndash; the &lt;code&gt;Index&lt;/code&gt;
trait implementation on maps &amp;ndash; does the equivalent to C++ &lt;code&gt;at&lt;/code&gt;, and
panics if the key isn&amp;rsquo;t present. While not as generally useful as &lt;code&gt;get&lt;/code&gt;,
I think this is a reasonable interpretation of what &lt;code&gt;map[&amp;quot;foo&amp;quot;]&lt;/code&gt; should
mean.&lt;/p&gt;
&lt;h2 id=&#34;mutation-station&#34;&gt;Mutation Station&lt;/h2&gt;
&lt;p&gt;So Rust wins, I&amp;rsquo;d say pretty handily, when comparing how to access a
value from a map, how to query them. But where Rust truly shines is when
&lt;em&gt;mutating&lt;/em&gt; a map. For mutation, I&amp;rsquo;m going to approach the discussion
differently. I&amp;rsquo;m going to start by specifying what use cases might exist,
and then, in that context, we can discuss how an API might be built.&lt;/p&gt;
&lt;p&gt;The mutation situation has a similar dilemma to querying: the key in
question might or might not already be in the map. And, for example,
we often want to change the value if the key is present, and insert a
fresh value if the key is absent.&lt;/p&gt;
&lt;p&gt;Of course, we could always check if the key is present first, and
then do something different in these two scenarios. But that has
the same problem we already discussed for querying: We then have
to iterate the tree twice, or hash the key twice, or in general
traverse the container twice:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;auto it = map.find(key); // first traversal
if (it != map.end()) {
    return it-&amp;gt;second;
} else {
    int res = load_from_file(key);
    map.insert(std::pair{key, res}); // second traversal
    return res;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So what should we do for our API for this scenario, where we want to
change the value if the key is present, and insert a fresh value if
the key is absent?&lt;/p&gt;
&lt;p&gt;Well, sometimes that fresh value is a default value,
like if we&amp;rsquo;re counting and the key is the thing we&amp;rsquo;re counting &amp;ndash; in that
case, we can always insert 0. In that case, C++&amp;rsquo;s &lt;code&gt;operator[]&lt;/code&gt; &amp;ndash; when
combined with an appropriate default constructor &amp;ndash; can actually
work well.&lt;/p&gt;
&lt;p&gt;And sometimes, that fresh value depends on the key, like if the value is a
more complicated record of many data points about the item in question.
If the value is a sophisticated OOP-style &amp;ldquo;object,&amp;rdquo; and the key indexes
one of the fields also contained in the value, C++&amp;rsquo;s &lt;code&gt;operator[]&lt;/code&gt; would
not work. The default value is a function of the key.&lt;/p&gt;
&lt;p&gt;And sometimes, there isn&amp;rsquo;t a default value &lt;em&gt;per se&lt;/em&gt;. Sometimes, if the key
is absent, we need to do additional work to find out what value should
be inserted. This is the case if the map is a cache of some database,
accessed via IPC or file or even Internet. In that situation, we only
want to send a query if the key is not present. We would not be able
to accomplish our goals simply provide a default value when sending the
mutation operation.&lt;/p&gt;
&lt;p&gt;C++ doesn&amp;rsquo;t have anything for us here. &lt;code&gt;operator[]&lt;/code&gt;
is pretty much its most sophisticated &amp;ldquo;query-and-mutate&amp;rdquo;
operation. Java, somewhat surprisingly, does have something relevant,
&lt;a href=&#34;https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#compute-K-java.util.function.BiFunction-&#34;&gt;&lt;code&gt;compute&lt;/code&gt;&lt;/a&gt;.
This handles all of these situations, with a relatively unergonomic
callback function &amp;ndash; and as long as your map never contains &lt;code&gt;null&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;Rust&amp;rsquo;s solution, however, is to create a value that encapsulates
being at a key in the map that &lt;em&gt;might or might not&lt;/em&gt; have a value
associated with it, a value of the
&lt;a href=&#34;https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html&#34;&gt;&lt;code&gt;Entry&lt;/code&gt;&lt;/a&gt; type.&lt;/p&gt;
&lt;p&gt;As long as you have that value, the borrow checker prevents you from
modifying the map and potentially invalidating it. And as long
as you have it, you can query which situation you&amp;rsquo;re in &amp;ndash; the
missing key or the present key. You can update a present key. You can
compute a default for the missing key, either by providing the value or
providing a function to generate it. There are many options, and you can
read all of them in the &lt;code&gt;Entry&lt;/code&gt; documentation; the world is your oyster.&lt;/p&gt;
&lt;p&gt;So the C++ code above can be ergonomically expressed as something like
this in Rust:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;let entry = map.entry(key.to_string());
*entry.or_insert_with(|| load_from_file(key))
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And the idiom where we&amp;rsquo;re counting something could be expressed
something like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;map.entry(string)
    .and_modify(|v| *v += 1)
    .or_insert(1);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So we get this nice little program that counts how many times
we use different command line arguments:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;use std::collections::BTreeMap;
use std::env;

fn count_strings(strings: Vec&amp;lt;String&amp;gt;) -&amp;gt; BTreeMap&amp;lt;String, u32&amp;gt; {
    let mut map = BTreeMap::new();
    for string in strings {
        map.entry(string)
            .and_modify(|v| *v += 1)
            .or_insert(1);
    }
    map
}

fn main() {
    for (string, count) in count_strings(env::args().collect()) {
        println!(&amp;#34;{string} shows up {count} times&amp;#34;);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;So first off, &lt;code&gt;Entry&lt;/code&gt;s are super nice, and neither Java nor C++ has
anything anywhere near as nice. Even when it comes to just querying,
Rust&amp;rsquo;s &lt;code&gt;get&lt;/code&gt; is much better than Java&amp;rsquo;s &lt;code&gt;get&lt;/code&gt;, and a little more ergonomic
than C++&amp;rsquo;s &lt;code&gt;find&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But this isn&amp;rsquo;t an accident. This isn&amp;rsquo;t just about Rust&amp;rsquo;s map API having
a nice touch. When we look at the definition of &lt;a href=&#34;https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html&#34;&gt;&lt;code&gt;Entry&lt;/code&gt;&lt;/a&gt;,
we see things that Java and C++ can&amp;rsquo;t do:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;pub enum Entry&amp;lt;&amp;#39;a, K, V&amp;gt; 
where
    K: &amp;#39;a,
    V: &amp;#39;a, 
 {
    Vacant(VacantEntry&amp;lt;&amp;#39;a, K, V&amp;gt;),
    Occupied(OccupiedEntry&amp;lt;&amp;#39;a, K, V&amp;gt;),
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;First, this is an &lt;code&gt;enum&lt;/code&gt;: There&amp;rsquo;s two options, and in both option,
there&amp;rsquo;s additional information. Of course, Java and C++ can express
a dichotomy between two options, but it&amp;rsquo;s a lot clumsier. Either you&amp;rsquo;d
have to use a class hierarchy, or &lt;code&gt;std::variant&lt;/code&gt;, or something else. In
Rust, this is as easy as pie, and since it does it the easy way, you can
not only use the various combinator methods in Rust, you can also use
&lt;code&gt;Entry&lt;/code&gt;s with a good old-fashioned &lt;code&gt;match&lt;/code&gt; or &lt;code&gt;if let&lt;/code&gt; to distinguish
between the &lt;code&gt;Vacant&lt;/code&gt; and &lt;code&gt;Occupied&lt;/code&gt; situation.&lt;/p&gt;
&lt;p&gt;Second, there&amp;rsquo;s a little lifetime annotation there: &lt;code&gt;&#39;a&lt;/code&gt;. This is
an indication that while you have an &lt;code&gt;Entry&lt;/code&gt; into a map, Rust won&amp;rsquo;t
let you change it. Now, in Java and C++, there&amp;rsquo;s also iterators,
which you may not change a map while you&amp;rsquo;re holding, but in both
those languages, you have to enforce that constraint yourself.
In Rust, the compiler can enforce it for you, making &lt;code&gt;Entry&lt;/code&gt;s
impossible to use wrong in this way.&lt;/p&gt;
&lt;p&gt;Without both of these features, &lt;code&gt;Entry&lt;/code&gt; would not have been an obvious API
to create. It would&amp;rsquo;ve been barely possible. But Rust&amp;rsquo;s feature set encourages
things like &lt;code&gt;Entry&lt;/code&gt;, which is yet another reason to prefer Rust over C++
(and Java): Rust has &lt;code&gt;enum&lt;/code&gt;s (and lifetimes) and uses them to good effect.&lt;/p&gt;
&lt;h2 id=&#34;addendum&#34;&gt;Addendum&lt;/h2&gt;
&lt;p&gt;I wanted to address a few points that people have raised in comments
since I posted this.&lt;/p&gt;
&lt;p&gt;Some people have pointed out that C++ has &lt;code&gt;insert_or_assign&lt;/code&gt;,
but in spite of the promising name, it just unconditionally sets a key
to be associated with a value, whether or not it previously
was. This is not the same as behaving differently based on
whether a value previously existed, and it is therefore not
relevant to our discussion.&lt;/p&gt;
&lt;p&gt;More interestingly, it has been pointed out to me that with
the return value of &lt;code&gt;insert&lt;/code&gt;, you can tell whether the &lt;code&gt;insert&lt;/code&gt;
actually &lt;code&gt;insert&lt;/code&gt;ed anything, and also get an iterator to the entry
that existed before if it didn&amp;rsquo;t. This allows implementing some, but not
all, of the patterns of &lt;code&gt;Entry&lt;/code&gt; without traversing the map twice.&lt;/p&gt;
&lt;p&gt;For example, counting:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;int main(int argc, char **argv) {
    std::vector&amp;lt;std::string&amp;gt; args{argv, argv + argc};
    std::map&amp;lt;std::string, int&amp;gt; counts;

    for (const auto &amp;amp;arg : args) {
        counts.insert(std::pair{arg, 0}).first-&amp;gt;second += 1;
    }

    for (const auto &amp;amp;pair : counts) {
        std::cout &amp;lt;&amp;lt; pair.first &amp;lt;&amp;lt; &amp;#34;: &amp;#34; &amp;lt;&amp;lt; pair.second &amp;lt;&amp;lt; std::endl;
    }

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This works, but is much less clear and ergonomic than the &lt;code&gt;Entry&lt;/code&gt;-based
API. But perhaps more importantly, this functionality is much more
constrained than &lt;code&gt;Entry&lt;/code&gt;, and is equivalent to using &lt;code&gt;Entry&lt;/code&gt; with just
&lt;code&gt;or_insert&lt;/code&gt;, and never using any of the other methods. As another
commentator pointed out, counting is possible with just &lt;code&gt;or_insert&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;*map.entry(key).or_insert(0) += 1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But counting is just one example. C++&amp;rsquo;s &lt;code&gt;insert&lt;/code&gt; is still deeply
limited. Using C++&amp;rsquo;s &lt;code&gt;insert&lt;/code&gt; means you have to know &lt;em&gt;a priori&lt;/em&gt; what
value you would be inserting.  You can&amp;rsquo;t use it to notice that a key is
missing and then go off and do other work to figure out what the value
should be. So you can&amp;rsquo;t do my &lt;code&gt;load_from_file&lt;/code&gt; example.&lt;/p&gt;
&lt;p&gt;In order to do the &lt;code&gt;load_from_file&lt;/code&gt; example in C++, even with this use of
&lt;code&gt;insert&lt;/code&gt;, you would have to temporarily insert some sentinal value in the
map &amp;ndash; and that goes against how strongly typed languages ought to work,
in addition to breaking the C++ concept of exception safety.&lt;/p&gt;
&lt;p&gt;This is, as was pointed out in another comment, exactly what C++
programmers sometimes have to do, to meet performance goals, at the
expense of clarity and simplicity, and therefore, especially in C++,
at the expense of confidence in safety and correctness.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>The Good Ol&#39; Days of QBasic Nibbles</title>
      <link href="https://www.thecodedmessage.com/posts/qbasic-nostalgia/" />
      <id>https://www.thecodedmessage.com/posts/qbasic-nostalgia/</id>
      <updated>2022-02-28T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/nibbles1.png&#34; alt=&#34;QBasic Nibbles Splash Screen&#34;&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s talk about an ancient programming language! I think we
can all learn things from history, and it gives us grounding
to realize that our time is just one time among many, to see
what people in the past did differently, what they got wrong
that we would never do now, and also to see what they got right.&lt;/p&gt;
&lt;p&gt;Do you remember MS-DOS? Do you remember that it came with
an interpreted programming language? From MS-DOS 5 onwards,
it came with not Python, not Javascript or R or Matlab,
but a &lt;a href=&#34;https://en.wikipedia.org/wiki/QBasic&#34;&gt;dialect&lt;/a&gt;
of &lt;a href=&#34;https://en.wikipedia.org/wiki/BASIC&#34;&gt;BASIC&lt;/a&gt;. But
I think most people, especially most people my age who
were children at the height of the MS-DOS era, remember
it for the games, the two sample programs that came with it, namely
&lt;a href=&#34;https://www.howtogeek.com/779956/gorilla.bas-how-to-play-the-secret-ms-dos-game-from-your-childhood/&#34;&gt;Gorillas&lt;/a&gt;
and Nibbles (their name for Snake).&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/nibbles1.png&#34; alt=&#34;QBasic Nibbles Splash Screen&#34;&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s talk about an ancient programming language! I think we
can all learn things from history, and it gives us grounding
to realize that our time is just one time among many, to see
what people in the past did differently, what they got wrong
that we would never do now, and also to see what they got right.&lt;/p&gt;
&lt;p&gt;Do you remember MS-DOS? Do you remember that it came with
an interpreted programming language? From MS-DOS 5 onwards,
it came with not Python, not Javascript or R or Matlab,
but a &lt;a href=&#34;https://en.wikipedia.org/wiki/QBasic&#34;&gt;dialect&lt;/a&gt;
of &lt;a href=&#34;https://en.wikipedia.org/wiki/BASIC&#34;&gt;BASIC&lt;/a&gt;. But
I think most people, especially most people my age who
were children at the height of the MS-DOS era, remember
it for the games, the two sample programs that came with it, namely
&lt;a href=&#34;https://www.howtogeek.com/779956/gorilla.bas-how-to-play-the-secret-ms-dos-game-from-your-childhood/&#34;&gt;Gorillas&lt;/a&gt;
and Nibbles (their name for Snake).&lt;/p&gt;
&lt;p&gt;Nibbles is extra near and dear to my heart because not only is it the
game that I better enjoyed, but more interestingly because it&amp;rsquo;s the
first &amp;ldquo;large program&amp;rdquo; that I ever did work on
(for me as a child, &amp;ldquo;large&amp;rdquo; meant multiple subroutines), and the first
existing program I ever modified.&lt;/p&gt;
&lt;p&gt;So recently, I tried to see if I could find it. And indeed, I could.
I just needed DosBox, the &lt;a href=&#34;https://www.qbasic.net/en/top-ten-downloads/&#34;&gt;QBasic
interpreter&lt;/a&gt; (you want
QBasic EN 1.1), to run it. After that, you just need the &lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS&#34;&gt;program
itself&lt;/a&gt;, after which, you can throw them in a directory, &amp;ldquo;mount&amp;rdquo; it from
inside DosBox, and run &lt;code&gt;QBASIC.EXE&lt;/code&gt; and use its very discoverable
interface (by 90&amp;rsquo;s standards).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/nibbles4.png&#34; alt=&#34;QBasic Nibbles in Action&#34;&gt;&lt;/p&gt;
&lt;p&gt;It looks a little less impressive in such a small little emulation
window, but of course at the time it took the entire screen of an
entire CRT monitor, and was the best technology available for me
to interact with.&lt;/p&gt;
&lt;p&gt;Nibbles was a sample game designed for you to learn to program as well
as having fun with. True to its time, it had a little set-up interface
where you answered questions in a very basic prompt-and-respond TUI
before you could
start playing:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/nibbles2.png&#34; alt=&#34;Prompt and Response TUI&#34;&gt;&lt;/p&gt;
&lt;p&gt;You ate numbers going from 1-9, which were easy to
display &amp;ndash; the program, though a video game, runs in text mode! &amp;ndash;
but at the time I just appreciated that it helped you keep
track of how far along in the level you were.
So I decided to take a look at the
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS&#34;&gt;code&lt;/a&gt; and discuss it a little bit.&lt;/p&gt;
&lt;p&gt;The first thing that struck me was how short it was &amp;ndash; at 721
lines, this is a rather short source file, a &amp;ldquo;simple&amp;rdquo; module or
class, let alone a whole program! I suppose things do
&lt;a href=&#34;https://xkcd.com/255/&#34;&gt;seem bigger&lt;/a&gt; when you&amp;rsquo;re a kid.&lt;/p&gt;
&lt;p&gt;But also, I didn&amp;rsquo;t view it as one block of size-12 text on a
high-resolution monitor. I read it in QBasic&amp;rsquo;s built-in
code browser where it showed up as 14 different logically separate parts,
at the time an overwhelming number:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/nibbles6.png&#34; alt=&#34;Subroutine/Function Selection&#34;&gt;&lt;/p&gt;
&lt;p&gt;And this is then what the subroutine would look like:
&lt;img src=&#34;https://www.thecodedmessage.com/images/nibbles7.png&#34; alt=&#34;Subroutine Definition&#34;&gt;&lt;/p&gt;
&lt;p&gt;Code browsers are great, and this interface is a solid reminder that
subroutines are a very early form of modules, especially given that
in QBasic, these subroutines could contain their own
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L103-L108&#34;&gt;sub-subroutines&lt;/a&gt;
using the more traditional
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L88&#34;&gt;&lt;code&gt;GOSUB&lt;/code&gt; command&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s talk about this programming language and program that once
people used to get real work (and real play) done.&lt;/p&gt;
&lt;p&gt;First off, we
see some &lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L83-L85&#34;&gt;mutable global variables&lt;/a&gt;, a big no-no by modern standards,
but can you really blame them when their scope is no larger than that
of a small modern class, where the fields would be effectively global
within the context of an instance?&lt;/p&gt;
&lt;p&gt;But also, to my pleasant surprise, there were also some &lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L75-L81&#34;&gt;global
constants&lt;/a&gt;,
and they are marked as such, with
the &lt;code&gt;CONST&lt;/code&gt; keyword.  In fact, as we see in
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L418&#34;&gt;multiple&lt;/a&gt;
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L51-L55&#34;&gt;places&lt;/a&gt;,
QBasic is actually strongly typed, sometimes even using
the
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L117&#34;&gt;sigils&lt;/a&gt;,
for which the BASIC family is &lt;a href=&#34;https://xkcd.com/1306/&#34;&gt;infamous&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &amp;ldquo;B&amp;rdquo; in BASIC stands for &amp;ldquo;beginner,&amp;rdquo; and that is exactly the
target audience QBasic was designed for. So it&amp;rsquo;s really refreshing
that in the past they didn&amp;rsquo;t have this notion that types were
too advanced for novices, or perhaps too tedious, that an
&lt;a href=&#34;https://www.python.org/&#34;&gt;easy-to-learn programming language&lt;/a&gt;
wouldn&amp;rsquo;t have you declare them.&lt;/p&gt;
&lt;p&gt;Or, of course, maybe duck-typing was seen as too difficult or
inefficient to implement. But in that case, why did they have
what I imagine would be an equally difficult compromise measure,
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L20&#34;&gt;alphabetically-based type
defaulting&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To be fair, for a long time I had no idea what &lt;code&gt;DEFINT&lt;/code&gt; even
meant, but &lt;code&gt;DEFINT A-Z&lt;/code&gt; certainly seemed like an appropriately mysterious
and even badass way to start a subroutine, a magical invocation, covering
the ends of the alphabet to start off each page of code.&lt;/p&gt;
&lt;p&gt;Obviously, QBasic is not object oriented. Its fundamental notion of
module isn&amp;rsquo;t a class, but rather a subroutine or function.  These two
notions were distinct: functions returned values (like in math) &amp;ndash;
though they could also have side effects &amp;ndash; and subroutines did not.
(Both had &lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L58-L73&#34;&gt;strongly-typed
arguments&lt;/a&gt;,
however).&lt;/p&gt;
&lt;p&gt;This might seem an odd distinction to make, but it makes sense at
a certain level. Especially syntactically, subroutine calls definitionally
must be the top-level construct of a statement. And lo and behold! &amp;ndash;
they do not require parentheses
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L150&#34;&gt;around their arguments&lt;/a&gt; whereas
functions &lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L456&#34;&gt;do&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s really no reason not to do something like that in Rust, come
to think of it. And come to think of it, Haskell makes a vaguely similar
distinction, where if what others would call a &amp;ldquo;function&amp;rdquo; does IO
and does not take arguments, it&amp;rsquo;s not a function at all, but a
special value known as an &amp;ldquo;action,&amp;rdquo; which can then only be called
in certain contexts.&lt;/p&gt;
&lt;p&gt;So what did I do with this? I added more action keys. I added
keys to speed up and slow down gameplay on command, so that if
you pressed the arrow in the direction the snake was currently
going, instead of doing nothing, it sped up the snake. Pressing
the opposite direction of where you were going would then slow
it down.  And then, I wrote new levels, using the &lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L299-L411&#34;&gt;existing levels
code&lt;/a&gt;
as a baseline.&lt;/p&gt;
&lt;p&gt;And then, after that, I began to attack the
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L414-L568&#34;&gt;main subroutine&lt;/a&gt;&amp;rsquo;s &lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L449-L541&#34;&gt;main loop&lt;/a&gt;. I thought it would be cool
if multiple numbers could be on the screen at the same time,
but this required modifying how the location of the numbers were
stored, replacing the
&lt;a href=&#34;https://github.com/tangentstorm/tangentlabs/blob/master/qbasic/NIBBLES.BAS#L493&#34;&gt;two
variables&lt;/a&gt;
indicating their current location with a two-dimensional array of boolean
values (represented by &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;-1&lt;/code&gt; &amp;ndash; integer/boolean distinctions were
not yet well-established).&lt;/p&gt;
&lt;p&gt;I wish I still had the code. But more importantly, I&amp;rsquo;m grateful that
the Microsoft of the &amp;rsquo;90s, as evil and monopolistic as it was, saw
the need to put a programming language, a little IDE, and some sample
programs and include them with their operating system. Bill Gates was
my hero when I was a small child &amp;ndash; before I knew what anti-trust was &amp;ndash;
and the fact that Microsoft made sure that computers came with plenty
of fun corridors for me to explore was a huge part of why.&lt;/p&gt;
&lt;p&gt;But also, there was no particular reason why the stuff I was doing
couldn&amp;rsquo;t be done by any other elementary schooler, if there were
interest in the schools in teaching it. Variables in programming
are far more concrete in their meaning than variables in algebra &amp;ndash;
for one thing, their values actually vary with time, which made
me think the variables in algebra were a bit of a misnomer.&lt;/p&gt;
&lt;p&gt;And yet, programming isn&amp;rsquo;t even a required course in most American
high schools. And that, I think, is a real shame. I understand that
most schools don&amp;rsquo;t have the resources to do a good job of it, and
that also, honestly, is a real shame.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Warnings and Linter Errors: The Awkward Middle Children</title>
      <link href="https://www.thecodedmessage.com/posts/warnings/" />
      <id>https://www.thecodedmessage.com/posts/warnings/</id>
      <updated>2022-02-25T00:00:00+00:00</updated>
      
      <summary type="html">&lt;h2 id=&#34;what-is-bad-rust&#34;&gt;What is &amp;ldquo;bad&amp;rdquo; Rust?&lt;/h2&gt;
&lt;p&gt;When we say that a snippet of code is &amp;ldquo;bad&amp;rdquo; Rust, it&amp;rsquo;s ambiguous.&lt;/p&gt;
&lt;p&gt;We might on the one hand mean that it is &amp;ldquo;invalid&amp;rdquo; Rust, like the
following function (standing on its own in a module):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn foo(bar: u32) -&amp;gt; u32 {
    bar + baz // but baz is never declared...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this situation, a rule of the programming language has been violated.
The compiler stops compiling and does not output a binary. In fact, it
has to stop compiling, because this is not a Rust program. It might resemble
one, but it in fact does not make any sense, because it is violating
one of the extra-syntactic constraints that text has to have to be a Rust
program.&lt;/p&gt;</summary>
      <content type="html">&lt;h2 id=&#34;what-is-bad-rust&#34;&gt;What is &amp;ldquo;bad&amp;rdquo; Rust?&lt;/h2&gt;
&lt;p&gt;When we say that a snippet of code is &amp;ldquo;bad&amp;rdquo; Rust, it&amp;rsquo;s ambiguous.&lt;/p&gt;
&lt;p&gt;We might on the one hand mean that it is &amp;ldquo;invalid&amp;rdquo; Rust, like the
following function (standing on its own in a module):&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn foo(bar: u32) -&amp;gt; u32 {
    bar + baz // but baz is never declared...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this situation, a rule of the programming language has been violated.
The compiler stops compiling and does not output a binary. In fact, it
has to stop compiling, because this is not a Rust program. It might resemble
one, but it in fact does not make any sense, because it is violating
one of the extra-syntactic constraints that text has to have to be a Rust
program.&lt;/p&gt;
&lt;p&gt;What would it even mean, to access a variable that&amp;rsquo;s not
declared? When you write a variable access, the compiler issues an
access to the corresponding register or location in memory. When
a variable is undeclared, no such location exists. The compiler
couldn&amp;rsquo;t compile this code if it wanted to!&lt;/p&gt;
&lt;p&gt;On the other hand, there&amp;rsquo;s this sort of &amp;ldquo;bad Rust&amp;rdquo; as well:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn foo(bar: bool) -&amp;gt; &amp;amp;&amp;#39;static str {
    match bar == false {
        true =&amp;gt; &amp;#34;false&amp;#34;,
        false =&amp;gt; &amp;#34;true&amp;#34;,
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This code is &amp;ndash; as the kids say &amp;ndash; cringe. Whatever this code is trying
to do, it should not be done this way. But for all its flaws, it&amp;rsquo;s definitely
&amp;ldquo;good&amp;rdquo; Rust in a validity sense: the compiler knows exactly what to do
to output a binary from it, and will do so with no complaints. Whatever
is &amp;ldquo;bad&amp;rdquo; about this code &amp;ndash; and it&amp;rsquo;s a lot &amp;ndash; is bad from a human
perspective only; the computer doesn&amp;rsquo;t even notice. It&amp;rsquo;s bad idiomatic Rust,
not erroneous invalid Rust, and it&amp;rsquo;s bad because humans prefer not to
structure their concepts this way.&lt;/p&gt;
&lt;p&gt;So now we have a nice little dichotomy of problems with a Rust program.
On the one hand, we have errors, where the compiler will not &amp;ndash; cannot,
even &amp;ndash; produce an output. And on the other hand, we have idiomatic
failures.  It&amp;rsquo;s a nice neat tidy distinction that a lot of people make,
but in the context of Rust &amp;ndash; and with most programming languages &amp;ndash;
it&amp;rsquo;s actually problematic, because problems with programs, like gender
or political views, don&amp;rsquo;t actually quite form a tidy binary. And as
with gender and politics, oversimplifying types of &amp;ldquo;bad Rust&amp;rdquo; into a binary,
even conceptually, can lead to practical problems.&lt;/p&gt;
&lt;p&gt;I am, of course, talking about warnings and linter errors &amp;ndash; those
rules that if you violate them, it won&amp;rsquo;t necessarily cause the compiler
to reject the program, but it may, depending on its settings. I&amp;rsquo;m also
talking about things like safety rules, where if you dereference pointers
the compiler will normally reject your program, but it can be told not
to on a block-by-block basis.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of that, for Rust:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn foo() -&amp;gt; u32 {
    return 3;
    println!(&amp;#34;Not reached!&amp;#34;);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The compiler knows that that the &lt;code&gt;println&lt;/code&gt; can&amp;rsquo;t be called,
and it makes a point to tell the user about it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;warning: unreachable statement
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But more on those later. For right now, we&amp;rsquo;ll continue to try and brush
these warnings under the rug.&lt;/p&gt;
&lt;h2 id=&#34;the-binary-error-model&#34;&gt;The Binary Error Model&lt;/h2&gt;
&lt;p&gt;I call the philosophical framework I am criticizing the &amp;ldquo;binary error&amp;rdquo;
model, and before I start picking apart at it and denouncing it, I&amp;rsquo;d like
to spend some time explaining what I mean by it, and why it&amp;rsquo;s appealing.&lt;/p&gt;
&lt;p&gt;So to talk about &amp;ldquo;the binary error model,&amp;rdquo; as I&amp;rsquo;ve termed it, we&amp;rsquo;ll
start by talking about why it exists, what problem it&amp;rsquo;s trying to solve.
It&amp;rsquo;s trying to distinguish between a notion of the programming language
in itself, as a platonic ideal almost, versus the other things that
surround it &amp;ndash; like a reference implementation, or a set of community
norms. What would belong in a formal specification, and what not?
What would have to be the same for another compiler to also be a
Rust compiler?&lt;/p&gt;
&lt;p&gt;In the &amp;ldquo;binary error model,&amp;rdquo; Rust, or any programming language, is a
set of valid programs and their semantics. You could look at it as being
analogous to a Rust function with this signature:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn rust_programming_language(program: SourceTree) -&amp;gt; Option&amp;lt;Semantics&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;SourceTree&lt;/code&gt; in this context is a directory hierarchy of properly
organized Rust code at some level of organization, maybe a crate.
&lt;code&gt;Semantics&lt;/code&gt; is a little harder to define &amp;ndash; it&amp;rsquo;s an abstract notion
of what the program &amp;ldquo;does,&amp;rdquo; a representation of the platonic essence
of what the program should output (meaning, in this context, any observable
behavior) given a set of inputs (meaning, in this context, any information
the program can observe).&lt;/p&gt;
&lt;p&gt;So this definition is to say, the Rust programming language, in general,
can be thought of, philosophically, as a function from source trees to
specifications of concrete behavior. Since this isn&amp;rsquo;t an actual
Rust function, we can handwave those specifications a bit, and
discuss them in English or a formal model of our choice.&lt;/p&gt;
&lt;p&gt;And this is a coherent way to talk about Rust, a philosophical abstraction
with practical applications. For example, if we were comparing two Rust
compilers, trying to find out if they implemented &amp;ldquo;the same programming
languages,&amp;rdquo; we could use this model as our criterion.&lt;/p&gt;
&lt;p&gt;So, to find out whether two Rust implementations both implement the same
programming language, we use this function signature as our guide: Given
the same source tree, do they output programs with the same semantics,
the same concrete interaction with the outside world?&lt;/p&gt;
&lt;p&gt;There are a lot of things that can be different between implementations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do the programs, as compiled by these two different implementations, print out the same values when given the same inputs&lt;/li&gt;
&lt;li&gt;Do the programs write the same data to the disk?&lt;/li&gt;
&lt;li&gt;Do they panic in the same situations?&lt;/li&gt;
&lt;li&gt;Do they have the same FFI characteristics to interact with a C library?&lt;/li&gt;
&lt;li&gt;Do they have the same asymptotic complexity? (For a systems programming
language, we definitely want to include this under &amp;ldquo;semantics&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;Do they have the same memory model for internal inter-thread interactions?&lt;/li&gt;
&lt;li&gt;Do they make the same safety guarantees?&lt;/li&gt;
&lt;li&gt;Do they accept and reject the same set of programs?&lt;/li&gt;
&lt;li&gt;Do they print the same exact error messages?&lt;/li&gt;
&lt;li&gt;Do they issue warnings on the same set of programs?&lt;/li&gt;
&lt;li&gt;Are the two compilers invoked by the same command?&lt;/li&gt;
&lt;li&gt;Is one of the compilers actually an interpreter?&lt;/li&gt;
&lt;li&gt;Do they target the same processor architecture?&lt;/li&gt;
&lt;li&gt;Do they output the exact same binaries?&lt;/li&gt;
&lt;li&gt;Do they run with exactly equal performance?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Obviously, different implementations will differ in some of these ways.
But we do need some way of defining whether two compilers both
implement Rust, rather than one implementing Rust and one implementing Go,
or one implementing Rust and the other one not quite succeeding at
implementing Rust.&lt;/p&gt;
&lt;p&gt;In the model, as we&amp;rsquo;ve defined it, the question comes down
to whether accepted programs have the same semantics (but not form)
and whether the set of accepted programs are the same. This means that,
of the above questions, they stop mattering after &amp;ldquo;do they accept and
reject the same set of programs?&amp;rdquo; That is where the binary error
model draws the line.&lt;/p&gt;
&lt;p&gt;To apply this model, the relevant part of a compiler is that it implements
something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn rust_compiler(program: SourceTree) -&amp;gt; Option&amp;lt;CompiledProgram&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And then, you could compare two compiled programs based on their
semantics.&lt;/p&gt;
&lt;p&gt;This model could also be useful for writing a formal specification
of the Rust programming language (no, &amp;ldquo;the compiler itself&amp;rdquo; doesn&amp;rsquo;t count as
a specification), and for programming languages that have a formal,
written specification, it is couched in terms of something similar
to this model &amp;ndash; but not necessarily exactly.&lt;/p&gt;
&lt;h2 id=&#34;warnings-and-errors&#34;&gt;Warnings and Errors&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s take another look at our abstract &amp;ldquo;function signature&amp;rdquo; for the
Rust programming language:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn rust_programming_language(program: SourceTree) -&amp;gt; Option&amp;lt;Semantics&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We have so far been glossing over a feature of the return type,
&lt;code&gt;Option&lt;/code&gt;. But that is what makes this particular model
the &amp;ldquo;binary error&amp;rdquo; model, and that&amp;rsquo;s what I&amp;rsquo;m going to
be criticizing, so let&amp;rsquo;s discuss it now.&lt;/p&gt;
&lt;p&gt;Some source trees are not Rust programs. Some are, in fact, Go programs,
or directories full of plain text files, or random binary data. Some,
on the other hand, are almost Rust programs, like the example from above:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn foo(bar: u32) -&amp;gt; u32 {
    bar + baz // but baz is never declared...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This model treats all of these programs equally. From the perspective
of this abstract function, these all return the same value, &lt;code&gt;None&lt;/code&gt;.
Which means, from the perspective of this philosophical perspective,
all of these are the same: not a valid Rust program.&lt;/p&gt;
&lt;p&gt;If we&amp;rsquo;re comparing two implementations of Rust, this model therefore
considers these statements to be irrelevancies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do they generate the same error messages?&lt;/li&gt;
&lt;li&gt;Are their error messages equally relevant to the problem?&lt;/li&gt;
&lt;li&gt;Are their error messages equally comprehensible to a beginner programmer?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These things, however, are still relevant:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do they reject the same source trees?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In fact, a single program accepted by one and not by the other would
make these two compilers implementations of different programming languages.&lt;/p&gt;
&lt;p&gt;And what about warnings? This abstract function signature barely has
room for errors, flattening them all to &lt;code&gt;None&lt;/code&gt;. The complexities of
the ways in which a Rust program might be bad are simplified to a binary:
it is or is not a valid Rust program. Warnings are rounded to &amp;ldquo;it is valid.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So in the &amp;ldquo;binary error&amp;rdquo; model, where the &amp;ldquo;return value&amp;rdquo; of the abstract
function for the programming language is just &lt;code&gt;Option&amp;lt;Semantics&amp;gt;&lt;/code&gt;,
this function falls into the &amp;ldquo;valid Rust&amp;rdquo; side of the binary:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn foo() -&amp;gt; i32 {
    let Foo = 3;
    Foo
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is considered to be the case, even though the standard Rust
compiler outputs a warning for it:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;warning: variable `Foo` should have a snake case name
 --&amp;gt; test.rs:2:9
  |
2 |     let Foo = 3;
  |         ^^^ help: convert the identifier to snake case (notice the capitalization): `foo`
  |
  = note: `#[warn(non_snake_case)]` on by default

warning: 1 warning emitted
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So what&amp;rsquo;s going on here?&lt;/p&gt;
&lt;p&gt;Well, in point of fact, our compiler implementation does not implement
&lt;code&gt;Option&amp;lt;CompilerError&amp;gt;&lt;/code&gt; as its conceptual return value.  Its contract
looks more like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn rust_compiler(program: SourceTree) -&amp;gt;
    (Result&amp;lt;CompiledProgram, Vec&amp;lt;ErrorMessage&amp;gt;&amp;gt;, Vec&amp;lt;Warning&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But when we compare the compiler to other compilers in the &amp;ldquo;binary
error&amp;rdquo; model, we pretend instead the compiler was wrapped in this wrapper:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn rust_compiler_for_comparison(program: SourceTree) -&amp;gt; Option&amp;lt;CompiledProgram&amp;gt; {
    let res = rust_compiler(program);
    let (res, _) = res; // strip warnings
    res.ok() // flatten errors, did it compile or not?
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this model, only the parts that are part of our original
&lt;code&gt;rust_language&lt;/code&gt; function truly are part of the Rust programming
language. Only the rules that would cause every hypothetical
compiler to reject the program are part of the programming language.
This warning is &amp;ldquo;just the compiler&amp;rsquo;s opinion, man.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s as if the compiler had two jobs: compiling the Rust programming
language (defined as including a binary distinction between valid and
invalid programs) and separately a linter, which tells you the
compiler-writer&amp;rsquo;s opinions about what might be considered wrong with
the code.&lt;/p&gt;
&lt;p&gt;And this is a self-consistent way to think about Rust and about
programming languages. It has practical applications: It gives you a
definition of when two compilers implement the &amp;ldquo;same&amp;rdquo; programming
language, and it allows you to define a formal specification for
Rust &amp;ndash; or to imagine an abstract formal specification, if you so choose,
and use this notion to think about how your Rust code might fare under
alternative implementations of the programming language.&lt;/p&gt;
&lt;h2 id=&#34;alternatives-to-the-binary-error-model&#34;&gt;Alternatives to the &amp;ldquo;Binary Error Model&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;There is no coherent way to say that this way of thinking about Rust is
wrong, per se. It is a philosophical perspective, a definition of what
concepts (like type safety) are part of the &amp;ldquo;programming language&amp;rdquo; and
the &amp;ldquo;programming language specification&amp;rdquo; (even if none has been written)
and what concepts are not, what concepts (like using snake case) are just
opinions and conventions outside of the scope of the programming language.&lt;/p&gt;
&lt;p&gt;But on the other hand, we are not forced to assume this model. As it is
a definition of what is part of the &amp;ldquo;programming language,&amp;rdquo; we are free
to use a different operating definition. As it is a scope for what
goes in the &amp;ldquo;programming language specification,&amp;rdquo; the Rust community
is free to write a formal specification with different scope.&lt;/p&gt;
&lt;p&gt;And I think we should, when that time comes, use a different scope.
I think that the people in charge of writing the spec come to it, they
will use a different scope rather than strictly following the definitions
explained here. Because even though the &amp;ldquo;binary error model&amp;rdquo; isn&amp;rsquo;t wrong,
per se, I think it is, nevertheless, harmful.&lt;/p&gt;
&lt;p&gt;I not only think if a formal Rust specification is written, it should
not use this model. I think people should not assume this model. I
think it will lead to mistakes in your thinking.  I also think that,
if you do assume this model specifically in Rust, you have to do a lot
more mental work that can be saved by asserting a different model.&lt;/p&gt;
&lt;p&gt;So what&amp;rsquo;s the alternative? Well, our original definition of a programming
language did two things. It determined if the program was valid (a binary
up-down decision), and it mapped each valid program to its semantics.&lt;/p&gt;
&lt;p&gt;An alternative model would not make validity so binary. If we do this
in the most straight-forward way, we get something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn rust_programming_language(program: SourceTree) -&amp;gt;
    (Result&amp;lt;Semantics, Vec&amp;lt;Errors&amp;gt;&amp;gt;, Vec&amp;lt;Warning&amp;gt;);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This loses a few of the nice properties that we had in the previous
definition. &amp;ldquo;Valid Rust programs&amp;rdquo; is no longer a straight-forward set.
Instead, we have a potential multiplicity of sets distinguished by this
definition:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Programs that compile&lt;/li&gt;
&lt;li&gt;Programs that compile without warnings&lt;/li&gt;
&lt;li&gt;Programs that compile without a specific warning we may care about&lt;/li&gt;
&lt;li&gt;Programs that don&amp;rsquo;t compile but only have one error&lt;/li&gt;
&lt;li&gt;Programs that don&amp;rsquo;t compile but only have one category of error&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also, this definition imposes more on the writers of alternative
implementations. Suddenly, a compiler is only a valid Rust compiler
if it outputs the exact same list of errors and warnings, given an
input program.&lt;/p&gt;
&lt;p&gt;This seems to me a little too strict. I don&amp;rsquo;t think the exact wording
of an error or warning should necessarily matter or be part of a programming
language spec. And compilers regularly stop compiling after experiencing
too many errors (where too many can sometimes be one), and implementations
would reasonably differ about &lt;em&gt;which&lt;/em&gt; errors they would output before
giving up.&lt;/p&gt;
&lt;p&gt;But I think it&amp;rsquo;s a good starting point, and in any case much better than
the binary-error &lt;code&gt;Option&amp;lt;Semantics&amp;gt;&lt;/code&gt; model. Part of the benefit of Rust
as a programming language is how much work has gone into its warnings.
For an alternative implementation to claim to be Rust without having the
same warning system would strike me as extremely misleading.  Warnings &amp;ndash;
obligatory warnings &amp;ndash; should be included in any language spec.&lt;/p&gt;
&lt;p&gt;Many important Rust safety features are actually warnings. Ignoring
&lt;code&gt;#[must_use]&lt;/code&gt; is technically a warning &amp;ndash; just set to &lt;code&gt;#[deny]&lt;/code&gt;
by default. A function that has dead code after a &lt;code&gt;return&lt;/code&gt; statement:
this is a warning, but also a serious correctness issue.&lt;/p&gt;
&lt;h2 id=&#34;rust-warnings-are-complicated&#34;&gt;Rust Warnings are Complicated&lt;/h2&gt;
&lt;p&gt;And of course any Rust implementation would have to include warnings.
Just as C (in practice) has a &lt;code&gt;#warning&lt;/code&gt; directive,
which causes the compiler to issue warnings, Rust has a number of annotations
that control the issuance of warnings.&lt;/p&gt;
&lt;p&gt;For example, if we add an annotation to our function from before:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#[deny(non_snake_case)]
fn foo() -&amp;gt; i32 {
    let Foo = 3;
    Foo
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;hellip; the warning becomes an error:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;error: variable `Foo` should have a snake case name
 --&amp;gt; test.rs:3:9
  |
3 |     let Foo = 3;
  |         ^^^ help: convert the identifier to snake case (notice the capitalization): `foo`
  |
note: the lint level is defined here
 --&amp;gt; test.rs:1:8
  |
1 | #[deny(non_snake_case)]
  |        ^^^^^^^^^^^^^^

error: aborting due to previous error
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Any Rust specification, even one with the binary error model,
would therefore have to include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The rules about snake case (variables should have snake case)&lt;/li&gt;
&lt;li&gt;The rules about annotations (so that &lt;code&gt;#[deny(...)]&lt;/code&gt; triggers an error)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means that, even if we did imagine a specification where only
errors were in scope, rules for warnings would have to also be in that
specification, because they can be configured to become errors. And at
that point, why not also specify in the specification that the warnings
are obligatory?&lt;/p&gt;
&lt;p&gt;Especially because we can also say &lt;code&gt;#[warn(...)]&lt;/code&gt; as a tolerance level
for these configurable rules. What do we say about &lt;code&gt;#[warn(...)]&lt;/code&gt;
in the spec if warnings are out of scope?&lt;/p&gt;
&lt;h2 id=&#34;the-other-side-of-the-binary&#34;&gt;The Other Side of the Binary&lt;/h2&gt;
&lt;p&gt;Now that I&amp;rsquo;ve criticized the &amp;ldquo;binary error&amp;rdquo; model from the warnings side,
I also want to address the notion that all errors are created equal.
Errors are different from each other.&lt;/p&gt;
&lt;p&gt;First off, there&amp;rsquo;s an obvious distinction between syntax errors and
semantic errors. This is kind of boring and obvious, but it adds some
nuance into the idea that invalid Rust is simply &amp;ldquo;not Rust,&amp;rdquo; and
it comes up in practice sometimes.&lt;/p&gt;
&lt;p&gt;As I write my code, I sometimes run &lt;code&gt;cargo fmt&lt;/code&gt; as part of my editing
workflow. Usually, this helps me read my own code better for further
editing, and usually, this works even if my code is full of errors &amp;ndash;
it might even help me find and understand the errors. But sometimes,
my code has a relatively superficial, syntactic error, like a missing
&lt;code&gt;}&lt;/code&gt;, and &lt;code&gt;cargo fmt&lt;/code&gt; can&amp;rsquo;t even help me. This sends me into a little
bit of a panic, but I&amp;rsquo;m usually also glad I didn&amp;rsquo;t keep working longer
with such a problem.&lt;/p&gt;
&lt;p&gt;If a Rust specification wanted to include formatting tools in its scope,
it could conceivably make a formal distinction between syntax and semantic
errors.&lt;/p&gt;
&lt;p&gt;More interesting, however, are errors that don&amp;rsquo;t have to be errors,
where the compiler could keep compiling, but it chooses not to.&lt;/p&gt;
&lt;p&gt;We have the obvious example, where the error is configurable, where
it&amp;rsquo;s actually a warning that&amp;rsquo;s just been set to &lt;code&gt;#[deny(...)]&lt;/code&gt; as a
lint level.&lt;/p&gt;
&lt;p&gt;But we also have things like lifetime errors, which cannot be disabled. Or
the rule against dereferencing a pointer outside an &lt;code&gt;unsafe&lt;/code&gt; block. The Rust
compiler could, if it wanted to, simply allow those things. We could
do something like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#[unsafe_allow(lifetime_mismatches)]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The compiler would then output a program, which would then exhibit
undefined behavior &amp;ndash; or not. It would then be potentially unsound &amp;ndash;
or not.&lt;/p&gt;
&lt;p&gt;This is not included in Rust, but it&amp;rsquo;s theoretically possible, unlike
referring to a variable that doesn&amp;rsquo;t exist, where there is no reasonable
interpretation of what the code should do.&lt;/p&gt;
&lt;p&gt;On the border is things that C++ allows, but are arguably non-sensical
like referring to a variable that doesn&amp;rsquo;t exist. If a function returns
&lt;code&gt;u32&lt;/code&gt;, and you reach the end of the function, that&amp;rsquo;s non-sensical, right?&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn foo() -&amp;gt; u32 { }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But depending on the ABI, you can just not output the code that sets
the return value, and perhaps not even output the code that returns from
the function. This is definitely undefined behavior, but C++ will often
allow it, sometimes without even a warning.&lt;/p&gt;
&lt;h2 id=&#34;unsafety-as-always-on-warnings&#34;&gt;Unsafety as Always-On Warnings&lt;/h2&gt;
&lt;p&gt;As an aside, the &lt;code&gt;#[allow]&lt;/code&gt; and &lt;code&gt;#[deny]&lt;/code&gt; annotations are very
similar to how &lt;code&gt;unsafe&lt;/code&gt; works. We could imagine an alternative world
where there was no &lt;code&gt;unsafe&lt;/code&gt; keyword for blocks. Instead of writing:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;unsafe { *ptr }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&amp;hellip; we could instead imagine a Rust where this is written as:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;#[allow(unsafe)]
*ptr
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Basically, using operations like dereference (&lt;code&gt;*ptr&lt;/code&gt;) are
disallowed in Rust by default, but can be allowed. They are
disallowed because, like Rust that is warned about, they are
indications that the programmer likely made a mistake. But like
Rust that is warned about, the programmer can make explicit
that they are using the construct on purpose.&lt;/p&gt;
&lt;p&gt;Given that &lt;code&gt;unsafe&lt;/code&gt;/safety, one of Rust&amp;rsquo;s core features, works
in a way very similar to warnings, should make us take seriously
the importance of warnings. It would have been just as valid
from a safety point of view to use literally the same mechanism
with &lt;code&gt;#[allow]&lt;/code&gt; and &lt;code&gt;#[deny]&lt;/code&gt;, but I
think safety is such an important category of possible mistakes
it&amp;rsquo;s probably for the best that it has its own special syntax.&lt;/p&gt;
&lt;h2 id=&#34;take-aways&#34;&gt;Take-Aways&lt;/h2&gt;
&lt;p&gt;So why am I writing all of this, besides thinking it&amp;rsquo;s all an
interesting mental exercise?&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t think the authors of any future Rust spec would actually err in
such a way as to not discuss warnings at all. But I think it&amp;rsquo;s important
to understand the theoretical implications.&lt;/p&gt;
&lt;p&gt;But I also know that people do think in terms of the hypothetical Rust
specification which only accepts or rejects programs. I recently saw
someone write that capitalization conventions, such as snake case, are not
part of the Rust programming language. They meant that according to the
&amp;ldquo;binary error&amp;rdquo; model that we discussed above, which they implicitly
subscribed to, using snake case or not will never change whether your
program is a valid Rust program, and therefore, the entire convention
is not part of Rust.&lt;/p&gt;
&lt;p&gt;But even if we ignore the fact that a Rust compiler needs to know about this
convention in case &lt;code&gt;#[deny]&lt;/code&gt; is used, this assumes a definition of
Rust programming language and Rust specification that uses the &amp;ldquo;binary
error&amp;rdquo; model.&lt;/p&gt;
&lt;p&gt;And while that is one way to think about Rust, it&amp;rsquo;s not
a very good one, and I would say it&amp;rsquo;s not a very useful one.
And more fundamentally, you don&amp;rsquo;t have to. You don&amp;rsquo;t have to use
this philosophical framework where only rules that cause compilation
failures are part of the programming language.&lt;/p&gt;
&lt;p&gt;So I don&amp;rsquo;t think it&amp;rsquo;s fair to say &amp;ldquo;in Haskell, variable name case is
significant, and in Rust, it is not, it is only a convention and not part
of the programming language.&amp;rdquo; I think it&amp;rsquo;s more fair to say &amp;ldquo;in Haskell,
case conventions are mandatory, violations are errors, and they are used
to disambiguate the syntax. In Rust, they are non-fatal warnings by
default, and the compiler can still process Rust with incorrect case,
and in some situations has to.&amp;rdquo; Or, more simply, &amp;ldquo;in Haskell, case
convention violations are errors, but in Rust, they&amp;rsquo;re just warnings.&amp;rdquo;
But, in both Haskell and Rust, capitalization conventions are part of
the programming language. In both, the compiler has to know about them,
and enforces them in at least some situations.&lt;/p&gt;
&lt;p&gt;This may seem like a nitpick, but I think using definitions of
&amp;ldquo;programming language&amp;rdquo; vs &amp;ldquo;convention&amp;rdquo; can make the &amp;ldquo;convention&amp;rdquo; stuff
seem less important than it should be. I think that if you think that
way, and were writing an alternative implementation of Rust, you might
give yourself permission to not care about the warnings. You might be
less likely to add a policy to use &lt;code&gt;-Werror&lt;/code&gt;, or require &lt;code&gt;clippy&lt;/code&gt; to
pass in your CI.&lt;/p&gt;
&lt;p&gt;If someone with that attitude were writing the language spec &amp;ndash; which I
don&amp;rsquo;t think they would be, but if they were &amp;ndash; they might underspecify
the things that make Rust the useful tool that it is.  Programming is
about contracts, and as far as I&amp;rsquo;m concerned, the warnings are part of
the Rust compiler&amp;rsquo;s contract. And a compiler should not be allowed to
call itself a Rust compiler if it doesn&amp;rsquo;t follow it.&lt;/p&gt;
&lt;p&gt;Snake case for variables is part of the Rust programming language, as I
define the Rust programming language, and &amp;ndash; I think &amp;ndash; as most of the
community defines it. Certainly it is part of &amp;ldquo;the Rust programming
language&amp;rdquo; as that phrase is used in common parlance, and it is one
of many features that make Rust special.
If there is to be a specification, it should
be part of the Rust specification. I understand that if you use the
&amp;ldquo;binary error&amp;rdquo; model to define what a programming language is, and what
a programming specification should be, you don&amp;rsquo;t get this result. But
I just don&amp;rsquo;t think you should be using that model, and I think it does
matter whether you do, even though it is a philosophical perspective
that cannot be disproven.&lt;/p&gt;
&lt;p&gt;Of course, Rust will probably not ever have a single monolithic
specification mediated by ISO or an equivalent. It will certainly
continue to be a community organization, with many different standards
and specifications, perhaps one for a compiler with basic features,
another for a compiler that fully supports errors, another for formatters
like &lt;code&gt;cargo fmt&lt;/code&gt;. Each of these specifications will delineate
different sets of source trees: source trees with the syntax of Rust,
source trees without errors, source trees without warnings, etc.&lt;/p&gt;
&lt;p&gt;Just like the notion of a &amp;ldquo;programming language&amp;rdquo; doesn&amp;rsquo;t have to
be a single set, a single binary between valid and invalid, the notion
of a specification also needn&amp;rsquo;t be so monolithic.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Haskell Error Messages: Come on!</title>
      <link href="https://www.thecodedmessage.com/posts/haskell-gripe/" />
      <id>https://www.thecodedmessage.com/posts/haskell-gripe/</id>
      <updated>2022-02-16T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I am a big fan of strongly typed languages, and my favorite GC&amp;rsquo;d language
is Haskell. And I want you, the reader, to keep that in mind today.
What I am writing is some commentary about a language I deeply love,
some loving criticism.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s what happened: A few days ago, I was showing off some Haskell
for a friend who primarily programs in Python. The stakes were high
&amp;ndash; could I demonstrate that this strange language was worth some
investigation?&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I am a big fan of strongly typed languages, and my favorite GC&amp;rsquo;d language
is Haskell. And I want you, the reader, to keep that in mind today.
What I am writing is some commentary about a language I deeply love,
some loving criticism.&lt;/p&gt;
&lt;p&gt;So here&amp;rsquo;s what happened: A few days ago, I was showing off some Haskell
for a friend who primarily programs in Python. The stakes were high
&amp;ndash; could I demonstrate that this strange language was worth some
investigation?&lt;/p&gt;
&lt;p&gt;My primary focus was on infinite lists, and defining &lt;code&gt;fibonacci&lt;/code&gt; as a
&lt;a href=&#34;https://wiki.haskell.org/The_Fibonacci_sequence#Using_the_infinite_list_of_Fibonacci_numbers&#34;&gt;recursive data structure&lt;/a&gt;
&amp;ndash; all fun things to show off Haskell&amp;rsquo;s laziness.
But at some point, we wrote an expression by accident that had a type
error in it, and so we got to see how the compiler treated such things.
I don&amp;rsquo;t remember the exact expression &amp;ndash; it was deep in context &amp;ndash; but
the problem was I was trying to add an integer to an list. Something
analogous to &lt;code&gt;1+[2,3]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, in some &lt;a href=&#34;https://en.wikipedia.org/wiki/JavaScript&#34;&gt;&amp;ldquo;weakly typed&amp;rdquo; languages&lt;/a&gt;,
&lt;a href=&#34;https://xkcd.com/1537/&#34;&gt;this sort of thing&lt;/a&gt; is actually allowed, as
a colleague of mine recently pointed out:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~]$ node
&amp;gt; 1+[2,3]
&amp;#39;12,3&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is, of course, hilarious. But! We shouldn&amp;rsquo;t paint &amp;ldquo;weakly typed&amp;rdquo;
languages with such a broad brush.  In my friend&amp;rsquo;s native Python, it
would have been an error, as it should be. It is a run-time error, but
what does that matter when you&amp;rsquo;re working in an interpreted language,
writing ad hoc scripts. The important thing is that failure is
recognized as failure, and it doesn&amp;rsquo;t try to
&lt;a href=&#34;https://en.wikipedia.org/wiki/Fail-fast&#34;&gt;continue with nonsense&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~]$ python3
Python 3.8.10 (default, Nov 26 2021, 20:14:08)
[GCC 9.3.0] on linux
Type &amp;#34;help&amp;#34;, &amp;#34;copyright&amp;#34;, &amp;#34;credits&amp;#34; or &amp;#34;license&amp;#34; for more information.
&amp;gt;&amp;gt;&amp;gt; 1+[2,3]
Traceback (most recent call last):
  File &amp;#34;&amp;lt;stdin&amp;gt;&amp;#34;, line 1, in &amp;lt;module&amp;gt;
TypeError: unsupported operand type(s) for +: &amp;#39;int&amp;#39; and &amp;#39;list&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is an error message. It&amp;rsquo;s even a pretty decent error message.
There are many things you can pass to the &lt;code&gt;+&lt;/code&gt; operator in Python,
but an &lt;code&gt;int&lt;/code&gt; and a &lt;code&gt;list&lt;/code&gt; together are not among them.&lt;/p&gt;
&lt;p&gt;So now, what did Haskell do, this language that I&amp;rsquo;m trying to show off?
Well, unfortunately, my friend didn&amp;rsquo;t see the actual problem in the code,
but was first made aware of it from the compiler&amp;rsquo;s error message. And
if you&amp;rsquo;ve ever done this before in Haskell, you&amp;rsquo;re probably wincing right
now, because you know what this error message is:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~]$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
Prelude&amp;gt; 1+[2,3]

&amp;lt;interactive&amp;gt;:1:1: error:
    • Non type-variable argument in the constraint: Num [a]
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        it :: forall a. (Num a, Num [a]) =&amp;gt; [a]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, my friend didn&amp;rsquo;t understand this error message at all.
Since I was in Demonstration Mode, my instinct was to explain it to him,
but after a few false starts, I realized that this would simply not
help, and pointed out that you couldn&amp;rsquo;t add integers to lists,
and showed him where this was happening (it was a little more
subtle than this example).&lt;/p&gt;
&lt;p&gt;But since then, my colleagues and I were discussing error messages in
Slack, specifically how good Rust&amp;rsquo;s error messages are, specifically
how much better they are than Haskell&amp;rsquo;s. So I had an opportunity to
paste that very bad Haskell error message me and my friend discovered
into the Slack. There, it served as a case study, so we could discuss how
problematically incomprehensible it is, sparking a lot of discussion, from
which I shall try to extract the most interesting parts into this post.&lt;/p&gt;
&lt;p&gt;For one, this error message has little to do with the concrete
problem. The problem is &amp;ndash; and the error message should say this &amp;ndash; that
you can&amp;rsquo;t add lists. Specifically, in Haskell, you can only add things that
implement the &lt;code&gt;Num&lt;/code&gt; typeclass (which lists don&amp;rsquo;t), and so you&amp;rsquo;d think the
compiler would be smart enough to mention &lt;em&gt;anywhere&lt;/em&gt; in this error message
something along the lines of &amp;ldquo;expecting &lt;code&gt;[a]&lt;/code&gt; to have &lt;code&gt;Num&lt;/code&gt; instance,
but it does not.&amp;rdquo; That&amp;rsquo;s the &lt;em&gt;actual&lt;/em&gt; problem, even if not well-explained.&lt;/p&gt;
&lt;p&gt;But instead, &lt;code&gt;ghc&lt;/code&gt; tries to assume you meant what you wrote, and figure
out a way in which &lt;code&gt;[a]&lt;/code&gt; &lt;em&gt;can&lt;/em&gt; have the &lt;code&gt;Num&lt;/code&gt; instance. This is where
it fails, and then it gives advice on how to make &lt;em&gt;that&lt;/em&gt; succeed.
As my professor-colleague points out, this is dangerous advice, especially
for beginners, because there&amp;rsquo;s no way that using &lt;code&gt;FlexibleContexts&lt;/code&gt;
will actually help in that situation. The problem isn&amp;rsquo;t that these
lists aren&amp;rsquo;t numbers in particular, and that you need to only accept
lists that are numbers in your function. The problem is that no lists
are (or at least should be) numbers! But a beginner might just follow
the advice, try to figure out what the hell &lt;code&gt;FlexibleContexts&lt;/code&gt; are,
and find themselves in a world of pain, and no closer to solving the
actual problem.&lt;/p&gt;
&lt;p&gt;Part of what causes this is the type of &lt;code&gt;1&lt;/code&gt; itself. Haskell, unlike
Rust, allows literals like &lt;code&gt;1&lt;/code&gt; to be interpreted in any number type.
Given that Haskell (like Rust) has return-type polymorphism, it can directly
express this in the type system:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Prelude&amp;gt; :type 1
1 :: Num p =&amp;gt; p
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In Rust, this would be something like &lt;code&gt;impl Num&lt;/code&gt;. It means that &lt;code&gt;1&lt;/code&gt; can
be any type that is &lt;code&gt;Num&lt;/code&gt;. Combine that with the fact that &lt;code&gt;+&lt;/code&gt; requires
its arguments to be &lt;code&gt;Num&lt;/code&gt; and to match (&lt;code&gt;(+) :: Num a =&amp;gt; a -&amp;gt; a -&amp;gt; a&lt;/code&gt;),
and when we see &lt;code&gt;1+[2,3]&lt;/code&gt;, we&amp;rsquo;re simply left trying to figure out how
&lt;code&gt;[2,3]&lt;/code&gt; is &lt;code&gt;Num&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If we did not have this &lt;em&gt;polymorphic literal&lt;/em&gt;, this notion that the
meaning of &lt;code&gt;1&lt;/code&gt; is flexible, we would have seen a much more comprehensible
error message. If &lt;code&gt;1&lt;/code&gt; meant the same thing as &lt;code&gt;(1::Integer)&lt;/code&gt; (or any
arbitrary choice), we&amp;rsquo;d have this beautiful explanation:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Prelude&amp;gt; (1::Integer) + [2,3]

&amp;lt;interactive&amp;gt;:4:16: error:
    • Couldn&amp;#39;t match expected type ‘Integer’
                  with actual type ‘[Integer]’
    • In the second argument of ‘(+)’, namely ‘[2, 3]’
      In the expression: (1 :: Integer) + [2, 3]
      In an equation for ‘it’: it = (1 :: Integer) + [2, 3]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or even if we just had non-numbers on both sides, we&amp;rsquo;d similarly
have a better error message:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;[jim@palatinate:~]$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
Prelude&amp;gt; () + [1,2]

&amp;lt;interactive&amp;gt;:1:6: error:
    • Couldn&amp;#39;t match expected type ‘()’ with actual type ‘[Integer]’
    • In the second argument of ‘(+)’, namely ‘[1, 2]’
      In the expression: () + [1, 2]
      In an equation for ‘it’: it = () + [1, 2]
Prelude&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What is my take-away here? I don&amp;rsquo;t think the compiler has been sufficiently
tweaked when it comes to error messages, or that the Haskell community
cares sufficiently about beginners. Rust as a community
puts a lot of energy into good error messages, so that even though
Rust also has a trait you could add to arrays to make &lt;code&gt;+&lt;/code&gt; work,
it still has a better error message:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;error[E0277]: cannot add `[{integer}; 2]` to `{integer}`
 --&amp;gt; test.rs:2:7
  |
2 |     1 + [2,3];
  |       ^ no implementation for `{integer} + [{integer}; 2]`
  |
  = help: the trait `Add&amp;lt;[{integer}; 2]&amp;gt;` is not implemented for `{integer}`
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But I also think the semantics of &lt;code&gt;1&lt;/code&gt; are too liberal, leaving the compiler
in an awkward place. See, the weird thing is, you can declare &lt;code&gt;[2,3]&lt;/code&gt;
a number, making &lt;code&gt;1+[2,3]&lt;/code&gt; an expression that adds two lists:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;instance Num [a] where
    (+) = (&amp;lt;&amp;gt;)
    (-) = (&amp;lt;&amp;gt;) -- Eh, why not?
    (*) = (&amp;lt;&amp;gt;)
    negate = reverse
    abs = id
    signum = const []
    fromInteger i = take (fromInteger i) $ repeat undefined

main = do
    print $ signum $ 1 + [2,3]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once you&amp;rsquo;ve defined lists as a number, &lt;code&gt;1&lt;/code&gt; is suddenly a list if
it wants to be. And this contributes to the difficulty of finding
the right error message: what you asked for is possible after all.&lt;/p&gt;
&lt;p&gt;And in the end, this leaves me with the feeling that Haskell has
this in common with Javascript, and that makes me sad. A polymorphic
enough strongly typed language is no longer strongly typed.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Being Fair about Memory Safety and Performance</title>
      <link href="https://www.thecodedmessage.com/posts/unsafe/" />
      <id>https://www.thecodedmessage.com/posts/unsafe/</id>
      <updated>2022-01-20T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;For this next iteration in my &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;series&lt;/a&gt; comparing
Rust to C++, I want to talk about something I&amp;rsquo;ve been avoiding so far:
memory safety. I&amp;rsquo;ve been avoiding this topic so far because I think it
is the most discussed difference between C++ and Rust, and therefore I
felt I&amp;rsquo;d have relatively little to add to the conversation. I&amp;rsquo;ve also
been avoiding it because I wanted to draw attention to all the other
little ways in which Rust is a better-designed programming language,
to say that even if you concede to the C++ people that Rust isn&amp;rsquo;t &amp;ldquo;truly
memory safe&amp;rdquo; or &amp;ldquo;memory safe enough,&amp;rdquo; Rust still wins.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;For this next iteration in my &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;series&lt;/a&gt; comparing
Rust to C++, I want to talk about something I&amp;rsquo;ve been avoiding so far:
memory safety. I&amp;rsquo;ve been avoiding this topic so far because I think it
is the most discussed difference between C++ and Rust, and therefore I
felt I&amp;rsquo;d have relatively little to add to the conversation. I&amp;rsquo;ve also
been avoiding it because I wanted to draw attention to all the other
little ways in which Rust is a better-designed programming language,
to say that even if you concede to the C++ people that Rust isn&amp;rsquo;t &amp;ldquo;truly
memory safe&amp;rdquo; or &amp;ldquo;memory safe enough,&amp;rdquo; Rust still wins.&lt;/p&gt;
&lt;h2 id=&#34;array-indexing&#34;&gt;Array Indexing&lt;/h2&gt;
&lt;p&gt;But there is a persistent and persnickety little argument that I wanted to
talk specifically about. This argument is really persuasive on its face,
and so I think it deserves some attention &amp;ndash; especially since I am guilty
of having used this argument myself, many years ago when I still worked
at an HFT firm, to claim that C++ had a niche that Rust wasn&amp;rsquo;t ready for.
I&amp;rsquo;ve also seen it a few times in a row in the wild, and it&amp;rsquo;s made me
so emotional that I simply had to write this, and as a result, it&amp;rsquo;s
a little more emotional than some of the other posts.&lt;/p&gt;
&lt;p&gt;In this argument, array indexing stands in for a number of little
features. But &amp;ndash; I&amp;rsquo;ve seen array indexing cited so often as a canonical
example that I feel compelled to address it directly!&lt;/p&gt;
&lt;p&gt;The argument goes like this: In Rust, array accesses are checked. Every
time you write &lt;code&gt;arr[i]&lt;/code&gt;, there is an extra prepended
&lt;code&gt;if i &amp;gt;= arr.len() { panic!(..) }&lt;/code&gt;. As you can see, that is more code,
and worse, a run-time check. And while the optimizer might eliminate
it, or the branch predictor may well predict it right every time,
the extra code bloat and possible run-time check, is just
unacceptable in [insert field here (I used HFT)], where every
nanosecond matters. And until some acceptable solution is found to this,
I just don&amp;rsquo;t see Rust making it in [insert field].&lt;/p&gt;
&lt;p&gt;When I made this argument, to a group of programming-language academics,
the defenders of Rust countered with a number of points, all of which
accepted the basic premise:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do I really need those extra nanoseconds? Yes.&lt;/li&gt;
&lt;li&gt;Is it really too much of a price to pay for all that extra
safety? Yes.&lt;/li&gt;
&lt;li&gt;Do I really distrust the optimizer that much? Yes. If only
Rust had a way to do optimizer assertions, a way to
statically verify that the &lt;a href=&#34;https://github.com/dtolnay/no-panic&#34;&gt;panic had been optimized
out&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Would dependent typing on integer values help? Yes. That sounds
very promising. I think Rust will get there someday, but for right
now we must use C++.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that I know more about Rust I&amp;rsquo;m happy to tell you that I was
completely off base. I wasn&amp;rsquo;t off base about the performance considerations,
or the unacceptability of even the slightest risk of a run-time check.
I was off base about an even more basic premise: that Rust uses checked
array indexing, whereas C++ uses unchecked array indexing.&lt;/p&gt;
&lt;p&gt;But wait! Isn&amp;rsquo;t that the whole point? Doesn&amp;rsquo;t C++ avoid checking everything,
to make sure all abstractions are zero-cost, to be blazing fast? Doesn&amp;rsquo;t
Rust, while trying for performance, in the end always concede to the
demands of safety?&lt;/p&gt;
&lt;p&gt;Well, let&amp;rsquo;s look at the APIs in question. C++ apologists are always
saying to use the modern C++ features from C++11 and later,
rather than the more C-like &amp;ldquo;old style&amp;rdquo; C++ features, so on the
C++ side let&amp;rsquo;s take a look at the
&lt;a href=&#34;https://en.cppreference.com/w/cpp/container/array&#34;&gt;documentation&lt;/a&gt;
for &lt;code&gt;std::array&lt;/code&gt;, introduced in C++11.&lt;/p&gt;
&lt;p&gt;Here we see two indexing methods. The first one, &lt;code&gt;at&lt;/code&gt;, is bounds
checked and will throw an exception if the index is out of bounds,
whereas the second one, &lt;code&gt;operator[]&lt;/code&gt;, is not, and will instead exhibit
undefined behavior of a very difficult-to-debug nature. It looks like C++
actually believes in free choice here, leaving the choice of method up
to the user. Not quite what we supposed, but the important part is that
unchecked indexing is available, so so far the argument can still stand.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s look at Rust. Rust arrays and vectors can also be used with
methods from &lt;a href=&#34;https://doc.rust-lang.org/std/primitive.slice.html&#34;&gt;slice&lt;/a&gt;,
as can slices, so the slice documentation is the best place to look.
And looking there, we immediately see &amp;ndash; drum roll please &amp;ndash; 4 methods. We
see &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;get_mut&lt;/code&gt;, which are checked, and right underneath them,
in alphabetical order, &lt;code&gt;get_unchecked&lt;/code&gt; and &lt;code&gt;get_unchecked_mut&lt;/code&gt;, which
are not.&lt;/p&gt;
&lt;p&gt;To review, where do Rust and C++, these programming languages with
their vastly different philosophies, Rust for the cautious, C++
for the fast and bold, stand? In the exact same place. Both programming
languages have both checked and unchecked indexing.&lt;/p&gt;
&lt;p&gt;Let me say that again. This is the talking point form, what to say if you
need something quick to say, if you&amp;rsquo;re ever debating programming languages
on a political-style talk show (or at a party or even a job interview):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In both Rust and C++, there is a method for checked array indexing,
and a method for unchecked array indexing. The languages actually
agree on this issue. They only disagree about which version gets to
be spelled with brackets.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The difference is simply in the default, which one gets
that old fashioned &lt;code&gt;arr[index]&lt;/code&gt; syntax. And even that &lt;a href=&#34;https://docs.rs/unchecked-index/latest/unchecked_index/&#34;&gt;can be
changed&lt;/a&gt;.
Even if the C++ default were superior &amp;ndash; and, as I will argue later,
it is not &amp;ndash; this is surely a minor issue. After all, don&amp;rsquo;t we normally
use our fancy &lt;code&gt;for x in arr&lt;/code&gt; syntax in Rust? This issue is just so small
as to be unlikely to be a deciding factor in what programming language
is better, even if we&amp;rsquo;re in a special application domain where every
nanosecond matters.&lt;/p&gt;
&lt;h2 id=&#34;the-unsafe-keyword&#34;&gt;The Unsafe Keyword&lt;/h2&gt;
&lt;p&gt;So that&amp;rsquo;s a wrap folks. We can all go home, and none of
us will ever see this extremely silly argument on the
Internet or in person again. It&amp;rsquo;s just a misunderstanding,
the person making it was simply misinformed, and all it will
take is a link to this blog post &amp;ndash; or the &lt;a href=&#34;https://doc.rust-lang.org/std/primitive.slice.html#method.get_unchecked&#34;&gt;relevant method in the
docs&lt;/a&gt;
to set them straight.&lt;/p&gt;
&lt;p&gt;But wait! The C++ apologists are still talking! What are they saying?
How have they not been completely flummoxed? They&amp;rsquo;re pointing
at that method, chanting a word like a slogan at a protest march.
I can&amp;rsquo;t quite make it out &amp;ndash; what it is it?&lt;/p&gt;
&lt;p&gt;Oh. They&amp;rsquo;re chanting &lt;code&gt;unsafe&lt;/code&gt;. And credit where credit is due:
it&amp;rsquo;s very difficult to chant in a monospace font.&lt;/p&gt;
&lt;p&gt;Well, that is easy to respond with! The nerve, that C++ programmers would
call our unchecked array indexing method unsafe. For one, all unchecked
array indexing methods are unsafe: that&amp;rsquo;s what unchecked means. If it
were safe, it would be at least statically checked. For another, isn&amp;rsquo;t
this the pot calling the kettle black? Isn&amp;rsquo;t C++ all about unsafety,
so much that C++ programmers don&amp;rsquo;t even mark their unsafe code regions
becasue it all is, or their unsafe functions because they all are?&lt;/p&gt;
&lt;p&gt;&amp;ldquo;But isn&amp;rsquo;t that the whole point of Rust?&amp;rdquo; they cry. &amp;ldquo;If you have to
use &lt;code&gt;unsafe&lt;/code&gt; to write good Rust, then Rust isn&amp;rsquo;t a safe language
after all! It&amp;rsquo;s a cute effort, but it&amp;rsquo;s failing at its purpose!
Might as well use C++ like a &lt;a href=&#34;http://www.catb.org/jargon/html/R/Real-Programmer.html&#34;&gt;Real Programmer&lt;/a&gt;!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;This, my friends, is a
&lt;a href=&#34;https://www.smbc-comics.com/comic/logical-fallacies&#34;&gt;straw&lt;/a&gt;
&lt;a href=&#34;https://www.smbc-comics.com/comic/straw-men&#34;&gt;man&lt;/a&gt;. No, the point
of Rust and specifically Rust&amp;rsquo;s memory safety features is not
to create an entirely safe programming language that can&amp;rsquo;t be
circumvented in any circumstance; you must be thinking of Sing#,
the programming language for Microsoft&amp;rsquo;s defunct &lt;a href=&#34;https://www.microsoft.com/en-us/research/project/singularity/&#34;&gt;research
OS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let me be abundantly clear: The point of memory safety, the unsafe
keyword, and friends in Rust is not to completely enforce memory safety,
to make it impossible for the programmer to do anything they want to
with the computer, even if they can&amp;rsquo;t prove to the compiler that it&amp;rsquo;s OK.
In fact, the point of memory safety isn&amp;rsquo;t to make it &lt;em&gt;impossible&lt;/em&gt; to do
anything at all &amp;ndash; it&amp;rsquo;s to make it &lt;em&gt;possible&lt;/em&gt; to reason about the program.&lt;/p&gt;
&lt;p&gt;The premise of Rust is that the vast majority of code in a systems program
doesn&amp;rsquo;t need to be unsafe, and so it might as well be safe. People used
to believe that you needed garbage collection for safety, but Rust
proved that you could use lifetimes to still get safety without that
performance cost. Now that we&amp;rsquo;re there, why worry about null pointers?
Why not tell the compiler which things can be null, and which things
can&amp;rsquo;t, so the compiler can check for you whether you&amp;rsquo;re handling nulls
correctly? I&amp;rsquo;ve programmed C++ professionally for years without such a
feature.  You&amp;rsquo;d better believe I would have totally annotated the crap
out of the code so the compiler could&amp;rsquo;ve caught them ahead of time.&lt;/p&gt;
&lt;p&gt;Sometimes, C++ apologists cite valgrind. I&amp;rsquo;ve had codebases where
I tried to use &lt;code&gt;valgrind&lt;/code&gt;. Unfortunately, there was so much undefined
behavior and memory leaks already caked into this project that new
ones were simply impossible to see among all the noise. An army
of junior engineers was at some point required to clean this up
when finally the hierarcy decided that &amp;ldquo;valgrind&amp;rdquo; was something we
might want to be able to use in the future.&lt;/p&gt;
&lt;p&gt;And a lot of those undefined behaviors were ticking time bombs.
Certainly, this codebase had its issues. A friend of mine took days to
find a bug where a pointer had a value of 7. I don&amp;rsquo;t mean 7 elements into
some array, not 7 of the relatively wide pointer type, not a convenient,
testable-for &lt;code&gt;NULL&lt;/code&gt;, value. No, none of that: The pointer&amp;rsquo;s value was
exactly &lt;code&gt;0x7&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: My friend had a very similar incident to that described
in &lt;a href=&#34;https://scholar.harvard.edu/files/mickens/files/thenightwatch.pdf&#34;&gt;this piece&lt;/a&gt;,
but it was not the same incident. Some time after, I read that
piece and shared it with this friend &amp;hellip; and I must have conflated
the numbers from the piece and from what happened to my friend.
It was some null-page number, some &amp;ldquo;low integer,&amp;rdquo; however, even
if not &lt;code&gt;0x7&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I&amp;rsquo;ve had memory corruption issues where I poured over every line of code
that I wrote, over and over again, finding nothing. Ultimately, I learned
that the issue was in framework code &amp;ndash; code written by my boss&amp;rsquo;s boss.
The code was untested, and written extremely poorly, and had rotted, so
that it didn&amp;rsquo;t work at all. In Rust, I might have had some idea that
my code &amp;ndash; which in Rust would have all been able to be &amp;ldquo;safe&amp;rdquo; &amp;ndash;
couldn&amp;rsquo;t possibly be the source of the problem. Maybe my humble assumption
that my code was to blame would be a little less tenable.&lt;/p&gt;
&lt;p&gt;If I wanted a language that was always safe, at the time I knew Java
or Python existed. Some companies even do finance in Java, for exactly
that reason. But sometimes you still need that extra bit of performance.
&lt;code&gt;unsafe&lt;/code&gt; is sometimes necessary.&lt;/p&gt;
&lt;p&gt;But given what gains safe Rust has made in predictable performance,
it&amp;rsquo;s not as necessary as it used to be. The majority of the code I
wrote then could&amp;rsquo;ve been written in safe Rust, and not lost a single
clock cycle. The parts that needed to be unsafe could have been
isolated, delegated to specific sections, wrapped in
abstract data types, perhaps entrusted to a specific team.&lt;/p&gt;
&lt;p&gt;And even then, I&amp;rsquo;m sure we would have been debugging memory
corruption issues. But we&amp;rsquo;d know where to look. We&amp;rsquo;d know where to
throw the tests. And we&amp;rsquo;d have saved programmer-years of time,
days if not months of my life.&lt;/p&gt;
&lt;p&gt;Now, I&amp;rsquo;m proud of my C++ skills. There is some part of me that wishes
that C++ was better than Rust, that all that time getting better at
debugging memory corruption wasn&amp;rsquo;t dedicated to a skill that is
becoming obsolescent through better technology. And to be honest, that&amp;rsquo;s
part of why I dismissed Rust as a candidate for HFT programming
languages.&lt;/p&gt;
&lt;p&gt;But it&amp;rsquo;s possible to be proud of a skill that is also becoming obsolete.
And I am trying to replace it with a new skill to be proud of &amp;ndash; writing
Rust as performant as idiomatic C++, or even more performant, while
reaching for the &lt;code&gt;unsafe&lt;/code&gt; keyword rarely and modularly. I think it&amp;rsquo;s truly
possible, for where it&amp;rsquo;s relevant.&lt;/p&gt;
&lt;p&gt;Now I must turn to a subset of C++ apologists, who write using &amp;ldquo;modern
C++&amp;rdquo; which is &amp;ldquo;very safe now&amp;rdquo; and experience therefore no memory corruption
issues. To them I say, you are not doing high performance programming.
If you were, you&amp;rsquo;d have to do some wonky things with pointers to spell
the bespoke high-performance constructs you&amp;rsquo;d need.&lt;/p&gt;
&lt;p&gt;There is indeed a safe subset of C++ heavy with modern features. If
you are disciplined and keep your programming in that realm, you can
avoid memory corruption mostly. But first, this safe subset covers fewer
high-performance features than Rust. I&amp;rsquo;ve read some of this code and its
idioms: It&amp;rsquo;s full of &lt;code&gt;shared_ptr&lt;/code&gt;s not to share ownership but simply to
avoid types that might be invalidated. It ironically leans on reference
counting more than idiomatic Rust. This is among other, similar problems.&lt;/p&gt;
&lt;p&gt;Let me be clear: First off, instead of keeping in your brain which
features are &amp;ldquo;modern&amp;rdquo; and which are &amp;ldquo;edgy,&amp;rdquo; why not have a distinction where
it&amp;rsquo;s well-marked? Second off, if you are writing entirely in this safe
subset of C++, you can get much better performance instead out of the
safe subset of Rust. You have no right to complain about Rust&amp;rsquo;s safety
trade-offs, as you&amp;rsquo;re using a worse set, where you get no safety
promises from the compiler and none of Rust&amp;rsquo;s surprising safe performance.&lt;/p&gt;
&lt;p&gt;Rust&amp;rsquo;s safe and &amp;ldquo;slow&amp;rdquo; subset is faster than C++&amp;rsquo;s while still being,
obviously, safer. Rust&amp;rsquo;s unsafe subset is better factored and better
distinguished. Comparing apples to apples, Rust is better programming
language for extracting performance out of LLVM, because you&amp;rsquo;ll be able
to code more often without fear, and with very focussed fear when you
do feel it.&lt;/p&gt;
&lt;p&gt;A tool is even more useful if you can adjust it. The defenders
of C++ talk about choosing trade-offs, but really, Rust offers both
trade-offs. Mark your code as &lt;code&gt;unsafe&lt;/code&gt; and convince yourself of its
safety manually, or rely on programming language features. It&amp;rsquo;s up to
you, on a function-by-function, even block-by-block, basis.  In C++,
if you have a problem, every line of code is suspect; you simply
can&amp;rsquo;t opt in to safety, but in Rust, for where you don&amp;rsquo;t need the
performance of unchecked indexing and other unsafe features, you can
relax about the possibility of going &lt;a href=&#34;https://en.wikipedia.org/wiki/Knight_Capital_Group&#34;&gt;bankrupt due to inadvertent memory
reinterpretation&lt;/a&gt; &amp;ndash;
and how do I wish my NDA permitted me to talk about consequences at my own
previous jobs!&lt;/p&gt;
&lt;p&gt;And for where you do need to use &lt;code&gt;unsafe&lt;/code&gt;, you can make sure your
debugging and overthinking efforts are well-directed, for the few places
in a large project you need it.&lt;/p&gt;
&lt;h2 id=&#34;unchecked-indices&#34;&gt;Unchecked Indices&lt;/h2&gt;
&lt;p&gt;This has gotten a little far from the original question. Should array
indices be checked? Well, let me be clear about two facts that are both true,
but in tension with each other:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unchecked array indexing is sometimes absolutely necessary&lt;/li&gt;
&lt;li&gt;Unchecked array indexing is an edge-case feature, which you
normally don&amp;rsquo;t want.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If unchecked array indexing was unavailable in Rust, that would be a bug.
What is not a bug is making it inconvenient. C++ programmers probably
should be using &lt;code&gt;at&lt;/code&gt; instead of &lt;code&gt;operator[]&lt;/code&gt; more often. But in C++,
what would it gain? There&amp;rsquo;s so many unsafe features, what&amp;rsquo;s the cost
of one more?&lt;/p&gt;
&lt;p&gt;But in Rust, where so much code can be written that&amp;rsquo;s completely safe,
defaulting to the safe version makes more sense. Lack of safety is a cost
too, and Rust makes that cost explicit. Isn&amp;rsquo;t that the goal of C++, making
costs explicit?&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look at situations where you are indexing memory. First off, most
of them I saw were in old C-style &lt;code&gt;for&lt;/code&gt;-loops, where you loop over an
index rather than using iterators directly with a collection. Both Rust
and C++ have safe versions of &lt;code&gt;for&lt;/code&gt; that loop over collections with
iterators, and those use the same check for the loop as they do for
bounds, so those are easy enough to address. Nevertheless, I think that
a lot of the noise about checked vs. unchecked array accesses comes from
people who use indexing for their &lt;code&gt;for&lt;/code&gt;-loops instead of iterators,
and therefore mistakenly think that array indexing in general is a
far more common operation than it is.&lt;/p&gt;
&lt;p&gt;For the remaining situations, most are implementing either gnarly
business logic, or a subtle, fast algorithm.&lt;/p&gt;
&lt;p&gt;If it&amp;rsquo;s gnarly business logic, in my experience, it&amp;rsquo;s usually at config
time &amp;ndash; along with a good third to half to even more of the code in a
complicated production system.&lt;/p&gt;
&lt;p&gt;What do I mean by config time? A running high-performance system, whether
optimized for latency or throughput, has a bunch of data structures
organized just so, a lot of threads set up just right to move data
between them in the perfect rhythm, and a lot of the work is in arranging
them. That work is generally not performance-sensitive, but often has
to be in the same programming language as the performance-intensive stuff.&lt;/p&gt;
&lt;p&gt;Config-time is, depending on how you look at it, less of a thing or the
entire thing in a programming language like Python.  Python basically
exists to do config-time programming for performance-intensive code put
in very comprehensive &amp;ldquo;libraries&amp;rdquo; written in C or C++. But in C++, where
you have a constructor that runs only once or a few times at first,
and other methods related to it, in the same programming language as the
money-making do-it part, you have to really adjust programming style
between them.&lt;/p&gt;
&lt;p&gt;Config-time is obviously when you read the configuration files.
It&amp;rsquo;s where you open the relevant files. It&amp;rsquo;s where you call &lt;code&gt;socket&lt;/code&gt;
and &lt;code&gt;bind&lt;/code&gt; and &lt;code&gt;listen&lt;/code&gt; on your listening port. It&amp;rsquo;s where you spin up
your worker threads, and make computations on how many worker threads
there are. It&amp;rsquo;s where you construct your objects and your object pools.
It&amp;rsquo;s where you memory map your log file. It&amp;rsquo;s where you set your process
priorities. It&amp;rsquo;s where you recursively call the constructors and &lt;code&gt;init&lt;/code&gt;
functions of every object in your overwrought OOP hierarchy.&lt;/p&gt;
&lt;p&gt;There is no need to sacrifice safety for performance at
config time &amp;ndash; especially since undefined behavior might lie latent and
destabilize the system once it&amp;rsquo;s actually up and running. If you do
an unchecked array access at config time, you might put garbage data in
an important field, maybe one that determines how much money you&amp;rsquo;re willing
to risk that day or how many of a thing to buy. And for what? To save a few
nanoseconds before your process has even &amp;ldquo;gone live&amp;rdquo;?&lt;/p&gt;
&lt;p&gt;So, when do you truly need unchecked array accesses?  If it&amp;rsquo;s a subtle
fast algorithm, probably deep in an inner loop, you should probably be
wrapping it in an abstraction anyway. The code that actually executes the
algorithm should be separate from the business logic, so that programmers
trying to maintain the business logic don&amp;rsquo;t accidentally break it. And
that&amp;rsquo;s exactly where it makes the most sense to use &lt;code&gt;unsafe&lt;/code&gt; &amp;ndash; when
implementing a special algorithm. Maybe the proof that the index is
within bounds relies upon some number theory the compiler was never going
to understand without its own proof engine: great! You should probably
be explaining that in a comment in C++ anyway, and so the conventional
comment that goes with the &lt;code&gt;unsafe&lt;/code&gt; block in Rust is a perfect place to
explain it.&lt;/p&gt;
&lt;p&gt;But maybe I&amp;rsquo;m wrong about all of this. Maybe your experience hasn&amp;rsquo;t
matched mine.  Maybe your particular application needs to make unchecked
array accesses a lot, needs them to be unchecked, and needs them littered
all over the codebase. I raise my eyebrows at you, suspect you need more
iterators and perhaps other abstractions, and wonder what problem you&amp;rsquo;re
trying to solve. But even if you&amp;rsquo;re absolutely right, I think it&amp;rsquo;s still
a better idea to write Rust littered with &lt;code&gt;unsafe&lt;/code&gt; every time you index
an array, than to write C++.&lt;/p&gt;
&lt;p&gt;Because, as I keep emphasizing, Rust is still a better unsafe programming
language than C++. It would be better than C++ even if safety weren&amp;rsquo;t
a feature.&lt;/p&gt;
&lt;h2 id=&#34;post-script-some-perspective-for-the-new-rustacean&#34;&gt;Post-Script: Some Perspective for the New Rustacean&lt;/h2&gt;
&lt;p&gt;I understand where this straw man argument comes from. The word
&lt;code&gt;unsafe&lt;/code&gt; is scary, and advice, especially aimed at people coming
from safe languages like Python and Javascript, is to avoid &lt;code&gt;unsafe&lt;/code&gt;
features while learning. And while I think adding &lt;code&gt;unsafe&lt;/code&gt; to production
code should only be done once you&amp;rsquo;ve exhausted safe possibilities &amp;ndash; which
requires full understanding of safe possibilities &amp;ndash; this advice can
feel overbearing for a transitioning C++ programmer, especially when
it is immediately obvious that the safe features are very constrained
and can&amp;rsquo;t literally do everything.&lt;/p&gt;
&lt;p&gt;For that good-faith recovering C++ programmer, new to Rust: You&amp;rsquo;re
right. The safe subset isn&amp;rsquo;t enough to do everything you want to
do. And when it doesn&amp;rsquo;t, that doesn&amp;rsquo;t mean it failed. Its goal is to
make unsafe code rare, not non-existent.  But it might surprise you
how rarely you truly &lt;em&gt;need&lt;/em&gt; &lt;code&gt;unsafe&lt;/code&gt;.  And a good resource for you
might be, as it was for me, the excellent &lt;a href=&#34;http://cliffle.com/p/dangerust/&#34;&gt;Learn Rust the Dangerous
Way&lt;/a&gt; by Cliff L. Biffle.&lt;/p&gt;
&lt;p&gt;For what it&amp;rsquo;s worth, however, this criticism of Rust in general is often
levelled either in bad faith, or from a misunderstanding of what the
&lt;code&gt;unsafe&lt;/code&gt; keyword is for. For all the philosophical discussion of what
&lt;code&gt;unsafe&lt;/code&gt; truly means &amp;ndash; and how it interacts with the surrounding
module and encapsulation/privacy boundaries &amp;ndash; as well as principled
conventions for using it, please see the
&lt;a href=&#34;https://doc.rust-lang.org/nomicon/&#34;&gt;Rustonomicon&lt;/a&gt;, the canonical
book on unsafe Rust, the same way &lt;a href=&#34;https://doc.rust-lang.org/book/&#34;&gt;the book&lt;/a&gt;
is canonical for introducing Rust.&lt;/p&gt;
&lt;p&gt;Other criticisms of Rust from an HFT or low-latency point of view
are more relevant. Most specifically, &lt;code&gt;gcc&lt;/code&gt; and &lt;code&gt;icc&lt;/code&gt; are much better
compilers for those use cases &amp;ndash; empirically &amp;ndash; than is LLVM. Also,
the large codebases existing in C++ are often tested and contain
thousands upon thousands of programmer-years of optimizations and
bugfixes, where even small compiler upgrades are scrutinized closely
for performance regressions. Migrating to another programming language
from that starting point would be prohibitively expensive.&lt;/p&gt;
&lt;p&gt;None of which is to say that if Rust gradually replaced C++ altogether,
eventually such ultra-optimizing compilers and ultra-optimized codebases
wouldn&amp;rsquo;t start appearing in Rust. I hope to see that day within my
lifetime.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>In Defense of Async: Function Colors Are Rusty</title>
      <link href="https://www.thecodedmessage.com/posts/async-colors/" />
      <id>https://www.thecodedmessage.com/posts/async-colors/</id>
      <updated>2022-01-03T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;Finally in 2019, Rust stabilized the &lt;code&gt;async&lt;/code&gt; feature, which supports
asynchronous operations in a way that doesn&amp;rsquo;t require multiple operating
system threads. This feature was so anticipated and hyped and in
demand that there was a &lt;a href=&#34;https://areweasyncyet.rs/&#34;&gt;website&lt;/a&gt; whose sole
purpose was to announce its stabilization.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;async&lt;/code&gt; was controversial from its inception; it&amp;rsquo;s still controversial
today; and in this post I am throwing my own 2 cents into this
controversy, in defense of the feature. I am only going to try to
counter one particular line of criticism here, and I don&amp;rsquo;t anticipate
I&amp;rsquo;ll cover all the nuance of it &amp;ndash; this is a multifaceted issue, and
I have a day job. I am also going to assume for this
post that you have some understanding of how &lt;code&gt;async&lt;/code&gt; works, but if
you don&amp;rsquo;t, or just want a refresher I heartily recommend the &lt;a href=&#34;https://tokio.rs/tokio/tutorial&#34;&gt;Tokio
tutorial&lt;/a&gt;.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;Finally in 2019, Rust stabilized the &lt;code&gt;async&lt;/code&gt; feature, which supports
asynchronous operations in a way that doesn&amp;rsquo;t require multiple operating
system threads. This feature was so anticipated and hyped and in
demand that there was a &lt;a href=&#34;https://areweasyncyet.rs/&#34;&gt;website&lt;/a&gt; whose sole
purpose was to announce its stabilization.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;async&lt;/code&gt; was controversial from its inception; it&amp;rsquo;s still controversial
today; and in this post I am throwing my own 2 cents into this
controversy, in defense of the feature. I am only going to try to
counter one particular line of criticism here, and I don&amp;rsquo;t anticipate
I&amp;rsquo;ll cover all the nuance of it &amp;ndash; this is a multifaceted issue, and
I have a day job. I am also going to assume for this
post that you have some understanding of how &lt;code&gt;async&lt;/code&gt; works, but if
you don&amp;rsquo;t, or just want a refresher I heartily recommend the &lt;a href=&#34;https://tokio.rs/tokio/tutorial&#34;&gt;Tokio
tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;the-questionable-feature-colored-functions&#34;&gt;The Questionable Feature: Colored Functions&lt;/h2&gt;
&lt;p&gt;In any discussion of a programming language feature, the first thing
to ask is what problem the feature is trying to solve. In the case of
&lt;code&gt;async&lt;/code&gt;, it&amp;rsquo;s trying to deal with asynchronous operations &amp;ndash; operations
that don&amp;rsquo;t require more work from the CPU to make progress, and where
several might be in flight at any given time. For example, a single process
might be writing some data to a file, reading data from another file,
waiting for new incoming connections, and servicing an existing connection.&lt;/p&gt;
&lt;p&gt;So how does Rust solve this?
The easiest way to address this problem would be to have a thread for each
operation, and to let the thread block at the asynchronous operation,
essentially pretending that the operation is a long-running function
like any other the CPU has to do, rather than something taking
place elsewhere.  But operating system threads are expensive. And
rather than using green threads as &lt;a href=&#34;https://gobyexample.com/goroutines&#34;&gt;some other programming languages
do&lt;/a&gt;, Rust decided to create a
syntactic sugar for futures, meaning that Rust&amp;rsquo;s &lt;code&gt;async&lt;/code&gt; feature now
suffers from the dreaded function coloring effect first explained by
Bob Nystrom in a Javascript context in 2015.&lt;/p&gt;
&lt;p&gt;In Bob Nystrom&amp;rsquo;s
&lt;a href=&#34;https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/&#34;&gt;now-famous essay&lt;/a&gt;
he complains that an analogous feature in Javascript is harmful, because
asynchronous functions &amp;ndash; which he refers to as &amp;ldquo;red&amp;rdquo; functions &amp;ndash; can only
be called from other red functions. Once a red function is needed, the
function that calls it must also be red, and same with the function that
calls that, the whole way up the call chain. And the syntax and semantics
of calling a red function is more complicated than that of calling blue
functions &amp;ndash; especially in Javascript, where the next thing to do had to
be enclosed in a lambda, resulting in &lt;a href=&#34;http://callbackhell.com/&#34;&gt;callback hell&lt;/a&gt;
(I do not endorse the suggestions in that post).&lt;/p&gt;
&lt;h2 id=&#34;colored-is-good-actually-and-rusty&#34;&gt;Colored Is Good, Actually, and Rusty&lt;/h2&gt;
&lt;p&gt;My position is close to those of &lt;a href=&#34;https://morestina.net/blog/1686/rust-async-is-colored&#34;&gt;this article&lt;/a&gt;,
but with enough nuance that I wanted to write my own blog post to explain
it in more detail. Fundamentally, I agree that Rust does indeed have
colored functions, and that it&amp;rsquo;s not a bad thing. But I would go further.
I say that function coloring has always existed in Rust, even before it
manifested in the &lt;code&gt;async&lt;/code&gt; world, that it is the Rustiest way to solve
this problem, and furthermore, that Rust needs more function coloring than
it has.&lt;/p&gt;
&lt;p&gt;Rust, unlike the Javascript of the original colored functions article, is
strongly typed, and influenced heavily by Haskell. This means
that it has lots of type distinction on its values: &amp;ldquo;colored&amp;rdquo; values, if
you will.&lt;/p&gt;
&lt;p&gt;This type information includes basic ideas of type (string vs number
vs widget), but also shades of distinction that a Javascript programmer
won&amp;rsquo;t even be aware of.  Let&amp;rsquo;s say you want to take a parameter to your
function, a &amp;ldquo;widget.&amp;rdquo; In Javascript, you just take a parameter &lt;code&gt;widget&lt;/code&gt;
and do widget things with it, and hope that it works out. The name is
just a comment: it&amp;rsquo;s up to the caller to know what exactly is expected,
hopefully some sort of widget that works.  In Rust, on the other hand, you
have to annotate the parameter with a type, which not only ensures it&amp;rsquo;s
actually a widget, but distinguishes between these potential requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Exclusive reference to a widget &lt;code&gt;&amp;amp;mut Widget&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Ownership of a widget &lt;code&gt;Widget&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Reference to a widget that lives forever: &lt;code&gt;&amp;amp;&#39;static Widget&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Optional widget (in Javascript this is very unclear): &lt;code&gt;Option&amp;lt;Widget&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If &lt;code&gt;Widget&lt;/code&gt; is a trait, you have even more options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Owned run-time generic widget: &lt;code&gt;Box&amp;lt;dyn Widget&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Non-owned reference to compile-time generic widget: &lt;code&gt;&amp;amp;impl Widget&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The list goes on. For each of these options, also, the caller often
has to do something different. If the parameter is optional with &lt;code&gt;Option&lt;/code&gt;,
and the caller in fact has a widget, the caller still has to add &lt;code&gt;Some&lt;/code&gt;
to the parameter:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn foo(widget: &amp;amp;Widget) { ... }
fn foo2(widget: Option&amp;lt;&amp;amp;Widget&amp;gt;) { ... }
fn foo3(widget: Widget) { ... }

let baz = Widget::new();
foo(&amp;amp;baz);
foo2(Some(&amp;amp;baz));
foo3(baz);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;All of these, in my
&lt;a href=&#34;https://en.wikipedia.org/wiki/Synesthesia&#34;&gt;synaesthetic&lt;/a&gt; mind, are
expressed by different colors and textures on the parameter.  For all
of these, Rust has made a value judgment that the programmer should be
explicitly aware of these &lt;em&gt;shades&lt;/em&gt; of distinction, if you will (pun
intended). If a parameter is to be optional, the function is called
differently than if it is mandatory. If a borrow happens, that requires a
&lt;code&gt;&amp;amp;&lt;/code&gt; from the caller, to make clear to the programmer what is going on,
to make sure the writer of the caller and the writer of the callee are
on the same page. Parameters in Rust are, in general, colored.&lt;/p&gt;
&lt;p&gt;And this value coloring, like the async/sync function coloring, propagates. If
a function requires a parameter to be &lt;code&gt;&#39;static&lt;/code&gt; in lifetime,
that requirement propagates to the caller of that function to the caller
of that function to the originator of the value in question.&lt;/p&gt;
&lt;p&gt;Similarly with return values &amp;ndash; I disagree with &amp;ldquo;More Stina&amp;rdquo; about
&lt;code&gt;Result&lt;/code&gt;.  I say &lt;code&gt;Result&lt;/code&gt;-returning fallible functions are colored. In
many programming languages, including Javascript, any and all functions
can throw recoverable exceptions. In Rust, functions that might fail
(in a recoverable fashion) must have a different return type than those
that do not &amp;ndash; they must return a &lt;code&gt;Result&amp;lt;...&amp;gt;&lt;/code&gt;. Functions that return
&lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt; are, as with async functions, harder to call than functions
that just return &lt;code&gt;T&lt;/code&gt;. If you don&amp;rsquo;t want to use the syntactic sugar &lt;code&gt;?&lt;/code&gt;
to propagate the error, you have to grapple with &lt;code&gt;Result&lt;/code&gt; as a literal
return type, which means unpacking it and doing something else in the
&lt;code&gt;Err&lt;/code&gt; case. This is more straightforward than dealing with a raw &lt;code&gt;impl Future&lt;/code&gt;, but fundamentally the same concept: either propagate the &amp;ldquo;color&amp;rdquo;
with &lt;code&gt;?&lt;/code&gt; or &lt;code&gt;async&lt;/code&gt;, or else deal with all the implications of &lt;code&gt;Result&lt;/code&gt;
or &lt;code&gt;Future&lt;/code&gt; on the spot.&lt;/p&gt;
&lt;p&gt;And all of these distinctions mean something. Passing by shared reference,
mutable reference, or value are different, and put different safety
requirements on the calling code, safety requirements that allow Rust
to make more safety guarantees than Javascript ever could. Passing
by reference is literally different at the ABI level from by-value,
so each can implement the exact contract as efficiently as possible,
unlike Javascript which leans on an expensive garbage collector for
cleaning up the difference between these notions.  That is to say, where
Javascript (and Python) use garbage collectors, Rust uses distinctions &amp;ndash;
color distinctions, one might say &amp;ndash; between types to achieve the same
result, benefitting in performance but requiring more exactness from
the programmer.&lt;/p&gt;
&lt;p&gt;And in Rust, a statically typed programming language, we believe this to
be a good thing. Rust is not for every project &amp;ndash; it&amp;rsquo;s a steeper learning
curve than Python or Javascript, and not every project needs to be
maintainable long-term &amp;ndash; but it has a distinct, consistent philosophy,
which says that different things should be treated differently.&lt;/p&gt;
&lt;h2 id=&#34;async-functions-are-just-different&#34;&gt;Async Functions Are Just Different&lt;/h2&gt;
&lt;p&gt;A blocking or asynchronous function is not the same thing as a
non-blocking function.  A non-blocking function fundamentally does some
CPU tasks, taking control of the processor, using it, and giving it back.
An asynchronous function does the set-up necessary for work to happen
elsewhere. That work doesn&amp;rsquo;t need control of the CPU, and can be dealt
with through a handle &amp;ndash; a future &amp;ndash; rather than just waiting for completion.
These are fundamentally different notions, and while it might (or might not)
make sense in Go or Javascript to lump them together into one notion
of &amp;ldquo;calling a function,&amp;rdquo; Rust doesn&amp;rsquo;t do lumping.&lt;/p&gt;
&lt;p&gt;When you call a normal function &amp;ndash; without &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; &amp;ndash; you build up
a stack. When you use &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;, you build up a complex nested
state object. If you use &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; with an executor to spawn a new
task, that complex state object ends up on the heap in a data structure
next to other task objects.&lt;/p&gt;
&lt;p&gt;Both &amp;ldquo;call stack&amp;rdquo; (for synchronous code) and &amp;ldquo;task state object&amp;rdquo; (for
asynchronous code) are reasonable ways of managing memory. Honestly, the
miracle is that Rust, through &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt;, manages to make these
two vastly different paradigms look as similar as they do. Having to
annotate the difference is a small price to pay for high-performance
reactive programming.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not 100% perfect. Even with the &lt;code&gt;must_use&lt;/code&gt; warnings, people forget
to call &lt;code&gt;await&lt;/code&gt; on their futures sometimes. And writing reactive, async
code is harder &amp;ndash; which makes sense, because the resulting code is a
more difficult but more performing usage of memory. Writing code that
passes the borrow checker is harder, but considered worth it because
we can remove indirections and avoid garbage collection. &lt;code&gt;async&lt;/code&gt; offers
us the same deal for reactive programming.&lt;/p&gt;
&lt;h2 id=&#34;alternatives-to-async&#34;&gt;Alternatives to Async&lt;/h2&gt;
&lt;p&gt;But let&amp;rsquo;s say we did want to remove the coloring here. Let&amp;rsquo;s say
we did want to pretend that blocking functions were just like CPU-based
ones, but just taking a long time. What would we have to do?&lt;/p&gt;
&lt;p&gt;Well, we&amp;rsquo;d still have to wait for multiple things simultaneously. Our
servers have many connections they have to service at once, and when a
message comes in on socket B, it can&amp;rsquo;t be ignored just because the code
happens to be on socket A. If asynchronous operations are implemented
by blocking, we have to handle this with multithreading.&lt;/p&gt;
&lt;p&gt;Kernel multithreading is expensive, but even Go-style &amp;ldquo;green threads&amp;rdquo;
have to have a separate stack for each green thread. Stacks are gnarly,
because it&amp;rsquo;s unclear how much space should be reserved for them ahead
of time. They have to dynamically adjust to the run-time demand, and
when the original allocation is used up, you get a pause as you try
to allocate more. The advantage is, you have a simpler mental model
with fewer distinctions. Basically, you trade performance for simplicity
&amp;ndash; like in garbage collection.&lt;/p&gt;
&lt;p&gt;If you want to do this trade, Rust doesn&amp;rsquo;t stop you from implementing
it yourself. OS threads and blocking system calls are perfectly reasonable
solutions to many problems. But Rust isn&amp;rsquo;t going to encourage the trade
by creating a new compromise point of &amp;ldquo;green threads.&amp;rdquo; You have to do async
the whole way, and if you think of what async code actually de-sugars to,
you wouldn&amp;rsquo;t complain about how hard async functions are, but be impressed
it&amp;rsquo;s so darn easy to write them!&lt;/p&gt;
&lt;p&gt;Rust is a systems programming language at heart. I understand and respect
that, because of its type system and guarantees, it has found use outside
of the old domains of C and C++, but those C and C++ systems programmers
are Rust&amp;rsquo;s ideal &amp;ldquo;base,&amp;rdquo; in a political sense of the word. Rust should
not sacrifice performance for ease of programmability.&lt;/p&gt;
&lt;h2 id=&#34;blocking-vs-non-blocking&#34;&gt;Blocking vs Non-Blocking&lt;/h2&gt;
&lt;p&gt;Rust has two ways of doing off-CPU &amp;ldquo;IO&amp;rdquo; operations,
blocking and non-blocking. Blocking takes over the thread, and non-blocking
works through &lt;code&gt;async&lt;/code&gt;. This mirrors a distinction in the system calls
that most kernels provide. The operating system API has this distinction
built into it, and it makes sense for Rust to propagate that to the user.&lt;/p&gt;
&lt;p&gt;But fundamentally, one of these constructs is more honest than the
other. When we call a blocking kernel system call, rather than the
kernel taking over the CPU, running on it, and then returning the
thread of execution to us, what actually happens internally is
more of a mirage. The kernel deschedules the current process,
and using an internal mechanism more like &lt;code&gt;async&lt;/code&gt; than like blocking,
schedules it again, recovering its previous state as if nothing
happens, when the IO is done.&lt;/p&gt;
&lt;p&gt;This means that we can pretend the I/O operation was just an operation
like any other, but it comes at a risk &amp;ndash; the operation might not
return anytime soon. It might in fact wait for a situation that&amp;rsquo;s
not going to happen anytime soon.&lt;/p&gt;
&lt;p&gt;If such a blocking function is called from a non-async Rust thread,
we assume that the caller is using threads to juggle multiple I/O
events &amp;ndash; or else that they simply don&amp;rsquo;t have anything else going on.
But it is very dangerous to call a blocking function from an &lt;code&gt;async&lt;/code&gt;
function. It can starve threads in a thread pool, and cause knock-on
effects in other places. Maybe an async task is waiting for a message
from a channel, and even though the message was sent, the task doesn&amp;rsquo;t
resume because the thread it&amp;rsquo;s scheduled on is busy on this blocking
function. The effects are unpredictable and non-local &amp;ndash; similar to
the dreaded &amp;ldquo;undefined behavior&amp;rdquo; &amp;ndash; and debugging is similarly difficult
&amp;ndash; ask me how I know!&lt;/p&gt;
&lt;p&gt;Functions that block but are not async are referred to in the &amp;ldquo;More Stina&amp;rdquo;
&lt;a href=&#34;https://morestina.net/blog/1686/rust-async-is-colored&#34;&gt;blog post&lt;/a&gt; (also
linked above) as &amp;ldquo;purple functions.&amp;rdquo; They are not true async &amp;ldquo;red functions&amp;rdquo;
that you can call with &lt;code&gt;async&lt;/code&gt;, but they are also not safe to simply call
from an async function like a truly CPU-based &amp;ldquo;blue function&amp;rdquo; would be.
Calling a blocking function from an async function is extremely unsafe,
and there is simply no warning generated by &lt;code&gt;rustc&lt;/code&gt;, normally so helpful
about such things, to let you know how deep and undebuggable a mistake
you&amp;rsquo;re making.&lt;/p&gt;
&lt;p&gt;These purple functions ought to be a different color in Rust, just like
they are in practice. It should be an error to call a blocking system call
from an &lt;code&gt;async&lt;/code&gt; function. I don&amp;rsquo;t know how this would work &amp;ndash; I imagine
a generalization of &lt;code&gt;unsafe&lt;/code&gt; that includes things like &lt;code&gt;blocks&lt;/code&gt;, perhaps
as well as &lt;code&gt;panics&lt;/code&gt;. That would fundamentally be an &amp;ldquo;effects system,&amp;rdquo;
as is regularly proposed, but that&amp;rsquo;s not the only solution. But I do
fundamentally think that something ought to be done about this deficit
in Rust&amp;rsquo;s otherwise quite rigorous function-coloring system.&lt;/p&gt;
&lt;p&gt;So, in conclusion, I say: yes, Rust &lt;code&gt;async&lt;/code&gt; functions are colored.
This is the same as saying they are strongly typed, and this is a good
thing. And instead of trying to fix it, we should have more of it.&lt;/p&gt;
&lt;h2 id=&#34;postscript-monads&#34;&gt;Postscript: Monads&lt;/h2&gt;
&lt;p&gt;As I mentioned before, calling an async function does something
fundamentally different under the hood from calling a vanilla &amp;ldquo;blue&amp;rdquo;
function. Similarly, calling a fallible function with &lt;code&gt;Result&lt;/code&gt; does
something different from calling a function with a normal return
value. In both cases, the control flow is different &amp;ndash; either it
contains short-circuits to error code (&lt;code&gt;Result&lt;/code&gt;); or regular
hops back and forth between the task, other tasks, and the
executor (&lt;code&gt;async&lt;/code&gt;/&lt;code&gt;Future&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;In both these cases, it&amp;rsquo;s like the meaning of having one statement
come after another has changed: &lt;code&gt;;&lt;/code&gt; itself has been overriden.
And it would be nice if generic collections methods, like &lt;code&gt;map&lt;/code&gt;
and &lt;code&gt;filter&lt;/code&gt;, supported this, so that you could fail, or &lt;code&gt;await&lt;/code&gt;,
in the closures.&lt;/p&gt;
&lt;p&gt;This is possible in Haskell, because Haskell has a typeclass (equivalent
to Rust traits) for abstracting over different styles of control flow.
That is what Haskell&amp;rsquo;s infamous monads are for, and why Haskell persists
in using this technology even though it&amp;rsquo;s so famously confusing for
beginners.&lt;/p&gt;
&lt;p&gt;Fundamentally, every Haskell monad is a function color. And often, they
can be stacked together (via &amp;ldquo;monad transformers&amp;rdquo;) so that you can say
something like &amp;ldquo;this function can do IO, fail, and be asynchronous.&amp;rdquo;
You can also create functions that are polymorphic on &amp;ldquo;color&amp;rdquo;: the control
flow is rewritten based on which monad you actually end up in.&lt;/p&gt;
&lt;p&gt;Why is this useful? As &lt;a href=&#34;https://morestina.net/blog/1686/rust-async-is-colored&#34;&gt;&amp;ldquo;More Stina&amp;rdquo;&amp;rsquo;s
post&lt;/a&gt; already
mentions, there is a &lt;a href=&#34;https://blog.yoshuawuyts.com/fallible-iterator-adapters/&#34;&gt;proposal&lt;/a&gt; to add &lt;code&gt;try_&lt;/code&gt; versions of iterator adapter methods: &lt;code&gt;try_filter&lt;/code&gt;, etc.,
to enable them to work smoothly with &lt;code&gt;Result&lt;/code&gt;-&amp;ldquo;colored&amp;rdquo; functions.
A method like &lt;code&gt;filter&lt;/code&gt; or &lt;code&gt;map&lt;/code&gt; also would need an adapter to work well with
&lt;code&gt;async&lt;/code&gt;. If there were an abstract concept of monad, we could write
code with &lt;code&gt;filter&lt;/code&gt;-like methods that could short-circuit on failure and
do the right thing with &lt;code&gt;await&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;vec!([2,3,4])
    .iter()
    .filter_monad(|x| fallable_thing.contains(x)?)
    .filter_monad(|x| network_file_thing.contains(x).await?)
    .for_each_monad(|x| network_other_thing.send(x).await);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Perhaps Rust will someday gain this abstraction as well. I actually think
that would be good for Rust. Monads are hard to deal with conceptually,
and I&amp;rsquo;m not sure how to make them more user-accessible, but I think if
anyone could do it, it&amp;rsquo;s the Rust people, who&amp;rsquo;ve already done such a
good job so far at programming language design and maintenance.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Endianness, API Design, and Polymorphism in Rust</title>
      <link href="https://www.thecodedmessage.com/posts/endian_polymorphism/" />
      <id>https://www.thecodedmessage.com/posts/endian_polymorphism/</id>
      <updated>2021-11-21T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;I have been working on a serialization project recently that involves
endianness (also known as byte order), and it caused me to explore parts
of the Rust standard library that deals with endianness, and share my
thoughts about how endianness should be represented in a programming
language and its standard library, as I think this is also something
that Rust does better than C++, and also makes for a good case study to
talk about API design and polymorphism in Rust.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;I have been working on a serialization project recently that involves
endianness (also known as byte order), and it caused me to explore parts
of the Rust standard library that deals with endianness, and share my
thoughts about how endianness should be represented in a programming
language and its standard library, as I think this is also something
that Rust does better than C++, and also makes for a good case study to
talk about API design and polymorphism in Rust.&lt;/p&gt;
&lt;p&gt;To start with, let&amp;rsquo;s discuss endianness a little. I assume most of
my audience has some familiarity with endianness; nevertheless, I&amp;rsquo;d
like to explain it from first principles. That way, we can subsequently
apply the insights from the explanation to API design. That, and I want
practice explaining concepts, even if they are basic. I&amp;rsquo;ll try to keep
it interesting, but also feel free to skim the next section.&lt;/p&gt;
&lt;h2 id=&#34;big-end-little-end&#34;&gt;Big End, Little End&lt;/h2&gt;
&lt;p&gt;I first encountered the concept of endianness when I was first learning
to program using the &lt;code&gt;DEBUG.EXE&lt;/code&gt; program on DOS. When a 16-bit value was
displayed as a 16-bit value, it was just normal hexadecimal, but when
it was displayed as two 8-bit bytes, something weird happened with the
display.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a &lt;a href=&#34;endianness/display_bytes.cpp&#34;&gt;C++ snippet&lt;/a&gt; that demonstates
the effect:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;template&amp;lt;typename T&amp;gt;
void display_bytes(const T &amp;amp;val) {
    char bytes[sizeof(T)];
    memcpy(bytes, &amp;amp;val, sizeof(T));
    for (auto byte : bytes) {
        printf(&amp;#34;%2x &amp;#34;, byte);
    }
    printf(&amp;#34;\n&amp;#34;);
}

int main() {
    int value = 0x12345678;
    printf(&amp;#34;%x\n&amp;#34;, value);
    display_bytes(value);
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When run on any little-endian processor (the vast majority of processors),
we get:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;12345678
78 56 34 12
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The least significant byte is first, so if you print out the individual
bytes in order, you have to read it backwards &amp;ndash; though each individual
byte is still forwards.&lt;/p&gt;
&lt;p&gt;If you were to run the same code on a big-endian processor, you would get:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;12345678
12 34 56 78
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At this point, little endianness as I understood it was a weird thing
that Intel processors did for reasons I didn&amp;rsquo;t understand, that made me
do a little extra work when reading hex dumps. At the time, this was
fine: I thought that having to apply this extra arcane knowledge was
cool for its own sake. But also, I thought of little endianness as the
weird way to do things that required extra work, and big endianness as
the more natural design. It wasn&amp;rsquo;t until much later that I got some
nuance on that opinion.&lt;/p&gt;
&lt;p&gt;See, the writing system we use for numbers is big endian. Instead of
dividing a number into bytes (base 256), we divide it into digits.
We consider the left of the page to come before the right of the page,
and we write the most significant digit first. This is all taught
explicitly in grade school:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;1234 = 1*10^3 + 2*10^2 + 3*10^1 + 4*10^0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There&amp;rsquo;s a certain, very human logic to this system: the more important
information comes first, then the details. Mathematically, though,
we see decreasing numbers for the powers of 10: first we specify
a factor for 10 to the &lt;em&gt;third&lt;/em&gt;, then to the &lt;em&gt;second&lt;/em&gt;, then to the
&lt;em&gt;first&lt;/em&gt;, then to the &lt;em&gt;zeroth&lt;/em&gt;. We could instead imagine where
we wrote our decimal numbers big endian, where the same
number would be written &lt;code&gt;4321&lt;/code&gt;, and still mean &amp;ldquo;one thousand
two hundred thirty-four,&amp;rdquo; where we&amp;rsquo;d count like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;0
1
2
3
...
9
01
11
21
...
91
02
12
...
99
001
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This would have the advantage that the first digit, digit zero,
would be multiplied by &lt;code&gt;10^0&lt;/code&gt;, digit one by &lt;code&gt;10^1&lt;/code&gt;. Not what
humans would normally decide to do, but it has a certain logic.
And if you think about languages like Hebrew or Arabic, which
are written right from left, but which write numbers the same
direction we do, the least significant digit is actually reached
first in the normal direction of reading: when they see &amp;ldquo;100&amp;rdquo;
in the midst of the text, the zeroes are &amp;ldquo;before&amp;rdquo; the &amp;ldquo;1&amp;rdquo;. (I am
told that this is not how most people think of it; that they instead
just think of numbers as going the other way from other text, but
it just goes to demonstrate how based on convention all of this
stuff is).&lt;/p&gt;
&lt;p&gt;So all of this is to say that, the weird effect we had before
with big endian looking &amp;ldquo;normal&amp;rdquo; and little endian looking &amp;ldquo;weird&amp;rdquo;
has nothing to do with the intrinsic logic of big vs little endian,
but rather with the fact that we&amp;rsquo;re mixing a little endian processor
with a big endian writing notation. If we
&lt;a href=&#34;https://www.thecodedmessage.com/endianness/backwards_hex.cpp&#34;&gt;instead&lt;/a&gt; were to print
the digits of each number in increasing significance &amp;ndash; that is,
if we were to use little endian as our printing convention &amp;ndash; we&amp;rsquo;d get:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# Little Endian Machine
87654321
87 65 43 21
# Big Endian Machine
87654321
21 43 65 87
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The mismatch between writing the whole word in hex and writing the
individual bytes in order, in hex is caused by a mismatch between
the endianness of the system (normally little in practice) and
the endianness of the writing system (normally big in practice).
When the writing system isn&amp;rsquo;t a factor, little endian makes more
mathematical sense, is easier to reason about in circuitry and
code, and therefore has won out over big endian in every major processor
architecture.&lt;/p&gt;
&lt;p&gt;The only real exception is network byte order, which uses big endian.
This is convenient for manually reading hex dumps of packets, but
probably has more to do with the fact that the Internet developed when
this question was much less settled. Due to the presence of network byte
order, however, and the fact that the endianness of Intel and modern
ARM is opposite of the endianness of most human writing systems, the
concept remains with us.&lt;/p&gt;
&lt;h2 id=&#34;when-is-endianness-relevant&#34;&gt;When is endianness relevant?&lt;/h2&gt;
&lt;p&gt;In writing numbers, a digit has no endianness: &lt;code&gt;8&lt;/code&gt; means the same thing as
a single digit number. Similarly, a byte is indivisible in a processor.
Bytes are made up of bits, but outside of special instructions, the
ordering of those bits is not relevant. One of them is most significant,
one of them is least, but unless we&amp;rsquo;re indexing them for a special
instruction, or sending them over a wire one by one, there is no way to
say which such bit comes &amp;ldquo;first.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Indeed, if we want to display a byte as a series of bits,
we as the programmer get to choose the endianness, and the
&lt;a href=&#34;https://www.thecodedmessage.com/endianness/bits.rs&#34;&gt;program&lt;/a&gt; runs identically on either a big endian
or a little endian platform. The little endian version is a little
more intuitive, as &amp;ldquo;2 to the N&amp;rdquo; is an operation that&amp;rsquo;s easy to write
on computers, and in little endian the N increases as the index increases:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn byte_as_bits_le(byte: u8) -&amp;gt; [u8; 8] {
    let mut res = [0u8; 8];
    for i in 0..8 {
        let mask = 1 &amp;lt;&amp;lt; i;
        if byte &amp;amp; mask == 0 {
            res[i] = 0;
        } else {
            res[i] = 1;
        }
    }
    res
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nevertheless, at no point is this function relying on the endianness
of the hardware, and it does the same thing on either types of hardware.&lt;/p&gt;
&lt;p&gt;Why do I bring this up? Well, I don&amp;rsquo;t think it makes any sense to speak
of the endianness of a (multi-byte) word &lt;em&gt;per se&lt;/em&gt;. The endianness of the
word only comes into play when it is stored as &amp;ndash; and accessible as &amp;ndash;
a series of bytes.&lt;/p&gt;
&lt;p&gt;So from that point of view, what are the operations where endianness is
relevant? Given a word, what series of bytes comprises it? And then,
given a series of bytes, what word is it?&lt;/p&gt;
&lt;p&gt;In Rust terms, these are &lt;code&gt;to_be_bytes&lt;/code&gt; (for big endian)/&lt;code&gt;to_le_bytes&lt;/code&gt; (for
little) in the one direction, and &lt;code&gt;from_be_bytes&lt;/code&gt;/&lt;code&gt;from_le_bytes&lt;/code&gt; in the
other. These methods are all bundled together in the Rust
&lt;a href=&#34;https://doc.rust-lang.org/std/primitive.u32.html#method.to_be_bytes&#34;&gt;documentation&lt;/a&gt;
for &amp;ndash; in this case &amp;ndash; the primitive &lt;code&gt;u32&lt;/code&gt; type, along with &lt;code&gt;ne&lt;/code&gt; which
gives whatever the native endianness of the processor is.&lt;/p&gt;
&lt;p&gt;These are the APIs I&amp;rsquo;m going to be discussing. But before discussing
how they might be improved, I&amp;rsquo;m going to point out an API that I think
doesn&amp;rsquo;t make as much sense:
&lt;a href=&#34;https://doc.rust-lang.org/std/primitive.u32.html#method.to_be&#34;&gt;&lt;code&gt;to_be&lt;/code&gt;&lt;/a&gt;. This method takes in a word, a &lt;code&gt;u32&lt;/code&gt;, and outputs
a &lt;code&gt;u32&lt;/code&gt;, and yet claims to change the endianness of that word, which as
I mentioned, does not have endianness per se, only in that it&amp;rsquo;s represented
by bytes.&lt;/p&gt;
&lt;p&gt;I know what they mean by it. On a little endian platform, it will replace
&lt;code&gt;0x12345678&lt;/code&gt; with &lt;code&gt;0x78563412&lt;/code&gt;. But what does that actually mean? In
its form as a &lt;code&gt;u32&lt;/code&gt;, as I have argued above, a number has no endianness.
So what is this number &lt;code&gt;0x78563412&lt;/code&gt;? It is the number that, if stored
in bytes in the native endianness, will store the original number in big
endian.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s a mouthful, I know, because it&amp;rsquo;s actually a complicated concept.
That is to say, it&amp;rsquo;s a hack. We want to write a number &amp;ndash; say, &lt;code&gt;2000&lt;/code&gt; &amp;ndash;
in big endian, but we don&amp;rsquo;t want to think of it as bytes, yet. We want to
be able to load the whole number into a register, and when we write it,
we want it to be &lt;code&gt;2000&lt;/code&gt; in big endian. So we byte swap the number, and
instead of storing &lt;code&gt;2000&lt;/code&gt;, we store &lt;code&gt;3490119680&lt;/code&gt;, so that if we
write it using the processor&amp;rsquo;s normal mechanism for writing, it comes out
to 2000 in big endian.&lt;/p&gt;
&lt;p&gt;Basically, &lt;code&gt;to_be&lt;/code&gt; does the equivalent of &lt;code&gt;u32::from_le_bytes(input.to_be_bytes())&lt;/code&gt;, and using it looks like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;let input: u32 = 2000;
// These two invocations do the same thing
let be = input.to_be();
let be2: u32 = u32::from_le_bytes(input.to_be_bytes());
println!(&amp;#34;{} {}&amp;#34;, be, be2); // 3490119680 for both

// The result can be written using native (little endian) byte
// order, and it will give 2000 in big endian byte order.
assert_eq!(be.to_le_bytes(), input.to_be_bytes());
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is arguably a useful hack &amp;ndash; though I&amp;rsquo;m not fully convinced &amp;ndash; but
it is definitely a hack. I do not think the description is sufficiently
rigorous. The output of &lt;code&gt;to_be&lt;/code&gt; is not a number &amp;ldquo;in big endian,&amp;rdquo; it
is a different number that resembles the big endian representation of
the original number. The description is a simplification, and I think
a conceptually incoherent one &amp;ndash; which is understandable because the
concept at play here is so hackish.&lt;/p&gt;
&lt;p&gt;It appears that &lt;code&gt;to_be&lt;/code&gt; was in Rust 1.0, and &lt;code&gt;to_be_bytes&lt;/code&gt; was introduced
later. This to me is a good sign, as &lt;code&gt;to_be_bytes&lt;/code&gt;, I think, makes
much more sense as an interface. And as to why we started out with the
&lt;code&gt;to_be&lt;/code&gt; type of interface in Rust, that makes sense as well, because in
C the traditional (POSIX but not ANSI C) functions for these conversions
have similar semantics, such as &lt;code&gt;htonl&lt;/code&gt; (host to network long), where
we have this conceit of storing a &amp;ldquo;big endian&amp;rdquo; or &amp;ldquo;network byte order&amp;rdquo;
value in a &lt;code&gt;uint32_t&lt;/code&gt; (C for &lt;code&gt;u32&lt;/code&gt;). This always struck me as the wrong
abstraction, but it is justified &amp;ndash; or at least more understandable &amp;ndash;
for C as we simply can&amp;rsquo;t pass around things like &lt;code&gt;char[4]&lt;/code&gt; (C for &lt;code&gt;[u8; 4]&lt;/code&gt;)
by value in C.&lt;/p&gt;
&lt;p&gt;There are other technical and historical reasons why &lt;code&gt;htonl&lt;/code&gt; and &lt;code&gt;to_be&lt;/code&gt;
and friends exist, even if conceptually messy, but in any case, since I&amp;rsquo;m
talking about API design, and &lt;code&gt;to_be_bytes&lt;/code&gt; and friends are a better match for
the concepts at hand, I am now going to pretend &lt;code&gt;to_be&lt;/code&gt; is deprecated
(it is not), and move on to discussing the design of &lt;code&gt;to_be_bytes&lt;/code&gt; and
&lt;code&gt;to_le_bytes&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;policies&#34;&gt;Policies&lt;/h2&gt;
&lt;p&gt;So the first thing I notice is that there&amp;rsquo;s six methods that deal
with fundamentally one topic:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;from_be_bytes
from_le_bytes
from_ne_bytes
to_be_bytes
to_le_bytes
to_ne_bytes
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;But really they vary in two ways, namely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;which operation is performed (&lt;code&gt;from_X_bytes&lt;/code&gt; vs &lt;code&gt;to_X_bytes&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;which endianness is required (&lt;code&gt;le&lt;/code&gt;, &lt;code&gt;be&lt;/code&gt;, and &lt;code&gt;ne&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For us humans, this is clear from the names, but to the compiler,
these names do not form a pattern that it is capable of recognizing.
There are simply 6 separate functions named with 6 separate combinations
of characters.&lt;/p&gt;
&lt;p&gt;Now, having separate functions for separate operations makes sense;
that&amp;rsquo;s what functions are for. But for the same operation but with
different endianness, it might make more sense to indicate that
it is one operation with several possible endiannesses by making
the endianness into a parameter.&lt;/p&gt;
&lt;p&gt;The obvious way to do this would be via run-time parameter. A fairly
literal translation of this API would be something like:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;enum Endian {
    Little,
    Big,
    Native,
}

impl u32 {
    fn to_endian_bytes(self, endianness: Endian) -&amp;gt; [u8; 4] {
        match endianness {
            Endian::Little | Endian::Native =&amp;gt; { ... }
            Endian::Big =&amp;gt; { ... }
        }
    }

    fn from_endian_bytes([u8: 4], endianness: Endian) -&amp;gt; Self {
        match endianness {
            Endian::Little | Endian::Native =&amp;gt; { ... }
            Endian::Big =&amp;gt; { ... }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This would also allow us to implement the concept of &amp;ldquo;native&amp;rdquo; byte
order a little differently, and create more names for byte orders:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;enum Endian {
    Little,
    Big,
}
static NATIVE_ENDIAN: Endian = Endian::Little;
static NETWORK_ENDIAN: Endian = Endian::Big;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So, besides simplifying away the need for a separate implementation
for the &lt;code&gt;ne&lt;/code&gt; functions, and making the code more in sync with what&amp;rsquo;s
happening, what other positive things have we accomplished? Well,
given that we now have a parameter, we can now make more complicated
code parametric on it. Imagine we have an entire structure to write out,
and we want to write the entire structure as big-endian or little-endian,
perhaps because the protocol in question changed endianness at some version.
Or perhaps we just want to make clear to the reader that one endianness
is used for the entire structure. We can now do something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;struct Structure {
    a: u32,
    b: u32,
    c: u32,
}

impl Structure {
    fn serialize(&amp;amp;self, endianness: Endian) -&amp;gt; [u8; 12] {
        let mut res = [0u8; 12];
        [0..4].copy_from_slice(self.a.to_endian_bytes(endianness));
        [4..8].copy_from_slice(self.b.to_endian_bytes(endianness));
        [8..12].copy_from_slice(self.c.to_endian_bytes(endianness));
        res
    }

    pub fn serialize_old_version(&amp;amp;self) -&amp;gt; [u8; 12] {
        self.serialize(Endian::Big)
    }

    pub fn serialize_new_version(&amp;amp;self) -&amp;gt; [u8; 12] {
        self.serialize(Endian::Little)
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The alternative would be to write two separate serializers, and duplicate
all the logic of how to arrange the layout. Duplication is bad, because
bug fixes don&amp;rsquo;t necessarily get to all the duplicate copies. So, to
save on duplication, we&amp;rsquo;d have to basically wrap &lt;code&gt;to_be_bytes&lt;/code&gt; and
&lt;code&gt;to_le_bytes&lt;/code&gt; in a version of this; it would be more convenient
if the standard library had done this for us.&lt;/p&gt;
&lt;p&gt;What is the downside of this? Well, the implementation didn&amp;rsquo;t really
get any simpler. Actually, in the normal case, where you don&amp;rsquo;t change
your mind about endianness, the implementation got more complicated.
We now have a &lt;code&gt;match&lt;/code&gt; expression in our two simplified functions,
which theoretically indicates a run-time decision. We could trust
the optimizer to fold the decision in through inlining and
constant-propagation, but trusting the optimizer is suspicious
and unnecessary.&lt;/p&gt;
&lt;p&gt;Nothing we&amp;rsquo;ve done so far requires this decision to be made at
run-time, and so we can instead make the decision at compile-time.
Where we had a run-time parameter, we can now have a compile-time
parameter.&lt;/p&gt;
&lt;p&gt;Now, although Rust has rudimentary support for other kinds of
compile-time parameters, the archetypical compile-time parameter
is a type, bound by a trait. Our &lt;code&gt;enum&lt;/code&gt; from before would then
have to be lifted into the type space, as a &lt;code&gt;trait&lt;/code&gt; and a few
types:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;trait Endianness { }

struct BigEndian;
impl Endianness for BigEndian { }

struct LittleEndian;
impl Endianness for LittleEndian { }
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, we need a compile-time equivalent for &lt;code&gt;match&lt;/code&gt;. This is a
little harder, as at the time of this writing stable Rust does
not have the most direct equivalent of &lt;code&gt;match&lt;/code&gt; for implementors
of &lt;code&gt;trait&lt;/code&gt;s, that is, &amp;ldquo;specialization.&amp;rdquo; But Rust does allow something
similar: the code for each branch of the &lt;code&gt;match&lt;/code&gt; must go in each type&amp;rsquo;s
implementation of that trait, and the fact of the &lt;code&gt;match&lt;/code&gt; must be
provided in the trait itself.&lt;/p&gt;
&lt;p&gt;This will also help us simplify the implementation. This &lt;code&gt;to_be_bytes&lt;/code&gt;/
&lt;code&gt;to_le_bytes&lt;/code&gt; API is not just implemented for &lt;code&gt;u32&lt;/code&gt;, but for all primitive
types. Currently, these mostly-similar implementations are stamped out
by a macro, along with other methods for primitive types. But we might
imagine that there are two things going on in the implementation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;write out the type into an array of bytes&lt;/li&gt;
&lt;li&gt;either swap the bytes, or not, based on whether we&amp;rsquo;re using the hardware
endianness&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We could then make the trait come into play &amp;ndash; with the decision made at
compile time &amp;ndash; for the swapping part.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;trait Endianness {
    fn possibly_swap(bytes: &amp;amp;mut [u8]);
}

struct BigEndian;
impl Endianness for BigEndian {
    fn possibly_swap(bytes: &amp;amp;mut [u8]) {
        // actually swap here
    }
}

impl Endianness for LittleEndian {
    fn possibly_swap(_: &amp;amp;mut [u8]) {
        // no need to do anything here
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We have now moved some of the implementation into a trait,
where the specifics of the implementation are determined by which type
implements that trait. This is an example of the policy pattern, where
a portion of the code is abstracted out into a policy, and the policy
and the main body of the function are sewn together &amp;ndash; in this case,
at compile-time &amp;ndash; into many variations of a function that execute
similarly to what an implementor might have written by hand.&lt;/p&gt;
&lt;p&gt;Note that there is no possibility of doing run-time endianness
determination in this version. This trait methods does not take a
&lt;code&gt;self&lt;/code&gt; parameter, and would have to be invoked as &lt;code&gt;T::possibly_swap&lt;/code&gt;.
This is possible in Rust because we are doing compile-time polymorphism,
not run-time, so there is no need to make this trait object-safe.&lt;/p&gt;
&lt;p&gt;Our previous example serializer, with the two versions, now looks
something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;struct Structure {
    a: u32,
    b: u32,
    c: u32,
}

impl Structure {
    fn serialize&amp;lt;T: Endianness&amp;gt;(&amp;amp;self) -&amp;gt; [u8; 12] {
        let res = [0u8; 12];
        (&amp;amp;mut res[0..4]).copy_from_slice(self.a.to_endian_bytes::&amp;lt;T&amp;gt;());
        (&amp;amp;mut res[4..8]).copy_from_slice(self.b.to_endian_bytes::&amp;lt;T&amp;gt;());
        (&amp;amp;mut res[8..12]).copy_from_slice(self.c.to_endian_bytes::&amp;lt;T&amp;gt;());
    }

    pub fn serialize_old_version(&amp;amp;self) -&amp;gt; [u8; 12] {
        self.serialize::&amp;lt;BigEndian&amp;gt;()
    }

    pub fn serialize_new_version(&amp;amp;self) -&amp;gt; [u8; 12] {
        self.serialize::&amp;lt;LittleEndian&amp;gt;()
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The policy pattern is a fairly common pattern in generic programming
just like in object-oriented programming, but when generic programming
is implemented through monomorphization, as it is in Rust, it can be
just as efficient as hand-implementing the combinations of policy
and code, while allowing for more policies.&lt;/p&gt;
&lt;p&gt;For example, if there were a platform where 4-byte chunks were split
into 2-byte chunks little endian, but 2-byte chunks were split into
1-byte chunks big endian, we could write a new policy for this platform
and all the existing code would support it.&lt;/p&gt;
&lt;p&gt;A much more complicated example of the policy pattern is &lt;code&gt;serde&lt;/code&gt;,
where the generated serializers and deserializers for each structure
are all polymorphic on what serialization format should be used. If a
new serialization format comes out with &lt;code&gt;serde&lt;/code&gt; support, all existing
&lt;code&gt;Serialize&lt;/code&gt; instances can then be used with the new format without
modification.&lt;/p&gt;
&lt;p&gt;Now, in practice, there are often processor instructions that do byte
swaps. The hardware uses an interface analogous to the hackish, conceptually
messy &lt;code&gt;to_be()&lt;/code&gt;, which at a hardware level makes sense because elegance of
abstraction is not as an important goal as performance. This converts
&lt;code&gt;0x12345678&lt;/code&gt; into &lt;code&gt;0x78563412&lt;/code&gt;, and similar. So, this implementation
is not actually what the policy would look like in a production context.
Nevertheless, the endianness argument could definitely be passed in by
a trait-constrained type parameter; the implementation would just be
more complicated.&lt;/p&gt;
&lt;h2 id=&#34;traits&#34;&gt;Traits&lt;/h2&gt;
&lt;p&gt;I mentioned before that &lt;code&gt;u32&lt;/code&gt; is not the only type that implements this
set of methods, this convention, this informal protocol of &lt;code&gt;to_be_bytes&lt;/code&gt;,
&lt;code&gt;to_le_bytes&lt;/code&gt;, etc.  This means that if we were writing in C++, we
would have enough from this informal protocol to write a function that
did something like &amp;ldquo;write this value in big endian twice, and little
endian twice, to different locations&amp;rdquo; that was agnostic to the type
provided, as long as it implemented this informal interface. It would
look something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;template &amp;lt;typename T&amp;gt;
void write_four_times(T val) {
    write_to_location_1(val.to_be_bytes());
    write_to_location_2(val.to_be_bytes());
    write_to_location_3(val.to_le_bytes());
    write_to_location_4(val.to_le_bytes());
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This would allow you to call &lt;code&gt;write_four_times&lt;/code&gt; on any type for
which that code made sense, as C++ templates are literally templates,
and the &lt;code&gt;T&lt;/code&gt; is filled in before type-checking. The protocol here
is implicit in the structure of the function &amp;ndash; it is compile-time
&lt;a href=&#34;https://en.wikipedia.org/wiki/Duck_typing#Templates_or_generic_types&#34;&gt;duck typing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Rust generic functions are type-checked before monomorphization, so
we can&amp;rsquo;t do this in Rust. Instead of defining &lt;code&gt;to_le_bytes()&lt;/code&gt; and
friends separately on each type, this function would require them
to be in a trait, maybe &lt;code&gt;EndianBytes&lt;/code&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn write_four_times&amp;lt;T: EndianBytes&amp;gt;(val: T) {
    write_to_location_1(&amp;amp;val.to_be_bytes());
    write_to_location_2(&amp;amp;val.to_be_bytes());
    write_to_location_3(&amp;amp;val.to_le_bytes());
    write_to_location_4(&amp;amp;val.to_le_bytes());
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;EndianBytes&lt;/code&gt; would have to define at least those methods:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;trait EndianBytes {
    fn to_be_bytes(self) -&amp;gt; [u8; ???];
    fn to_le_bytes(self) -&amp;gt; [u8; ???];
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unfortunately, as the &lt;code&gt;???&lt;/code&gt; shows, the different output arrays have
different lengths &amp;ndash; a &lt;code&gt;u16&lt;/code&gt; would be 2 bytes and a &lt;code&gt;u64&lt;/code&gt; 8 bytes &amp;ndash;
and so the Rust trait system at the time of this writing is (to my
knowledge) not powerful enough to represent this trait as is.  Instead,
it would have to return a slice, which introduces an additional run-time
value (the length) into the mix that we&amp;rsquo;d rather avoid in this
exercise on compile-time generic programming.&lt;/p&gt;
&lt;h2 id=&#34;run-time-endianness&#34;&gt;Run-Time Endianness&lt;/h2&gt;
&lt;p&gt;What if we want to make decisions about endianness at
run-time, say, because we are implementing DBus? This is,
as Linus Torvalds pointed out in one of his famously angry
&lt;a href=&#34;https://lkml.org/lkml/2015/4/22/628&#34;&gt;emails&lt;/a&gt;, a stupid idea for
a protocol, but we don&amp;rsquo;t always get to choose what protocol we
implement. Even though choosing one endianness and sticking to it would
have avoided the run-time cost of making a decision (which as Torvalds
points out is more than the cost of either decision), the developers
of DBus did not do that.  UTF-16 also didn&amp;rsquo;t &amp;ndash; it also does run-time
endianness adjustment with a sentinal character at the top of the text
block to indicate the endianness.&lt;/p&gt;
&lt;p&gt;The most obvious solution is to use the run-time parameterized
version we discussed towards the beginning of this post, and
have an &lt;code&gt;enum Endianness&lt;/code&gt; parameter. This would be parsed in each
message (or connection, or whatever duration of time endianness
is configured) and then passed through to all the serializing and
deserializing code, which would look something like our
original serialization example:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn serialize(&amp;amp;self, endianness: Endian) -&amp;gt; [u8; 12] {
    let res = [0u8; 12];
    (&amp;amp;mut res[0..4]).copy_from_slice(self.a.to_endian_bytes(endian));
    (&amp;amp;mut res[4..8]).copy_from_slice(self.b.to_endian_bytes(endian));
    (&amp;amp;mut res[8..12]).copy_from_slice(self.c.to_endian_bytes(endian));
}

pub fn serialize_old_version(&amp;amp;self) -&amp;gt; [u8; 12] {
    self.serialize(Endian::Big)
}

pub fn serialize_new_version(&amp;amp;self) -&amp;gt; [u8; 12] {
    self.serialize(Endian::Little)
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can do better than that, though. This has one copy of the serialization
code in the source, and one copy in the binary. What we could do instead,
is expand the more sophisticated compile-time version of the serialization
code, and move the &lt;code&gt;match&lt;/code&gt; into a wrapper serialize method:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;fn serialize_impl&amp;lt;T: EndiannessTrait&amp;gt;(&amp;amp;self) -&amp;gt; [u8; 12] {
    let res = [0u8; 12];
    (&amp;amp;mut res[0..4]).copy_from_slice(self.a.to_endian_bytes::&amp;lt;T&amp;gt;());
    (&amp;amp;mut res[4..8]).copy_from_slice(self.b.to_endian_bytes::&amp;lt;T&amp;gt;());
    (&amp;amp;mut res[8..12]).copy_from_slice(self.c.to_endian_bytes::&amp;lt;T&amp;gt;());
}

pub fn serialize(&amp;amp;self, endianness: EndiannessEnum) -&amp;gt; [u8; 12] {
    match endianness {
        EndiannessEnum::Big =&amp;gt; self.serialize_impl::&amp;lt;BigEndian&amp;gt;(),
        EndiannessEnum::Little =&amp;gt; self.serialize_impl::&amp;lt;LittleEndian&amp;gt;(),
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This generates two serializers from one serializer function (thus
mitigating the biggest problem with code duplication &amp;ndash; that of
maintainability), and makes the run-time decision further up
in the call tree. This ability &amp;ndash; to adjust between finer-grained
run-time decisions and duplication of run-time code &amp;ndash; is one of
the greatest powers of C++ and of Rust. We can effectively &amp;ndash; in the DBus
case &amp;ndash; create two entire DBus deserializers &amp;ndash; one for little-endian,
one for big endian &amp;ndash; and then decide between the two deserializers
at run-time on a per-message basis, which, because fewer run-time
decisions are being made, will be much more efficient than making the
run-time deserialization decision at every deserialization site.&lt;/p&gt;
&lt;p&gt;Of course, for serialization we can simply write one serializer and
always generate little-endian DBus messages.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>C&#43;&#43; Move Semantics Considered Harmful (Rust is better)</title>
      <link href="https://www.thecodedmessage.com/posts/cpp-move/" />
      <id>https://www.thecodedmessage.com/posts/cpp-move/</id>
      <updated>2021-11-03T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;This post is part of my &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;series&lt;/a&gt;
comparing C++ to Rust, which I introduced
with a &lt;a href=&#34;https://www.thecodedmessage.com/posts/hello-rust/&#34;&gt;discussion of C++ and Rust syntax&lt;/a&gt;. In
this post, I discuss move semantics. This post is framed around the
way moves are implemented in C++, and the fundamental problem with
that implementation, With that context, I shall then explain how Rust
implements the same feature. I know that move semantics in Rust are often
confusing to new Rustaceans &amp;ndash; though not as confusing as move semantics
in C++ &amp;ndash; and I think an exploration of how move semantics work in C++
can be helpful in understanding why Rust is designed the way it is,
and why Rust is a better alternative to C++.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;This post is part of my &lt;a href=&#34;https://www.thecodedmessage.com/tags/rust-vs-c++/&#34;&gt;series&lt;/a&gt;
comparing C++ to Rust, which I introduced
with a &lt;a href=&#34;https://www.thecodedmessage.com/posts/hello-rust/&#34;&gt;discussion of C++ and Rust syntax&lt;/a&gt;. In
this post, I discuss move semantics. This post is framed around the
way moves are implemented in C++, and the fundamental problem with
that implementation, With that context, I shall then explain how Rust
implements the same feature. I know that move semantics in Rust are often
confusing to new Rustaceans &amp;ndash; though not as confusing as move semantics
in C++ &amp;ndash; and I think an exploration of how move semantics work in C++
can be helpful in understanding why Rust is designed the way it is,
and why Rust is a better alternative to C++.&lt;/p&gt;
&lt;p&gt;I am by far not the first person to discuss this topic, but I intend:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;to discuss it thoroughly enough to contribute to the conversation&lt;/li&gt;
&lt;li&gt;to nevertheless discuss it in such a way that those
familiar with systems programming, but unfamiliar with either C++
or move semantics, can understand it, starting from first principles&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;modern-c&#34;&gt;Modern C++&lt;/h2&gt;
&lt;p&gt;First, some background.&lt;/p&gt;
&lt;p&gt;In 2011, C++ finally fixed a set of long-standing deficits in the
programming language with the shiny new C++11 standard, bringing it into
the modern era. Programmers enthusiastically pushed their companies to
allow them to migrate their codebases, champing at the bit to be able to
use these new features. Writers to this day talk about &amp;ldquo;modern C++,&amp;rdquo;
with the cut-off being 2011. Programmers who only used C++ pre-C++11 are
told that it is a new programming language, the best version of its old
self, worth a complete fresh try.&lt;/p&gt;
&lt;p&gt;There were a lot of new features to be excited about. C++ standard
threads were added then &amp;ndash; and thread standardization was indeed good,
though anyone who wanted to use threads before likely had their choice
of good libraries for their platform.  Closures were also very exciting,
especially for people like me who came from functional programming, but
to be honest, closures were just syntactic sugar for existing patterns
of boilerplate that could be readily used to write function objects.&lt;/p&gt;
&lt;p&gt;Indeed, the real excitement at the time, certainly the one my colleagues
and I were most excited about, was move semantics. To explain why this
feature was so important, I&amp;rsquo;ll need to talk a little about the C++
object model, and the problem that move semantics exist to solve.&lt;/p&gt;
&lt;h2 id=&#34;value-semantics&#34;&gt;Value Semantics&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start by talking about a primitive type in C++: &lt;code&gt;int&lt;/code&gt;. Objects &amp;ndash;
in C++ standard parlance, &lt;code&gt;int&lt;/code&gt; values are indeed considered objects &amp;ndash;
of type &lt;code&gt;int&lt;/code&gt; only take up a few bytes of storage, and so copying them
has always been very cheap. When you assign an &lt;code&gt;int&lt;/code&gt; from one variable
to another, it is copied. When you pass it to a function, it is copied:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;print_i&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; arg) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arg &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; arg &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; foo; &lt;span style=&#34;color:#75715e&#34;&gt;// copy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;// foo gets 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; bar &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl; &lt;span style=&#34;color:#75715e&#34;&gt;// bar is still 3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print_i(foo); &lt;span style=&#34;color:#75715e&#34;&gt;// prints 4+3 ==&amp;gt; 7
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; foo &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl; &lt;span style=&#34;color:#75715e&#34;&gt;// foo is still 4
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, every variable of type &lt;code&gt;int&lt;/code&gt; acts independently of each
other when mutated, which is how primitive types like &lt;code&gt;int&lt;/code&gt; work in many
programming languages.&lt;/p&gt;
&lt;p&gt;In the C++ version of object-oriented programming, it was decided that
values of custom, user-defined types would have the same semantics, that
they would work the same way as the primitive types. So for C++ strings:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; foo; &lt;span style=&#34;color:#75715e&#34;&gt;// copy (!)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;__&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bar &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;!!&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; foo &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl; &lt;span style=&#34;color:#75715e&#34;&gt;// foo is &amp;#34;foo__&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;cout &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; bar &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;endl; &lt;span style=&#34;color:#75715e&#34;&gt;// bar is &amp;#34;foo!!&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This means that whenever we assign a string to a new variable, or
pass it to a function, a copy is made. This is important, because
the &lt;code&gt;std::string&lt;/code&gt; object proper is just a handle, a small structure
that manages a larger memory allocation on the heap, where the
actual string data is stored. Each new &lt;code&gt;std::string&lt;/code&gt; that is made
via copy requires allocating a new heap allocation, a relatively
expensive operation in performance.&lt;/p&gt;
&lt;p&gt;This would cause a problem when we want to pass a &lt;code&gt;std::string&lt;/code&gt; to a
function, just like an &lt;code&gt;int&lt;/code&gt;, but don&amp;rsquo;t want to actually make a copy
of it. But C++ has a feature that helps with that: &lt;code&gt;const&lt;/code&gt; references.
Details of the C++ reference system are a topic for another post, but
&lt;code&gt;const&lt;/code&gt; references allow a function to operate on the &lt;code&gt;std::string&lt;/code&gt;
without the need for a copy, but still promising not to change the
original value.&lt;/p&gt;
&lt;p&gt;The feature is available for both &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;std::string&lt;/code&gt;; the principle
that they&amp;rsquo;re treated the same is preserved. But for the sake of performance,
&lt;code&gt;int&lt;/code&gt;s are passed by value, and &lt;code&gt;std::string&lt;/code&gt;s are passed by &lt;code&gt;const&lt;/code&gt;
reference in the same situation. In practice, this dilutes the benefit
of treating them the same, as in practice the function signatures
are different if we don&amp;rsquo;t want to trigger spurious expensive deep copies:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; bar);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;bar);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you instead declare the function &lt;code&gt;foo&lt;/code&gt; like you would with an &lt;code&gt;int&lt;/code&gt;,
you get a poorly performing deep copy. The default is something you
probably don&amp;rsquo;t want:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string bar);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo2&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;bar);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string bar(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// Make one heap allocation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(bar); &lt;span style=&#34;color:#75715e&#34;&gt;// Make another heap allocation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo2(bar); &lt;span style=&#34;color:#75715e&#34;&gt;// No copy is made
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is all part of &amp;ldquo;pre-modern&amp;rdquo; C++, but already we&amp;rsquo;re seeing negative
consequences of the decision to treat &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;std::string&lt;/code&gt; as identical
when they are not, a decision that will get more gnarly when applied to
moves. This is why Rust has the &lt;code&gt;Copy&lt;/code&gt; trait to mark types like &lt;code&gt;i32&lt;/code&gt;
(the Rust equivalent of &lt;code&gt;int&lt;/code&gt;) as being copyable, so that they can be
passed around freely, while requiring an explicit call to &lt;code&gt;clone()&lt;/code&gt;
for types like &lt;code&gt;String&lt;/code&gt; so we know we&amp;rsquo;re paying the cost of a deep copy,
or else an explicit indication that we&amp;rsquo;re passing by reference:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(bar: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Implementation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo2&lt;/span&gt;(bar: &lt;span style=&#34;color:#66d9ef&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;str&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Implementation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hi&amp;#34;&lt;/span&gt;.to_string();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(bar.clone());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo2(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;bar);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The third option in Rust is to move, but we&amp;rsquo;ll discuss that after
we discuss moves in C++.&lt;/p&gt;
&lt;h2 id=&#34;copy-deletes-and-moves&#34;&gt;Copy-Deletes and Moves&lt;/h2&gt;
&lt;p&gt;C++ value semantics break down even more when we do need the
function to hold onto the value. References are only valid as long
as the original value is valid, and sometimes a function needs it
to stay alive longer. Taking by reference is not an option when
the object (whether &lt;code&gt;int&lt;/code&gt; or &lt;code&gt;std::string&lt;/code&gt;) is being added to a vector
that will outlive the original object:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; vi;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; vs;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    foo &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vi.push_back(foo);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#75715e&#34;&gt;// foo goes out of scope, vi lives on
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi!&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bar &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34; Joe!&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vs.push_back(bar);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#75715e&#34;&gt;// bar goes out of scope, vs lives on
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, to add this string to the vector, we must first make an
allocation corresponding to the object contained in the variable
&lt;code&gt;bar&lt;/code&gt;, and then must make a new allocation for the object that lives in
&lt;code&gt;vs&lt;/code&gt;, and then copy all the data.&lt;/p&gt;
&lt;p&gt;Then, when &lt;code&gt;bar&lt;/code&gt; goes out of scope, its destructor is called, as is
done automatically whenever an object with a destructor goes out
of scope. This allows &lt;code&gt;std::string&lt;/code&gt; to free its heap allocation.&lt;/p&gt;
&lt;p&gt;Which means we copied an allocation into a new heap allocation, just to free
the original allocation. Copying an allocation and freeing the old one
is equivalent to just re-using the old allocation, just slower. Wouldn&amp;rsquo;t
it make more sense to make the string in the vector just refer to the
same heap allocation that &lt;code&gt;bar&lt;/code&gt; formerly did?&lt;/p&gt;
&lt;p&gt;Such an operation is referred to as a &amp;ldquo;move,&amp;rdquo; and the original C++ &amp;ndash;
pre C++11 &amp;ndash; didn&amp;rsquo;t support them. This was possibly because they didn&amp;rsquo;t
make sense for &lt;code&gt;int&lt;/code&gt;s, and so they were not added for objects that were
trying to act like &lt;code&gt;int&lt;/code&gt;s &amp;ndash; but on the other hand, destructors were
supported and &lt;code&gt;int&lt;/code&gt;s don&amp;rsquo;t need to be destructed.&lt;/p&gt;
&lt;p&gt;In any case, moves were not supported. And so, objects that managed
resources &amp;ndash; in this case, a heap allocation, but other resources could
apply as well &amp;ndash; could not be put onto vectors or stored in collections
directly without a copy and delete of whatever resource was being managed.&lt;/p&gt;
&lt;p&gt;Now, there were ways to handle this in pre-C++11 days. You could add
an indirection, and make a heap allocation to contain the &lt;code&gt;std::string&lt;/code&gt;
object, which is only a small object with a pointer to another allocation,
but would at least let you pass around a &lt;code&gt;std::string *&lt;/code&gt; which is a
raw pointer that would not trigger all these copies by automatically
managing the heap allocation with this façade of value semantics. Or
you could manually manage a C-style string with &lt;code&gt;char *&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But the most ergonomic, clear &lt;code&gt;std::vector&amp;lt;std::string&amp;gt;&lt;/code&gt; could not be
used without performance degradation. Worse, if the vector ever needed
to be resized, and had to itself switch to a different allocation, it
would have to copy all those &lt;code&gt;std::string&lt;/code&gt; objects internally and
delete the originals, N useless reallocations.&lt;/p&gt;
&lt;p&gt;As a demonstration of this, I wrote a &lt;a href=&#34;https://www.thecodedmessage.com/string_example/string.cpp&#34;&gt;sample
program&lt;/a&gt; with a vastly simplified
version of &lt;code&gt;std::string&lt;/code&gt;, that tracks how many allocations it makes.
It allows C++11-style moves to be enabled or disabled, and then it
takes all the command line arguments, creates &lt;code&gt;string&lt;/code&gt; objects out
of them, and puts them in a vector. For 8 command line arguments,
the version with move made, as you might expect, 8 allocations,
whereas the version without the move, that just put these strings
into a vector, made 23. Each time a string was added to a vector,
a spurious allocation was made, and then N spurious allocations
had to be made each time the vector doubled.&lt;/p&gt;
&lt;p&gt;This problem is purely an artifact of the limitations of the tools
provided by C++ to encapsulate and automatically manage memory, RAII and
&amp;ldquo;value semantics.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Consider this snippet of code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Pre-C++11, without moves
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; vec;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{ &lt;span style=&#34;color:#75715e&#34;&gt;// This might take place inside another function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// Using local block scope for simplicity
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi!&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vec.push_back(foo);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello!&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vec.push_back(bar);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Use the vector
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we didn&amp;rsquo;t use this &lt;code&gt;string&lt;/code&gt; class, we would then
have not done a copy, just to free the original allocation. We would
have simply put the pointer into the vector. We would then have been
responsible for freeing all the allocations &amp;ndash; once &amp;ndash; when we&amp;rsquo;re done:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Manually written equivalent
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&amp;gt;&lt;/span&gt; vec;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// strdup, a POSIX call, makes a new allocation and copies a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// string into it, here used to turn a static string into one
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// on the heap. We will assume we have a reason to store it
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// on the heap -- perhaps we did more manipulation in the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// real application to generate the string.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// The allocation is necessary to be the direct equivalent of
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// `vec.push_back(&amp;#34;Hi&amp;#34;)` or even `vec.emplace_back(&amp;#34;Hi&amp;#34;)` for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// a `std::vector&amp;lt;std::string&amp;gt;, because that data structure has
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// the invariant that all strings in the vector must have their
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// own heap allocation (assuming no small string optimization,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// which many strings are ineligible for).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; strdup(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vec.push_back(foo);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; strdup(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vec.push_back(bar);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Use the vector
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Then, later, when we are done with the vector, free all the elements once
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;c: vec) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    free(c);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The copy version of the C++ code instead does &amp;ndash; after de-sugaring the
RAII and value semantics and inlining &amp;ndash; something that no programmer
would ever write manually, something equivalent to this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Desugaring of pre-C++11 version of code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&amp;gt;&lt;/span&gt; vec;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; strdup(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vec.push_back(strdup(foo)); &lt;span style=&#34;color:#75715e&#34;&gt;// Why the additional allocate-and-copy?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    free(foo); &lt;span style=&#34;color:#75715e&#34;&gt;// Because the destructor of foo will free the original
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; strdup(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vec.push_back(strdup(bar));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    free(bar);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// Use the vec
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;c: vec) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    free(c);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;C++ without move semantics fails to reach its goal of zero-cost abstraction.
The version with the abstraction, with the value semantics, compiles to code
less efficient than any code someone would write manually, because what
we really want is to allocate the allocation while it&amp;rsquo;s a local variable
&lt;code&gt;foo&lt;/code&gt;, use the same allocation on the vector, and then only free it on the
vector.&lt;/p&gt;
&lt;p&gt;The abstractions of only supporting &amp;ldquo;copy&amp;rdquo; and &amp;ldquo;destruct&amp;rdquo; mean that the
destructor of the variable &lt;code&gt;foo&lt;/code&gt; must be called when &lt;code&gt;foo&lt;/code&gt; goes out of
scope. This means that the &amp;ldquo;copy&amp;rdquo; operation must make an independent
allocation, as it cannot control when the original goes out of scope,
or will be replaced with another value.  If we had instead re-used the
same allocation, it would be freed by &lt;code&gt;foo&lt;/code&gt;s destructor.&lt;/p&gt;
&lt;p&gt;But copying just to destroy the original is silly &amp;ndash; silly and
ill-performant. What any programmer would naturally write in that
situation results in a &amp;ldquo;move&amp;rdquo;. So this gap &amp;ndash; and it was a huge gap &amp;ndash;
in C++ value semantics was filled in C++11 when they added a &amp;ldquo;move&amp;rdquo;
operation.&lt;/p&gt;
&lt;p&gt;Because of this addition, using objects with value semantics that managed
resources became possible. It also became possible to use objects with
value semantics for resources that could not meaningfully be copied,
like unique ownership of an object or a thread handle, while still
being able to get the advantages of putting such objects in collections
and, well, moving them. Shops that previously had to work around value
semantics for performance reasons could now use them directly.&lt;/p&gt;
&lt;p&gt;It is not, therefore, surprising that this was for many the most exciting
change in C++11.&lt;/p&gt;
&lt;h2 id=&#34;how-move-is-implemented-in-c&#34;&gt;How Move Is Implemented in C++&lt;/h2&gt;
&lt;p&gt;But for now, let&amp;rsquo;s put ourselves in the place of the language designers
who designed this new move operation. What should this move operation
look like? How could we integrate it into the rest of C++?&lt;/p&gt;
&lt;p&gt;Ideally, we would want it to output &amp;ndash; after inlining &amp;ndash; exactly the
code that we would expect to write manually. When &lt;code&gt;foo&lt;/code&gt; is moved into the
vector, the original allocation must not freed. Instead, it is only freed
when the vector itself is freed. This is an absolute necessity to solve
the problem as we must remove a free in order to remove the allocation,
but we also cannot leak memory. If there is to be exactly one allocation,
there must be exactly one deallocation.&lt;/p&gt;
&lt;p&gt;Calls to &lt;code&gt;free&lt;/code&gt; (or &lt;code&gt;delete[]&lt;/code&gt; in my example program) are made in the
destructor, so the most straight-forward way to go forward is to say
that the destructor should only be called when the vector is destroyed,
but not when &lt;code&gt;foo&lt;/code&gt; goes out of scope. If &lt;code&gt;foo&lt;/code&gt; is moved onto the vector,
then the compiler should take note that it has been moved from, and simply
not call the destructor. The move should be treated as having already
destroyed the object, as an operation that accomplishes both initialization
of the new object (the string on the vector) from the original object and the
destruction of the original object.&lt;/p&gt;
&lt;p&gt;This notion is called &amp;ldquo;destructive move,&amp;rdquo; and it is how moves are done
in Rust, but it is not what C++ opted for.  In Rust, the compiler would
simply not output a destructor call (a &amp;ldquo;drop&amp;rdquo; in Rust) for &lt;code&gt;foo&lt;/code&gt; because
it has been moved from. But, in fact, the C++ compiler still does. In
destructive move semantics, the compiler would not allow &lt;code&gt;foo&lt;/code&gt; to be
read from after the move, but in fact, the C++ compiler still does,
not just for the destructor, but for any operation.&lt;/p&gt;
&lt;p&gt;So how is the deallocation avoided, if the compiler doesn&amp;rsquo;t remove it
in this situation? Well, there is a decision to make here.  If an object
has been moved from, no deallocation should be performed. If it has not,
a deallocation should be performed. Rust makes this decision at compile-time
(with rare exceptions where it has to add a &amp;ldquo;drop flag&amp;rdquo;),
but C++ makes it at run-time.&lt;/p&gt;
&lt;p&gt;When you write the code that defines what it means to move from
an object in C++, you must make sure the original object is in a
run-time state where the destructor will still be called on it, and
will still succeed. And, since we established already that we must save
a deallocation by moving, that means that the destructor must make a
run-time decision as to whether to deallocate or not.&lt;/p&gt;
&lt;p&gt;The more C-style post-inlining code for our example would then look
something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&amp;gt;&lt;/span&gt; vec;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; strdup(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vec.push_back(foo);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    foo &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nullptr&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (foo &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nullptr&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        free(foo);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; strdup(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi!&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    vec.push_back(bar);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bar &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nullptr&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (bar &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nullptr&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        free(bar);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This null check is hidden by the fact that in C++, &lt;code&gt;free&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt;
and friends are defined to be no-ops on null, but it still exists.
And while the check might be very cheap compared to the cost of calling
&lt;code&gt;free&lt;/code&gt;, it might not be cheap when things are moved in a tight loop,
where &lt;code&gt;free&lt;/code&gt; is never actually called. That is to say, this
run-time check is not cheap compared to the cost of &lt;em&gt;not&lt;/em&gt; calling &lt;code&gt;free&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So, given the semantics of move in C++, it results in code that is not
the same as &amp;ndash; and not as performant as &amp;ndash; the equivalent hand-written
C-style code, and therefore it is not a zero-cost abstraction, and
doesn&amp;rsquo;t live up to the goals of C++.&lt;/p&gt;
&lt;p&gt;Now, it looks like the optimizer should be able to clean up an adjacent
set to null and check for null, but not all examples are as simple as this
one, and, like in many situations where the abstraction relies on the
optimizer, the optimizer doesn&amp;rsquo;t always get it.&lt;/p&gt;
&lt;h2 id=&#34;arguing-semantics&#34;&gt;Arguing Semantics&lt;/h2&gt;
&lt;p&gt;But that performance hit is small, and it is usually possible to optimize
out. If that were the only problem with C++ move semantics, I might find
it annoying, but ultimately I&amp;rsquo;d say, like about many things in about both
C++ and Rust, something like: Well, this decision was made, remember to
profile, and if you absolutely have to make sure the optimizer got it
in a particular instance, check the assembly by hand.&lt;/p&gt;
&lt;p&gt;But there&amp;rsquo;s a few further consequences of that decision.&lt;/p&gt;
&lt;p&gt;First off, the resource might not be a memory allocation, and null pointers
might not be an appropriate way to indicate that that resource doesn&amp;rsquo;t
exist. This responsibility of having some run-time indication of what
resources need to be freed &amp;ndash; rather than a one-to-one correspondence
between objects and resources &amp;ndash; is left up to the implementors of classes.
For heap allocations, it is made relatively easy, but the implementor
of the class is still responsible for re-setting the original object.
In my example, the move constructor reads:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;string(string &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;other) &lt;span style=&#34;color:#66d9ef&#34;&gt;noexcept&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    m_len &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; other.m_len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    m_str &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; other.m_str;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    other.m_str &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;nullptr&lt;/span&gt;; &lt;span style=&#34;color:#75715e&#34;&gt;// Don&amp;#39;t forget to do this
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The move constructor has two responsibilities, where a destructive
version would only have one: It must set up state for the new object,
and it must set up a valid &amp;ldquo;moved from&amp;rdquo; state for the old object.
That second obligation is a direct consequence of non-destructive moves,
and provides the programmer with another chance to mess something up.&lt;/p&gt;
&lt;p&gt;In fact, since destructive moves can almost always be implemented by
just copying the memory (and leaving the original memory as garbage
data as the destructor will not be called on it), a default move
constructor would correctly cover the vast majority of implementations,
creating even fewer opportunities to introduce bugs.&lt;/p&gt;
&lt;p&gt;But in C++, the moved-from state also has obligations. The destructor
has to know at run-time not to reclaim any resources if the object no
longer has any, but in general, there is no rule that moved-from objects
must immediately be destroyed. The programming language has explicitly
decided not to enforce such a rule, and so, to be properly safe, moved-from
objects must be considered &amp;ndash; and must be &amp;ndash; valid values for those objects.&lt;/p&gt;
&lt;p&gt;This means that any object that manages a resource now must manage either
1 or 0 copies of that resource. Collections are easy &amp;ndash; moved from collections
can be made equivalent to the &amp;ldquo;empty&amp;rdquo; collection that has no element. For
things like thread handles or file handles, this means that you can have
a file handle with no corresponding file. Optionality is imported to all
&amp;ldquo;value types.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;So, smart pointer types that manage single-ownership heap allocations, or
any sort of transferrable ownership of heap allocations, now of necessity
must be nullable. Nullable pointers are a serious cause of errors, as
often they are used with the implicit contract that they will not be null,
but that contract is not actually represented in the type. Every time a
nullable pointer is passed around, you have a potential miscommunication
of whether &lt;code&gt;nullptr&lt;/code&gt; is a valid value, one that will cause some sort
of error condition, or one that may lead to undefined behavior.&lt;/p&gt;
&lt;p&gt;C++ move semantics of necessity perpetuate this confusion. Non-nullable
smart pointers are unimplementable in C++, not if you want them to be
moveable as well.&lt;/p&gt;
&lt;h2 id=&#34;move-complicatedly&#34;&gt;Move, Complicatedly&lt;/h2&gt;
&lt;p&gt;This leads me to Herb Sutter&amp;rsquo;s
&lt;a href=&#34;https://herbsutter.com/2020/02/17/move-simply/&#34;&gt;explanation of C++ move semantics&lt;/a&gt; from his blog. I respect Herb Sutter greatly as someone explaining
C++, and his materials helped me learn C++ and teach it. An explanation
like this is really useful if programming in C++ is what you have to do.&lt;/p&gt;
&lt;p&gt;However, I am instead investigating whether C++&amp;rsquo;s move semantics are
reasonable, especially in comparison to programming languages like Rust
which do have a destructive move. And from that point of view, I think
this blog post, and its necessity, serve as a good illustration of the
problems with C++&amp;rsquo;s move semantics.&lt;/p&gt;
&lt;p&gt;I shall respond to specific excerpts from the post.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;C++ “move” semantics are simple, and unchanged since C++11. But they
are still widely misunderstood, sometimes because of unclear teaching
and sometimes because of a desire to view move as something else instead
of what it is.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Given the definition he&amp;rsquo;s about to give of C++ move semantics, I
think this is unfair. The goal of move is clear: to allow resources to be
transferred when copying would force them to be duplicated. It is obvious
from the name. However, the semantics as the language defines them,
while enabling that goal, are defined without reference to that goal.&lt;/p&gt;
&lt;p&gt;This is doomed to lead to confusion, no matter how good the teaching is.
And it is desirable to try to understand the semantics as they connect
to the goal of the feature.&lt;/p&gt;
&lt;p&gt;To explain what I mean, see the definition he then gives for moving:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In C++, copying or moving from an object &lt;code&gt;a&lt;/code&gt; to an object &lt;code&gt;b&lt;/code&gt; sets &lt;code&gt;b&lt;/code&gt; to
&lt;code&gt;a&lt;/code&gt;’s original value. The only difference is that copying from &lt;code&gt;a&lt;/code&gt; won’t
change &lt;code&gt;a&lt;/code&gt;, but moving from &lt;code&gt;a&lt;/code&gt; might.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a fair statement of C++&amp;rsquo;s move semantics as defined. But it has
a disconnect with the goals.&lt;/p&gt;
&lt;p&gt;In this definition, we are discussing the assignment written as &lt;code&gt;b = a&lt;/code&gt;
or as &lt;code&gt;b = std::move(a)&lt;/code&gt;.  The reason why moving might change &lt;code&gt;a&lt;/code&gt;, as
we&amp;rsquo;ve discussed, is that &lt;code&gt;a&lt;/code&gt; might contain a resource. Moving indicates
that we do not wish to copy resources that are expensive or impossible
to copy, and that in exchange for this ability, we give up the right to
expect that &lt;code&gt;a&lt;/code&gt; retain its value.&lt;/p&gt;
&lt;p&gt;This definition is the correct one to use for reasoning about C++
programs, but it is not directly connected to why you might want
to use the feature at all. It is natural that programmers would
want to be able to reason about a feature in a way that aligns with
its goals.&lt;/p&gt;
&lt;p&gt;The goal of this post is to obscure the goal, and to treat
move as if it were a pure optimization of copy, which will not
help a programmer understand why &lt;code&gt;a&lt;/code&gt;&amp;rsquo;s value might change, or why
move-only types like &lt;code&gt;std::unique_ptr&lt;/code&gt; exist.&lt;/p&gt;
&lt;p&gt;The explanation of the goal of this operation is reserved in this post
for the section entitled &amp;ldquo;advanced notes for type implementors&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Of course, almost all C++ programmers in a sufficiently large project
have to become &amp;ldquo;type implementors&amp;rdquo; to understand and maintain custom
types, if not to write fresh implementations of them, so I think
most professional programmers should be reading these notes, and
so I think it&amp;rsquo;s unfair to call them advanced. But beyond that,
this explanation is core to why the operation exists, and the only
explanation for why move-only types exist, which all C++ programmers
will have to use:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For types that are move-only (not copyable), move is C++’s closest
current approximation to expressing an object that can be cheaply moved
around to different memory addresses, by making at least its value
cheap to move around.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He follows up with an acknowledgement that destructive moves are
a theoretical possibility:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;(Other not-yet-standard proposals to go further
in this direction include ones with names like “relocatable” and
“destructive move,” but those aren’t standard yet so it’s
premature to talk about them.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For his purposes, this is extremely fair, but since my purposes are to
compare C++ to Rust and other programming languages which have destructive
moves, it is not premature for me to talk about them.&lt;/p&gt;
&lt;p&gt;This gets more interesting in the Q&amp;amp;A.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;How can moving from an object not change its state?&lt;/p&gt;
&lt;p&gt;For example, moving an int doesn’t change the source’s value because
an int is cheap to copy, so move just does the same thing as copy. Copy
is always a valid implementation of move if the type didn’t provide
anything more efficient.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Indeed, for reasons of consistency and generic programming, move is
defined on all types that can be moved or copied, even types that don&amp;rsquo;t
implement move differently than copy.&lt;/p&gt;
&lt;p&gt;What makes this confusing in C++, however, is that types that manage
resources might be written without an implementation of move. They might
pre-date the move feature, or their implementor might not have understood
move well enough to implement them, or there might be a technical reason
why moving couldn&amp;rsquo;t be implemented in a way that elides the resource
duplication. For these types, a move falls back on a copy, even if the
copy does significant work. This can be surprising to the programmer,
and surprises in programming are never good. More direly, there
is no warning when this happens, because the notion of resource management
is not referenced in the semantics.&lt;/p&gt;
&lt;p&gt;In Rust, a move is always implemented by copying the data in the object
itself and then not destructing the original object, and never by copying
resources managed by the object, or running any custom code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But what about the “moved-from” state, isn’t it special somehow?&lt;/p&gt;
&lt;p&gt;No. The state of a after it has been moved from is the same as the
state of a after any other non-const operation. Move is just another
non-constfunction that might (or might not) change the value of the
source object.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I disagree in practice. For objects that use move as intended, to avoid
copying resources, move will (at least usually) drain its resource. This
means that an object that often manages a resource will enter a state in
which it is not managing a resource. That state is special, because it is
the state when a resource-managing object is doing something other than
its normal job, and is not managing a resource. This is not a &amp;ldquo;special
state&amp;rdquo; by any rigorous definition, but is guaranteed to be intuitively
special by virtue of being resource-free. (It is also a special state
in that the value is unspecified in general, whereas most of the time,
the value is specified.)&lt;/p&gt;
&lt;p&gt;Collections can, as I said before, get away with becoming the
empty collection in this scenario, but even for those, the empty
state is special: It is the only state that can be represented without
holding a resource. And many other types of objects cannot even
do this. &lt;code&gt;std::unique_ptr&lt;/code&gt;&amp;rsquo;s moved-from state is the null pointer,
and without these move semantics, it would be possible to design a
&lt;code&gt;std::unique_ptr&lt;/code&gt; that did not have a null state.&lt;/p&gt;
&lt;p&gt;Once &lt;code&gt;std::unique_ptr&lt;/code&gt; is forced to be allowed to have null values, it
makes sense that there be other ways to create a null &lt;code&gt;std::unique_ptr&lt;/code&gt;,
e.g. by default-constructing it. But it is the design of move semantics
that force it to have a null value in the first place.&lt;/p&gt;
&lt;p&gt;Put another way: &lt;code&gt;std::unique_ptr&lt;/code&gt; and thread handles are therefore
collections of 0 or 1 heap allocation handles or thread handles, and
once defined that way, the &amp;ldquo;empty&amp;rdquo; state is not special, but it is move
semantics that force them to be defined that way.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Does “but unspecified” mean the object’s invariants might not hold?&lt;/p&gt;
&lt;p&gt;No. In C++, an object is valid (meets its invariants) for its entire
lifetime, which is from the end of its construction to the start of its
destruction&amp;hellip;. Moving from an object does not end its
lifetime, only destruction does, so moving from an object does not make
it invalid or not obey its invariants.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is true, as discussed above. The moved-from object must be able to
be destructed, and there is nothing stopping a programmer for instead
doing something else with it. Given that, it must be in some state that
its operations can reckon with. But that state is not necessarily
one that would be valid if move semantics didn&amp;rsquo;t force its conclusion,
and so again, we are close to the problem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Does “but unspecified” mean the only safe operation on a moved-from
object is to call its destructor?&lt;/p&gt;
&lt;p&gt;No.&lt;/p&gt;
&lt;p&gt;Does “but unspecified” mean the only safe operation on a moved-from
object is to call its destructor or to assign it a new value?&lt;/p&gt;
&lt;p&gt;No.&lt;/p&gt;
&lt;p&gt;Does “but unspecified” sound scary or confusing to average
programmers?&lt;/p&gt;
&lt;p&gt;It shouldn’t, it’s just a reminder that the value might have changed,
that’s all. It isn’t intended to make “moved-from” seem mysterious
(it’s not).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I disagree firmly with the answer to the last question. &amp;ldquo;Unspecified&amp;rdquo;
values are extremely scary, especially to programmers on team projects,
because it means that the behavior of the program is subject to arbitrary
change, but that change will not be considered breaking.&lt;/p&gt;
&lt;p&gt;For example, &lt;code&gt;std::string&lt;/code&gt; does not make any promises about the contents
of a moved-from string. However, a programmer &amp;ndash; even a senior programmer
&amp;ndash; may, instead of consulting the documentation, write a test program
to find out what the value is of a moved-from string. Seeing an empty
string, the programmer might write a
&lt;a href=&#34;https://www.thecodedmessage.com/string_example/split.cpp&#34;&gt;program&lt;/a&gt; that relies on the string
being empty:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;split_into_chunks(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;in) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;vector&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; res;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;string acc;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; c: in) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (count &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            res.push_back(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;move(acc));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// Don&amp;#39;t need to clear string.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// I checked and it&amp;#39;s empty.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        acc &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; c;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, you should not do that. A later version of &lt;code&gt;std::string&lt;/code&gt;
might implement the small string optimization, where strings of
below a certain size are not stored in an expensive-to-copy heap
resource, but in the actual object itself. In that situation, it would
be reasonable to implement move as a copy, which is allowed, and then
this program would no longer do the same thing.&lt;/p&gt;
&lt;p&gt;But this is a surprise. This is a result of the &amp;ldquo;unspecified value.&amp;rdquo;
And so while it may, strictly speaking, be &amp;ldquo;safe&amp;rdquo; to do things
with a moved-from object other than destruct them or assign to them,
in practice, without documentation to the contrary making stronger
guarantees, the only way to get &amp;ldquo;not surprising&amp;rdquo; behavior is to
greatly limit what you do with moved-from objects.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What about objects that aren’t safe to be used normally after being moved
from?&lt;/p&gt;
&lt;p&gt;They are buggy&amp;hellip;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By this definition, &lt;code&gt;std::unique_ptr&lt;/code&gt; should likely be considered buggy,
as null pointers cannot be used &amp;ldquo;normally&amp;rdquo;. Similarly, a &lt;code&gt;std::thread&lt;/code&gt;
object that does not represent a thread handle. It is only by stretching
the definition of &amp;ldquo;used normally&amp;rdquo; to include these special &amp;ldquo;empty values&amp;rdquo;
that &lt;code&gt;std::unique_ptr&lt;/code&gt; gets to claim to not be buggy under that definition,
although a null pointer simply cannot be used the way a normal pointer
can.&lt;/p&gt;
&lt;p&gt;Again, this attitude, that a null pointer is a normal pointer, that an
empty thread handle is a normal type of thread handle, is adaptive to
programming C++. But it will inevitably exist in a programmer&amp;rsquo;s blind
spot, as null pointers always have. The &amp;ldquo;not null&amp;rdquo; invariant is often
expressed implicitly. Many uses of &lt;code&gt;std::unique_ptr&lt;/code&gt; are relying on
them never being null, and simply leave this up to the programmer
to ensure.&lt;/p&gt;
&lt;p&gt;Herb Sutter himself discusses this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Since the problem is that we are not expressing the “not null”
invariant, we should express that by construction — one way is
to make the pointer member a &lt;code&gt;gsl::not_null&amp;lt;&amp;gt;&lt;/code&gt; (see for example the
Microsoft GSL implementation) which is copyable but not movable or
default-constructible.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In a programming language with destructive moves, it would be possible
to have a smart pointer that was both &amp;ldquo;non-null&amp;rdquo; and movable. If we
need both movability and the ability to express this invariant in the
type system, well, C++ cannot help us.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But what about a third option, that the class intends (and documents) that
you just shouldn’t call operator&amp;lt; on a moved-from object… that’s a
hard-to-use class, but that doesn’t necessarily make it a buggy class,
does it?&lt;/p&gt;
&lt;p&gt;Yes, in my view it does make it a buggy class that shouldn’t pass
code review.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But in a sense, this is exactly what &lt;code&gt;std::unique_ptr&lt;/code&gt; is. It has a
special state where you cannot call its most important operator, the
dereference operator. It only avoids being called buggy because it
expands this state so it can be arrived at by other means.&lt;/p&gt;
&lt;p&gt;Again, everything Herb Sutter says is true in a strict sense. It is
memory-safe to use moved-from objects other than to destroy or
assign to them, even if the move operation makes no further guarantees.
It simply isn&amp;rsquo;t safe in a broader sense, in that it will have surprising,
changeable behavior. It is true that the null pointer is a valid
value of &lt;code&gt;std::unique_ptr&lt;/code&gt;, but smart pointers that implement move
are forced to have such a value.&lt;/p&gt;
&lt;p&gt;And therefore, it should not be surprising that these questions come
up. The misconceptions that Herb Sutter is addressing are an unfortunate
consequence of the dissonance between the strict semantics of
the programming language, where his statements are true, and the
practical implications of how these features are used and are
intended to be used, where the situation is more complicated.&lt;/p&gt;
&lt;h2 id=&#34;moves-in-rust&#34;&gt;Moves in Rust&lt;/h2&gt;
&lt;p&gt;So the natural follow-up question is, how does Rust handle move semantics?&lt;/p&gt;
&lt;p&gt;First off, as mentioned before, Rust makes a special case for types
that do not need move semantics, where the value itself contains all
the information necessary to represent it, where no heap allocations
or resources are managed by the value, types like &lt;code&gt;i32&lt;/code&gt;. These types
implement the special &lt;code&gt;Copy&lt;/code&gt; trait, because for these types, copying
is cheap, and is the default way to pass to functions or to handle
assignments:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(bar: &lt;span style=&#34;color:#66d9ef&#34;&gt;i32&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Implementation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; var: &lt;span style=&#34;color:#66d9ef&#34;&gt;i32&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(var); &lt;span style=&#34;color:#75715e&#34;&gt;// copy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(var); &lt;span style=&#34;color:#75715e&#34;&gt;// copy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(var); &lt;span style=&#34;color:#75715e&#34;&gt;// copy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For types that are not &lt;code&gt;Copy&lt;/code&gt;, such as &lt;code&gt;String&lt;/code&gt;, the default function
call uses move semantics. In Rust, when a variable is moved from, that
variable&amp;rsquo;s lifetime ends early. The move replaces the destructor call
at the end of the block, at compile time, which means it&amp;rsquo;s a compile
time error to write the equivalent code for &lt;code&gt;String&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(bar: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Implementation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; var: String &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;.to_string();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(var); &lt;span style=&#34;color:#75715e&#34;&gt;// Move
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(var); &lt;span style=&#34;color:#75715e&#34;&gt;// Compile-Time Error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(var); &lt;span style=&#34;color:#75715e&#34;&gt;// Compile-Time Error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Copy&lt;/code&gt; is a trait, but more entwined with the compiler than most traits.
Unlike most traits, you can&amp;rsquo;t implement it by hand, but only by deriving
from primitive types that implement copy. Types like &lt;code&gt;Box&lt;/code&gt;, that manage
a heap allocation, do not implement copy, and therefore structs that
contain &lt;code&gt;Box&lt;/code&gt; also cannot.&lt;/p&gt;
&lt;p&gt;This is already an advantage to Rust.  C++ pretends that all types are the
same, even though they require different usage patterns in practice. You
can pass a &lt;code&gt;std::string&lt;/code&gt; by copy just like an &lt;code&gt;int&lt;/code&gt;. Even if you have a
vector of vectors of strings, you can pass by copy and that&amp;rsquo;s usually the
default way to pass it &amp;ndash; moves in many cases require explicit opt-in. For
&lt;code&gt;int&lt;/code&gt; it&amp;rsquo;s a reasonable default, but for collections types it isn&amp;rsquo;t,
and in Rust the programming language is designed accordingly.&lt;/p&gt;
&lt;p&gt;If you want a deep copy, you can always explicitly ask for it with
&lt;code&gt;.clone()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;foo&lt;/span&gt;(bar: String) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Implementation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; var: String &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hi&amp;#34;&lt;/span&gt;.to_string();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(var.clone()); &lt;span style=&#34;color:#75715e&#34;&gt;// Copy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(var.clone()); &lt;span style=&#34;color:#75715e&#34;&gt;// Copy
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo(var);         &lt;span style=&#34;color:#75715e&#34;&gt;// Move
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What this actually does is create a clone, or a deep copy, and then
move the clone, as &lt;code&gt;foo&lt;/code&gt; takes its parameter by move, the default for
non-&lt;code&gt;Copy&lt;/code&gt; types.&lt;/p&gt;
&lt;p&gt;What does a move in Rust actually entail? C++ implements moves
with custom-written move constructors, which collections and other
resource-managing types have to implement in addition to implementing
copying (though automatic implementation is available if building out of
other movable types). Rust requires implementations for clone, but for
all moves, the implementation is the same: copy the memory in the value
itself, and don&amp;rsquo;t call the destructor on the original value. And in Rust,
all types are movable with this exact implementation &amp;ndash; non-movable types
don&amp;rsquo;t exist (though non-movable values do). The bytes encode information
&amp;ndash; such as a pointer &amp;ndash; about the resource that the value is managing,
and they must accomplish that in the new location just as well as they
did in the old location.&lt;/p&gt;
&lt;p&gt;C++ can&amp;rsquo;t do that, because in C++, the implementation of move has to
mark the moved-from value as no longer containing the resource. How this
marking works depends on the details of the type.&lt;/p&gt;
&lt;p&gt;But even if C++ implemented destructive moves, some sort of &amp;ldquo;move
constructor&amp;rdquo; or custom move implementation would still be required.
C++, unlike Rust, does not require that the bytes contained in an
object mean the same thing in any arbitrary location. The object could
contain a reference to itself, or to part of itself, that would be
invalidated by moving it. Or, there could be a data structure somewhere
with a reference to it, that would need to be updated. C++ would have
to give types an opportunity to address such things.&lt;/p&gt;
&lt;p&gt;Safe Rust forbids these things. The lifetime of a value takes moves into
account; you can&amp;rsquo;t move from a value unless there are no references
to it. And in safe Rust, there is no way for the user to create a
self-referential value (though the compiler can in its implementation
of &lt;code&gt;async&lt;/code&gt; &amp;ndash; but only if the value is already &amp;ldquo;pinned,&amp;rdquo; which we will
discuss in a moment).&lt;/p&gt;
&lt;p&gt;But even in unsafe Rust, such things violate the principle of move.
Moving is always safe, and unsafe Rust is always responsible for keeping
safe code safe. As a result, Rust has a mechanism called &amp;ldquo;pinning&amp;rdquo; that
indicates, in the type system, that a particular value will never move
again, which can be used to implement self-referential values and which
is used in &lt;code&gt;async&lt;/code&gt;. The details are beyond the scope of this blog post,
but it does mean that Rust can avoid the issue of move semantics for
non-movable values without ruining the simplicity of its move semantics.&lt;/p&gt;
&lt;p&gt;For these rare circumstances, the features of moving can be accomplished
by indirection, and using a &lt;code&gt;Box&lt;/code&gt; that points to a pinned value on
the heap. And there is nothing stopping such types from implementing a
custom function which effectively implements a custom move by consuming
the pinned value, and outputs a new value, which can then be pinned
in a different location. There is no need to muddy the built-in move
operation with such semantics.&lt;/p&gt;
&lt;h2 id=&#34;practical-implications-for-c-programmers&#34;&gt;Practical Implications for C++ Programmers&lt;/h2&gt;
&lt;p&gt;So, obviously, in light of my blog series, I recommend using Rust
over C++. For Rust users, I hope this clarifies why the move semantics
are the way they are, and why the &lt;code&gt;Copy&lt;/code&gt; trait exists and is so important.&lt;/p&gt;
&lt;p&gt;But of course, not everyone has the choice of using Rust. There are a
lot of large, mature C++ codebases that are well-tested and not going
away anytime soon, and many programmers working on those codebases.
For these programmers, here is some advice for the footgun
that is C++ move semantics, both based on what we&amp;rsquo;ve discussed, and
a few gotchas that were out of the scope of this post:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Learn the difference between rvalue, lvalue, and forwarding references.
Learn the rules for how passing by value works in modern C++. These
topics are out of the scope of this blog post, but they are core parts
of C++ move semantics and especially how overloading is handled in
situations where moves are possible. Scott Meyers&amp;rsquo;s &lt;em&gt;Effective Modern
C++&lt;/em&gt; is an excellent resource.&lt;/li&gt;
&lt;li&gt;Move constructors and assignment operators should always be &lt;code&gt;noexcept&lt;/code&gt;.
Otherwise, &lt;code&gt;std::vector&lt;/code&gt; and many other library utilities will simply
ignore them. There is no warning for this.&lt;/li&gt;
&lt;li&gt;The only sane things to do with most moved-from objects are to
immediately destroy it or reset its value. Comment about this in your
code! If the class specifically defines that moved-from values are
empty or null, note that in a comment too, so that programmers don&amp;rsquo;t
get the impression that there are any guarantees about moved-from
values in general.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Move semantics are essential to the performance of modern C++. Without
them, much of its standard library would become much more difficult
to use. However, the specific design of moves in C++:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;is misaligned with the purpose of moving&lt;/li&gt;
&lt;li&gt;fails to eliminate all run-time cost&lt;/li&gt;
&lt;li&gt;surprises programmers, and&lt;/li&gt;
&lt;li&gt;forces designers of types to implement an &amp;ldquo;empty-yet-valid&amp;rdquo; state&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why, then, does C++ use such a definition? Well, C++ was not originally
designed with move semantics in mind. Proposals to add destructive move
do not interact well with the existing language semantics.
One &lt;a href=&#34;https://www.foonathan.net/2017/09/destructive-move/&#34;&gt;interesting blog post&lt;/a&gt;
that I found even says, when following through on the consequences
of adding destructive move semantics:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;hellip;  if you try to statically detect such situations, you end up with Rust.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;C++ has so many unsafe features and so many existing mechanisms, that
this was deemed the most reasonable way to add move semantics to C++, harmful
as it is.&lt;/p&gt;
&lt;p&gt;And perhaps this decision was unnecessary. Perhaps there was a way &amp;ndash;
perhaps there still is a way &amp;ndash; to add destructive moves to C++. But
for right now, non-destructive moves are the ones the maintainers of
C++ have decided on. And even if destructive moves were added, it&amp;rsquo;s unlikely
that they&amp;rsquo;d be as clean as the Rust version, and the existing non-destructive
moves would still have to be supported for backwards-compatibility sake.&lt;/p&gt;
&lt;p&gt;In any case, Rust has taken this opportunity to learn from existing
programming languages, and to solve the same problems in a cleaner,
more principled way. And so, for the move semantics as well as for the
syntax, I recommend Rust over C++.&lt;/p&gt;
&lt;p&gt;And to be clear, this still has very little to do with the safety features
of Rust. A more C++-style language with no &lt;code&gt;unsafe&lt;/code&gt; keyword and no safety
guarantees could have still gone the Rust way, or something similar to
it. Rust is not just a safer alternative to C++, but, as I continue to
argue, unsafe Rust is a better unsafe language than C++.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Sayonara, C&#43;&#43;, and hello to Rust!</title>
      <link href="https://www.thecodedmessage.com/posts/hello-rust/" />
      <id>https://www.thecodedmessage.com/posts/hello-rust/</id>
      <updated>2021-10-26T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;This past May, I started a new job working in Rust. I was somewhat
skeptical of Rust for a while, but it turns out, it really is all it&amp;rsquo;s
cracked up to be. As a long-time C++ programmer, and C++ instructor,
I am convinced that Rust is better than C++ in all of C++&amp;rsquo;s application
space, that for any new programming project where C++ would make sense
as the programming language, Rust would make more sense.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;This past May, I started a new job working in Rust. I was somewhat
skeptical of Rust for a while, but it turns out, it really is all it&amp;rsquo;s
cracked up to be. As a long-time C++ programmer, and C++ instructor,
I am convinced that Rust is better than C++ in all of C++&amp;rsquo;s application
space, that for any new programming project where C++ would make sense
as the programming language, Rust would make more sense.&lt;/p&gt;
&lt;h2 id=&#34;what-rust-is-not-for&#34;&gt;What Rust is not for&lt;/h2&gt;
&lt;p&gt;Before going into more detail about why I think that, I&amp;rsquo;d like to throw
out a few caveats, so you know I&amp;rsquo;m a reasonable person and not just an
extremist fanboy.&lt;/p&gt;
&lt;p&gt;Caveat the first: Note that I said this about &lt;em&gt;new&lt;/em&gt; programming
project. There are some people on the Internet who demand the re-writing
of all existing C and C++ projects in Rust, and while I think Rust is a
better language for new projects, and that many existing projects should
seriously consider integrating it, I realize, like a reasonable mature
programmer, that for most existing projects, a Rust re-write would be
a prohibitively expensive rabbit hole. In short, Rust is not so amazing
that it will protect you from second system syndrome or from the perils
of a complete rewrite. It is but a mortal programming language.&lt;/p&gt;
&lt;p&gt;That said, new Rust versions of aging C and C++ projects are often
very worthwhile and exciting, like new versions of many aging projects
can be. It&amp;rsquo;s just not a magical exception to basic economics.&lt;/p&gt;
&lt;p&gt;Caveat the second: Note also that I said &amp;ldquo;where C++ would make sense.&amp;rdquo;
Rust has a lot of enthusiastic fans, and so there are a lot of people
learning Rust expecting the magic when they first learned their favorite
programming language. And what they find is a programming language that
requires lots of arcane rules, where everything seems rather tedious,
and where a lot of their favorite features don&amp;rsquo;t exist.&lt;/p&gt;
&lt;p&gt;Rust is a systems programming language. It is not garbage collected,
meaning you do have to manually manage memory. While Rust makes it
much harder to do that egregiously wrong, it&amp;rsquo;s still a very hard
problem, and there are trade-offs that Rust &amp;ndash; unlike GC&amp;rsquo;d languages
&amp;ndash; refuses to make for you.  Meanwhile, like C++, the emphasis is on
performance (or at least control over performance), whether latency
or throughput or memory footprint. Rust is trying to make sure that all
its organizational abstractions have no run-time cost, or, if they do,
to make sure it&amp;rsquo;s abundantly clear exactly what that cost is. If you
are a systems programmer, if you are used to C and C++ and to trying to
solve systems programming types of problems, Rust is magical, just like
when you learned your previous favorite programming language.&lt;/p&gt;
&lt;p&gt;If you are not, Rust is overkill for your task at hand and you shouldn&amp;rsquo;t
be using it. I earnestly recommend Haskell.&lt;/p&gt;
&lt;p&gt;For more clarity on what I mean by systems programming: If you write
Python or JavaScript or Ruby, then you&amp;rsquo;re running the code in a Python
interpreter, in Node or a web browser, in the Ruby interpreter, all on
top of an operating system with an operating system kernel.  Rust doesn&amp;rsquo;t
replace those tools. Rather, the Python interpreter, the web browser,
and Node, and even the kernel, are programs written in C or C++, and
Rust replaces that. It&amp;rsquo;s a whole &amp;rsquo;nother level of programming,
where you have manage the actual hardware.&lt;/p&gt;
&lt;h2 id=&#34;purpose-of-this-series&#34;&gt;Purpose of this series&lt;/h2&gt;
&lt;p&gt;But enough of what Rust is and is not for. It is an excellent systems
programming language, and one that was a long time coming. I plan
on writing several posts about Rust features, why they&amp;rsquo;re an improvement
upon C++ features, and why Rust is a better, more modern programming
language. Mostly, this will be a discussion of why Rust is better than
C++, which I think is the most comparable existing programming language,
but it will also touch on why Rust is an improvement on C.&lt;/p&gt;
&lt;p&gt;Because of this C++ focus, this series will at times be as much or
more a criticism of C++ as it is a commendation of Rust. I think that
is unavoidable, as this type of criticism of C++ is most truly credible
when an alternative is available, and similarly, Rust is most practically
evaluated in terms of its most viable alternative. Unfortunately, that also
means that I&amp;rsquo;ll assume some level of familiarity with C++, but hopefully
not too much.&lt;/p&gt;
&lt;p&gt;I know that this is a much-discussed topic. Perhaps this is the Rust
equivalent of the dreaded Haskell monad tutorial, where every person
new to the programming language excitedly writes the same thing, and so
thank you for reading.  I&amp;rsquo;m going to try and avoid the obvious tropes:
I&amp;rsquo;m going to try to do more than simply beat the table about type-safety
and memory safety and avoiding undefined behavior &amp;ndash; though of course
these topics will come up. In fact, I had until rather recently simply
assumed that the safety of Rust would lead to unacceptable performance
degradation, that Rust might be well and good for some applications but
could unfortunately never be useful in a true low-latency environment. I
had to be persuaded that memory safety wasn&amp;rsquo;t a downside in such contexts,
that Rust could truly be a competitor to C or C++ and not just to Go
or Swift.&lt;/p&gt;
&lt;h2 id=&#34;the-syntax-of-c&#34;&gt;The syntax of C++&lt;/h2&gt;
&lt;p&gt;So for today, I&amp;rsquo;m going to ignore memory safety completely. Even assuming
that C++ was more or less right that performance and optimization requires
a broad range of undefined behaviors, there were still problems with
C++ that left me regularly begging for at least a syntactic rewrite.
As Bjarne Stroustrup, creator of C++, famously said: &amp;ldquo;Within C++, there
is a much smaller and cleaner language struggling to get out.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;He later clarified that he wasn&amp;rsquo;t talking about a streamlined GC&amp;rsquo;d
language like Java, and of course he is aware of Rust and still on the C++
train. As he clarified, he was talking about the syntax of C++, and the
legacy of C. But just that category, just syntax, is I think enough to
justify a do-over of C++. I fantasized continually about a new syntax &amp;ndash;
with identical semantics in my mind &amp;ndash; that could be migrated to in a
file-by-file basis, with its own file extension.  This, I realize now,
would in practice make for a new language, and a good opportunity to
introduce modern typing in it, and in Rust, I see my hope realized,
if a little more inconveniently than I imagined.&lt;/p&gt;
&lt;p&gt;So that is what I want to focus on for the rest of this post: Why C++
syntax is rotten. Analyses of other Rust features I will reserve for
future posts.&lt;/p&gt;
&lt;p&gt;Many of C++&amp;rsquo;s syntactic foibles have to do with its C heritage. This is
not to smear C: the same features that make sense in a simple &amp;ldquo;portable
assembly&amp;rdquo; like C begin to break down when they are preserved with
almost-identical syntax and naively extended semantics in a language that
promises powerful generic programming features that assist in automatic
code generation, resource management, and memory safety.&lt;/p&gt;
&lt;h2 id=&#34;header-files&#34;&gt;Header Files&lt;/h2&gt;
&lt;p&gt;This is really clear in my first example: header files. In C, they
serve two purposes. For the programmer, they allow a separation of
interface and implementation, especially when considering that modern
IDE technology did not exist when C was developed. The header file shows
the external interface of how to use the module, and the C file shows
how it is implemented.&lt;/p&gt;
&lt;p&gt;For the compiler, this arrangement simplifies implementation. The information
necessary to compile each module is all included in the C file for the
module plus all the headers included by it (and included by them, etc.).
None of the other &lt;code&gt;.c&lt;/code&gt; C files need be consulted, only the much smaller &lt;code&gt;.h&lt;/code&gt;
headers, in a practice known as &lt;em&gt;separate compilation&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The problem when this is extended to C++ is templates. These are essentially
macros, in that they allow the on-demand generation of new code, based on
what is going on in the client code. So if we imagine that the module &lt;code&gt;broadcast&lt;/code&gt;
depends on the module &lt;code&gt;connection&lt;/code&gt;, and that the compiler is currently compiling
&lt;code&gt;broadcast&lt;/code&gt;, it would not only be necessary to investigate the interface to
&lt;code&gt;connection&lt;/code&gt;, but also the complete implementation of the templates.&lt;/p&gt;
&lt;p&gt;If we are to preserve the programmers&amp;rsquo; perspective, and keep only the
interface in the header files, this means that &amp;ldquo;separate compilation&amp;rdquo;
is broken and that the compiler would need to fish around in the main
C++ files. If we instead preserve the concept of separate compilation,
the headers are no longer about just interfaces, but also implementation
details.&lt;/p&gt;
&lt;p&gt;The inventors of C++ decided to preserve the concept of separate compilation,
and in the laziest way possible, literally the exact same implementation of C rather
than trying to apply the same principles and goals, and re-engineering something
better.&lt;/p&gt;
&lt;p&gt;So now, we have the situation for the programmer where the header file contains
a duplicate of the interface, in addition to the implementation of all functions
that happen to be templates. To a compiler, a function and a function
template are very different things, but to a user, functions go back and forth
between template and not all the time, requiring the programmer to move them
between files.&lt;/p&gt;
&lt;p&gt;Why does this distinction exist at all in C++? Computers are much faster now.
The compiler, to preserve efficiency, could automatically extract its own
binary file of what information it needs from each module to compile other
modules. The compiler could do this work for us. It is doing far more work
in all of its optimization steps.&lt;/p&gt;
&lt;p&gt;C is famously a portable syntax for writing assembly. In C, the
information needed by the compiler, the &lt;em&gt;application binary interface&lt;/em&gt;
or ABI, is exactly the same as the interface needed by the programmer,
the &lt;em&gt;application programming interface&lt;/em&gt; or API &amp;ndash; or at least very
close to it. And so in C, the concept of header files makes sense,
if unnecessary with modern compiler technology.&lt;/p&gt;
&lt;p&gt;And to be clear, templates are just the most egregious example of
non-interface code needed from other modules: bodies of inline functions
and private member variables in classes are also not part of the interface
from a programming perspective, but part of the binary interface, part
of what the compiler needs to know about a module to compile the other
modules that depend on it.&lt;/p&gt;
&lt;p&gt;Now, you may think, why is this such a big deal? Why such a complaint about
the inconvenience of moving things between files, or duplicating some
information? Why does it matter if the rules of which things to put
in which file are on the arcane side? You might imagine, so what?
You&amp;rsquo;ll mess it sometimes, the compiler will issue an error, you&amp;rsquo;ll
say &amp;ldquo;oh, right&amp;rdquo; and move the code to the appropriate location.&lt;/p&gt;
&lt;p&gt;To such objections I say: You don&amp;rsquo;t know C++. Unfortunately, I&amp;rsquo;ve
seen this attitude taken by professional C++ programmers, who were
careless with header files, moving code around in bulk in a way that
was liable to break this particular set of arcane rules, and accusing
me of overreacting and wasting time when I objected to this.&lt;/p&gt;
&lt;p&gt;For those who haven&amp;rsquo;t had the misfortunate of finding this out the
hard way, when you break an arcane rule in C++ &amp;ndash; even rules that have
nothing to do with run-time behavior or memory safety &amp;ndash; you are lucky
if you get away with a simple compiler error &amp;ndash; or even the somewhat
more common arcane, incomprehensible compiler error. Unfortunately,
the result is regularly no error at all. The compiler cannot tell,
from its separate compilation point of view, if the information
provided in the headers is consistent. One module might import
one version of a header, and another module might import another.&lt;/p&gt;
&lt;p&gt;This may sound unlikely, but many codebases have the practice of
separating out the actual interface in one header, and the template
implementations in another. At this point, it becomes important which
one is included, especially because &amp;ldquo;template specializations&amp;rdquo; mean
that additional template code doesn&amp;rsquo;t just make more templates
available, but changes the meaning of existing templates.&lt;/p&gt;
&lt;p&gt;If the templates included in different compilation units are inconsistent,
the result is undefinned behavior, and the program might potentially do
anything. Unfortunately, this also means the behavior might switch arbitrarily
between different compiler versions, different compiler vendors, or based on
seemingly unrelated permutations. Unpredictable behavior changes lead to bugs
and security vulnerabilities.&lt;/p&gt;
&lt;p&gt;Worse, header files are implemented by textual inclusion. The compiler
proceeds as if the contents of the header were literally included in the
module that imports them. Cycles of inclusion don&amp;rsquo;t result in error, but
instead, a header is simply not included (if common precautions are made)
when the second recursion happens.&lt;/p&gt;
&lt;p&gt;Thus: Imports via header files are sensitive to ordering. A
seemingly-innocuous change, like alphabetizing the included header files
in each module, can break builds or change behavior. Such a change rolled
out over an entire company&amp;rsquo;s codebase can be disastrous, and take many
programmer-months to unravel the consequences of. Ask me how I know.&lt;/p&gt;
&lt;p&gt;So it should make sense that the first concept I had for my &amp;ldquo;new syntax&amp;rdquo;
for C++ was that header files should be auto-generated from source files,
preferably in a pre-compiled binary format.&lt;/p&gt;
&lt;p&gt;This would be an implementation detail of the build artifact, maintained
a build directory, and be a compiler-specific optimization in favor of
better compilation times. Semantically, rather than textual inclusion,
there would simply be a declaration in one module to say that another
module&amp;rsquo;s public interface could be used, where order wouldn&amp;rsquo;t
matter.&lt;/p&gt;
&lt;p&gt;Rust is a modern programming language, and the Rust &lt;code&gt;use&lt;/code&gt; directive does
in fact work that way.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t particularly a special point about Rust. This would be the
obvious way to construct any new programming language. The compiler
doesn&amp;rsquo;t need header files &amp;ndash; the C preprocessor that implements &lt;code&gt;#include&lt;/code&gt;
directives, along with the rule that functions and structures must be
declared before use, is a hold-over from the time when compilers ran on
computers slower than a modern thermostat. And programmers don&amp;rsquo;t need
them either: A better place for interfaces to be put in a separate file
would be automatically-generated documentation.&lt;/p&gt;
&lt;p&gt;So Rust here gets points for doing what any sensible modern programming
language would do, and C++ loses points for carrying over an implementation
detail from C to a context where it no longer makes any sense.&lt;/p&gt;
&lt;h2 id=&#34;syntax-and-layout&#34;&gt;Syntax and Layout&lt;/h2&gt;
&lt;p&gt;Since we&amp;rsquo;re talking about the syntax of C++, I wanted to touch on something
very basic but very serious: basic syntax for control structures. C and its
syntactic descendants, including C# and Java, use something like this for
&lt;code&gt;if&lt;/code&gt;-statements and &lt;code&gt;for&lt;/code&gt;-statements:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if (!foo.is_empty()) {
    spin_up_thread(foo);
    destroy(&amp;amp;bar);
}
do_something_else();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example, the calls to &lt;code&gt;spin_up_thread&lt;/code&gt; and &lt;code&gt;destroy&lt;/code&gt; are inside
the &lt;code&gt;if&lt;/code&gt; statement, and only happen if &lt;code&gt;foo&lt;/code&gt; is indeed non-empty. The
call to &lt;code&gt;do_something_else&lt;/code&gt; is not part of the &lt;code&gt;if&lt;/code&gt; statement.&lt;/p&gt;
&lt;p&gt;How do we know that? Well, the compiler knows that because after the &lt;code&gt;if&lt;/code&gt;
statement there is an opening brace, and so all statements are included
until the matching closing brace, including the two mentioned. But,
depending on how fast we&amp;rsquo;re skimming the code, we probably know that
because the &lt;code&gt;spin_up_thread&lt;/code&gt; and &lt;code&gt;destroy&lt;/code&gt; calls are indented.&lt;/p&gt;
&lt;p&gt;In this situation, in what will be a recurring theme in this comparison,
the compiler and the programmer are getting their information from
different places. Therefore, the compiler and the programmer can disagree,
especially as braces aren&amp;rsquo;t mandatory, and if omitted indicate that only
the first subsequent statement is included:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if (!foo.is_empty())
    spin_up_thread(foo);
    destroy(&amp;amp;bar); // Warning: This is done unconditionally
do_something_else();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This looks like it only destroys &lt;code&gt;&amp;amp;bar&lt;/code&gt; conditionally, and to a human
following the indentation in code review or casual reading, that&amp;rsquo;s
exactly what you would expect. But there&amp;rsquo;s no braces and the compiler,
for whatever reason, ignores the same whitespace that human readers
rely on.&lt;/p&gt;
&lt;p&gt;This has come up in personal projects of mine, usually when collaborating
with someone else. Even if you make the personal discipline of always
including the braces &lt;code&gt;{&lt;/code&gt; around the body of your if-statements &lt;code&gt;}&lt;/code&gt;, someone
else might not have that discipline, and therefore, you might be exposed
to this intermediate-state code:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if (!foo.is_empty())
    spin_up_thread(foo);
do_something_else();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Needing to add a call to &lt;code&gt;destroy(&amp;amp;bar)&lt;/code&gt; in the condition, after &lt;code&gt;spin_up_thread&lt;/code&gt;,
you find the line, add a new line at the same indentation level, and simply fail
to notice that the new line is not actually wrapped in any &lt;code&gt;{&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This was, of course, the direct cause of a &lt;a href=&#34;https://arstechnica.com/information-technology/2014/02/extremely-critical-crypto-flaw-in-ios-may-also-affect-fully-patched-macs/&#34;&gt;major security vulnerability in iOS
and macOS&lt;/a&gt;:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if (some_err_condition)
    goto fail;
    goto fail;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since humans use indentation to read code, and to determine what is in a block
and what isn&amp;rsquo;t, I would&amp;rsquo;ve wanted my wish-list &amp;ldquo;new C++ syntax&amp;rdquo; programming
language to take a page from Python and use significant whitespace:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if !foo.is_empty():
    spin_up_thread(foo)
    destroy(&amp;amp;bar)
do_something_else()
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Rust is a minor disappointment in this department. It stuck to braces,
and whitespace being &amp;ldquo;insignificant.&amp;rdquo; But it made a huge improvement,
far outweighing my disappointment: Rust at least prevents the &lt;code&gt;goto fail&lt;/code&gt; scenario by making braces mandatory, helping ergonomics by
instead removing bracketing around the condition. Having the body of the
&lt;code&gt;if&lt;/code&gt;-statement without brackets is simply not worth it as a short-cut,
but if the braces are mandatory, then the parentheses aren&amp;rsquo;t necessary:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if !foo.is_empty() {
    spin_up_thread(foo);
    destroy(bar);
}
do_something_else();
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is better because then the &lt;code&gt;goto fail&lt;/code&gt; example would still be glaringly obviously
failsome, because even if the indentation does not match the braces, the braces still
have to go somewhere, and will jump out at you:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;if some_err_condition {
    goto fail; }
    goto fail;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It disappoints me that these issues tend to be dismissed as &amp;ldquo;matters
of taste,&amp;rdquo; because as Apple learned, there are actual consequences to
this misalignment of what programmers pay attention to and what the
compiler pays attention to. I would have liked Rust to go the whole
way, and remove altogether this strange concept that whitespace should
be insignificant, a concept that my oldest C and C++ books exclaimed
as a great feature without explanation or justification.  But at least
Rust has fixed the most egregious consequences of C++ syntax. Again,
this problem with C++ comes from a feature inherited from C, but in this
case C was just wrong to begin with, and should&amp;rsquo;ve done it the Rust way
(or the Python way) from the very start.&lt;/p&gt;
&lt;p&gt;Additionally, Rust has good auto-formatting, which unlike C++ auto-formatting
tools, do not break code (by, for example, re-ordering headers). This fundamentally
replaces the whitespace provided by the programmer &amp;ndash; which might be misleading to
other programmers &amp;ndash; with whitespace that aligns with the compiler&amp;rsquo;s interpretation,
and therefore is correct to rely on when skimming. A good &lt;code&gt;cargo fmt&lt;/code&gt; should therefore
be run before every code review, to make sure that the code can be easily and correctly
read.&lt;/p&gt;
&lt;h2 id=&#34;c-isms-vs-modern-c&#34;&gt;C-isms vs &amp;ldquo;Modern C++&amp;rdquo;&lt;/h2&gt;
&lt;p&gt;I then have one more topic before I wrap up syntax. C++ programmers
nowadays are telling everyone who was upset with their language in
the 90&amp;rsquo;s and aughts that it&amp;rsquo;s better now, that C++ has cleaned up its
act. C++11 really has changed a lot, and C++ is innovating again, and
that&amp;rsquo;s very good. C++ is full of new features, and part of its claim to
be a modern programming language involves claiming that programming in
C++ is good, if you use these new features.&lt;/p&gt;
&lt;p&gt;Smart pointers, written &lt;code&gt;std::unique_ptr&amp;lt;Foo&amp;gt;&lt;/code&gt;, allow automatic
implementation of construction and destruction for owning pointers, and
allows much clearer communication about ownership semantics in function
signatures, and so is preferable to writing the C-style &lt;code&gt;Foo *&lt;/code&gt;. C++
arrays, &lt;code&gt;std::array&amp;lt;Foo, 12&amp;gt; arr;&lt;/code&gt;, act like any other STL collection,
allow them and their iterators to be passed to standard templates that
expect STL interfaces, and provide a number of useful features as methods,
and so using them is preferable to the C-style &lt;code&gt;Foo arr[12];&lt;/code&gt;.
&lt;code&gt;static_cast&amp;lt;A&amp;gt;(b)&lt;/code&gt; is much more specific, and therefore less prone to
accident, than the C-style &lt;code&gt;(A)b&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;These are among the features that are trotted out whenever someone says
they used C++ in the 90&amp;rsquo;s and it had all these problems. These features
are among the ones used to claim that C++ is a better, cleaner, tidier,
more modern programming language than it used to be. Whether or not
they&amp;rsquo;ve done enough to replace their old counter-parts &amp;ndash; they&amp;rsquo;re
generally preferred whenever possible.&lt;/p&gt;
&lt;p&gt;The problem? Convenience. Who wants to type &lt;code&gt;std::unique_ptr&amp;lt;Foo&amp;gt;&lt;/code&gt; when
instead you can write &lt;code&gt;Foo *&lt;/code&gt;? Why are the somewhat-deprecated options
the easy ones to write? Why isn&amp;rsquo;t it something like &lt;code&gt;std::raw_ptr&amp;lt;Foo&amp;gt;&lt;/code&gt;
with some convenient notation for &lt;code&gt;std::unique_ptr&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;But of course, that would break compatibility with C, and with earlier
versions of C++.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t want to get into the myriad reasons why smart pointers are to be
preferred to raw pointers, or why raw pointers occupy such an awkward place
in C++ &amp;ndash; those are topics for a future post. But for however many seemingly-principled
reasons some of my colleagues might state for why they used raw pointers in
this or that situation, I couldn&amp;rsquo;t shake the feeling that it was partially
because raw pointers were given the old-fashioned, easy-to-type notation.&lt;/p&gt;
&lt;p&gt;And so, when I imagined my new C++ syntax, it would have &lt;code&gt;Foo *&lt;/code&gt; mean
&lt;code&gt;std::unique_ptr&amp;lt;Foo&amp;gt;&lt;/code&gt;, and &lt;code&gt;Foo arr[12]&lt;/code&gt; mean &lt;code&gt;std::array&amp;lt;Foo, 12&amp;gt;&lt;/code&gt;.
Why have the not-entirely-deprecated-but-not-preferred legacy C features
be the easier ones to type?&lt;/p&gt;
&lt;h2 id=&#34;conclusions&#34;&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;All in all, this shows that a lot of purely syntactic but still substantial
and consequential problems with C++ can be fixed with a syntax reboot, which
Rust mostly provides. And I haven&amp;rsquo;t once mentioned type safety or memory safety!
This will be developed on further in this blog series, where I will maintain that
Rust is not only a better programming language than C++, but a better &lt;em&gt;unsafe&lt;/em&gt;
programming language than C++. Even if I had to use &lt;code&gt;unsafe&lt;/code&gt; for every function
in my module, I&amp;rsquo;d still rather write my module in Rust than C++, for all
these reasons. I say this as a pre-emptive strike against the argument
that occasionally having to use &lt;code&gt;unsafe&lt;/code&gt; to achieve performance parity
with C++ (and it is very occasional) &amp;ldquo;defeats the whole purpose&amp;rdquo; of Rust.&lt;/p&gt;
&lt;p&gt;But of course, there are deeper problems with C++ that Rust also
addresses, beyond just the syntactic. But those will have to wait for
future posts.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Apple Silicon</title>
      <link href="https://www.thecodedmessage.com/posts/apple_silicon/" />
      <id>https://www.thecodedmessage.com/posts/apple_silicon/</id>
      <updated>2020-11-16T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;This year, Apple released, to much fanfare, a somewhat obscure
technical change to how its computers work: Macs will transition
away from Intel’s CPUs to in-house processors known as “Apple
Silicon,” more similar to the technology Apple already
uses in its phones and tablets. It is a tremendous amount of
hype for something rather technical, and to people used to more
user-visible feature announcements, this can be
&lt;a href=&#34;https://www.zdnet.com/article/apple-released-a-new-macbook-air-and-im-disheartened/&#34;&gt;somewhat disappointing&lt;/a&gt;,
or at least confusing.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;This year, Apple released, to much fanfare, a somewhat obscure
technical change to how its computers work: Macs will transition
away from Intel’s CPUs to in-house processors known as “Apple
Silicon,” more similar to the technology Apple already
uses in its phones and tablets. It is a tremendous amount of
hype for something rather technical, and to people used to more
user-visible feature announcements, this can be
&lt;a href=&#34;https://www.zdnet.com/article/apple-released-a-new-macbook-air-and-im-disheartened/&#34;&gt;somewhat disappointing&lt;/a&gt;,
or at least confusing.&lt;/p&gt;
&lt;p&gt;What does this actually mean for the end user? Apple claims that these
new Macs will be (many times) faster, run cooler, and have much better
battery life. Are these improvements as drastic as Apple claims? Will
there be downsides and other adjustments that users will have to make,
or will these new computers just work like faster, less power-hungry Macs?&lt;/p&gt;
&lt;p&gt;A lot of responses I’ve seen seem pretty skeptical, which is
fair. It’s been a long time since the drastic improvements of Moore’s
law have been the norm in computing; we’re used to much more incremental
improvements. And Apple is claiming to achieve these improvements by
moving away from Intel, when Intel is the established market leader in
making high-powered PC processors. Can these new computers really be
that much better?&lt;/p&gt;
&lt;p&gt;My answer, as your computer-nerdy friend, is that these computers are
not only going to be a great technical improvement over previous Macs,
but represent a revolution even beyond the Apple ecosystem, a turning
point for PCs in general, and one that was a long time coming. To explain
why, I’m going to delve into some computer history to give context
to this shift, and some of the technical details of how computers work,
and specifically in what ways these new Macs will work differently from
the current ones.&lt;/p&gt;
&lt;p&gt;So bear with me as we go deep. I promise it’s relevant.&lt;/p&gt;
&lt;h2 id=&#34;operating-systems-and-app-compatibility&#34;&gt;Operating Systems and App Compatibility&lt;/h2&gt;
&lt;p&gt;Do you remember when it mattered a lot more which operating system
you ran?&lt;/p&gt;
&lt;p&gt;Nowadays, most of my personal time on the computer is spent on the web
browser, doing my writing on a &lt;a href=&#34;https://docs.google.com/&#34;&gt;website&lt;/a&gt;,
my TV watching on a &lt;a href=&#34;https://www.netflix.com/&#34;&gt;website&lt;/a&gt; and even my
&lt;a href=&#34;https://www.rememberthemilk.com&#34;&gt;TODO lists&lt;/a&gt;.  I look at the bottom
of the screen on my non-work computer, the MacBook I’m using to type
this, and I see a slew of icons for various apps: a messenger app, a
mail app, a calendar app, a spreadsheet, a word processor, all in all
standard computer fare, but not getting much use compared to that Google
Chrome icon. As a result, unless we’re doing specialized tasks, like
programming (as I do for work) or CAD or photo-editing, apps besides
the browser is not the &lt;a href=&#34;https://xkcd.com/934/&#34;&gt;big deal it used to be&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But once, it was a huge deal. Every computer user had several different
apps in their workflow, and using an alternative operating system (as
macOS once was) risked not being able to find appropriate equivalent
apps, and possibly not even being able to read documents that would be
in “Windows formatting.” There was tremendous social pressure to use
the same software as other people, to the extent that this
&lt;a href=&#34;https://www.xkcd.com/111/&#34;&gt;webcomic&lt;/a&gt; rang true.&lt;/p&gt;
&lt;p&gt;Therefore, every serious personal computer application existed as
a Windows program, specifically a Windows program that ran on Intel
(or Intel-compatible) processors (known as “Wintel,” especially by
those who criticized it as a monopoly). A company would support other
types of computers only as an after-thought. And at that time, apps were
distributed on CDs and stored on physical media. It was common to have an
old version of an app lying around, not be able to receive live updates
for it, and to expect it to run on a newly-purchased computer, unmodified.&lt;/p&gt;
&lt;p&gt;In such an environment, compatibility was key to profits. Each new
Intel processor, and each new version of Windows, had to support all
the apps that could run on the previous version. There was no higher
priority. For years after Windows 95, since before Windows 95 was
even released, Microsoft had another operating system, Windows NT,
that was far more stable and technically superior. But Windows 95
was more similar to Windows 3.1 before it, and supported more apps,
so until Microsoft could get Windows NT to run all those other apps,
it was stuck with the inferior product. Eventually, 6 years later,
Microsoft came out with a version of Windows NT able to run 95 apps:
Windows XP. Even that transition was gnarly.&lt;/p&gt;
&lt;p&gt;The Intel side of the “Wintel” monopoly was similar. To this day,
a modern Intel processor is capable of running MS-DOS programs from the
80s directly, without requiring any emulation layer in the operating
system or any modifications to those programs. The antiquated 16-bit
instructions that comprise those programs will still be interpreted by
the modern hardware, which also supports countless other compatibility
modes for various eras of the processor history. And this is true not
only for the Intel processors that power Windows PCs, where it makes some
amount of sense to support all the Microsoft ecosystems of years past,
but also on Macs, where this history is much shallower.&lt;/p&gt;
&lt;h2 id=&#34;processor-design-and-instruction-set-architecture&#34;&gt;Processor Design and Instruction-Set Architecture&lt;/h2&gt;
&lt;p&gt;See, Intel is more than just a company. Intel is also an instruction set
architecture, also known as Intel64 (or Intel32 for 32 bit versions) or
x86 (sometimes x64 for 64 bit versions). When applications are prepared
to run on Intel, they are (traditionally) compiled to a file containing a
sequence of instructions. The meaning of each instruction is determined
by complicated standards, and the hardware of the processor must take
these instructions, and actually perform the designated operations.&lt;/p&gt;
&lt;p&gt;The amount of complexity involved in the meanings of these instructions,
or the instruction set architecture (ISA) is large. Intel’s ISA was
documented in 3 paperback volumes back when I was a child in the early
aughts when my parents were gracious enough to order the set for me. It
has only grown more gnarly since then.&lt;/p&gt;
&lt;p&gt;Because of the vast compatibility requirements that Intel in particular
historically has faced, their ISA, has never been redesigned from scratch
since the 80’s. This means that, instead of having every instruction be
a fixed length of say, 4 bytes, Intel instructions can range from 1 to 15
bytes. Some of them do simple things like adding two numbers together,
whereas others do more complicated things like copying an entire string
of characters. Many of the design choices would never be made by a modern
engineer, but Intel is stuck with them for historical reasons.&lt;/p&gt;
&lt;p&gt;But Intel hasn’t been able to clean this up, for the same reason that
“Wintel” customers can’t switch from Intel: Any clean-up would
mean old apps would not be able to run on the new computers. When Intel
did attempt this, with Itanium, the world wasn’t ready, even though
Intel tried to leverage the already-difficult transition to 64-bit as a
reason to get people to switch to a completely new architecture. Even
worse, any clean-up would mean that Intel would have to compete with
other companies as equals, whereas now there is only one other company,
AMD, that is allowed (for historical reasons) to design Intel-ISA
processors. Embarrassingly, it was AMD that actually convinced everyone
to switch to 64-bit, by providing a much more gradual transition to a
64-bit ISA far more similar to the existing 32-bit one.&lt;/p&gt;
&lt;p&gt;Processor architectures with such convoluted ISAs are referred to as
CISC, for Complex Instruction Set Computing. All of this complexity must
be implemented using more complex hardware. Intel processors come with
decoders to break down over-complicated instructions into smaller pieces,
reorder buffers to optimize on-the-fly which pieces can be done when,
and extra circuitry to handle all of the various compatibility modes that
are necessary to support old software. All of this constrains processor
design and, very specifically, draws extra power.&lt;/p&gt;
&lt;p&gt;What’s the alternative? The transition to mobile, to phones and tablets,
gave computing something of a fresh start. No one ever expected their
“Wintel” apps to run on a phone, and so when initial iPhones and
Androids came out, new apps were written from scratch. Those would be
written for whatever processor architecture Apple and Google chose, and
they chose a more modern, less-CISC ISA: ARM. ARM stands for Advanced
RISC Machine, where RISC, or Reduced Instruction Set Computing, is the
opposite of CISC.&lt;/p&gt;
&lt;p&gt;The ARM ISA, which unlike Intel’s is available for any company to
license and design their own compatible processors, takes a moderate
position in the historical RISC/CISC wars, and require in any case far
less decoding circuitry than Intel processors require. When Intel tried
to make Intel-ISA processors for phones and lightweight laptops, the Atom
processors, it was a failure. The decoder got in the way of achieving a
good combination of performance and power consumption, and the resulting
phones were either unacceptably slow or unacceptably low in battery life.&lt;/p&gt;
&lt;p&gt;And Apple Silicon is Apple’s branding for their ARM ISA processors,
supporting the ARM ISA with Apple’s proprietary processor
design. They’re bringing the benefits of phones to the PC world.&lt;/p&gt;
&lt;h2 id=&#34;new-modes-of-app-development&#34;&gt;New Modes of App Development&lt;/h2&gt;
&lt;p&gt;So the “Wintel” monopoly and Intel in general never jumped from
the PC world to mobile, and as a result we have our cool, fanless,
high battery life but high performance phones we have today. But why,
then, do Macs, which never ran Windows programs, use Intel processors
to begin with? Why are they switching now? And why is this a turning
point for PCs in general?&lt;/p&gt;
&lt;p&gt;Well, for one thing, it’s not entirely true that Macs don’t
run Windows programs. A key reason why Apple switched from Power to
Intel in the first place was that Macs can run Windows programs: by
either running a version of Windows simultaneously to running macOS
(&lt;a href=&#34;https://www.parallels.com/)&#34;&gt;https://www.parallels.com/)&lt;/a&gt;, or, more simply, by rebooting the same
computer into Windows, which runs on Mac just as well as on any other
type of PC. When Intel Macs first came out, this was a decisive feature
for many switchers, nervous to abandon app compatibility.&lt;/p&gt;
&lt;p&gt;And at the time, Intel was the best processor manufacturer in existence,
so that Intel processors with their flaws were still better (as they were
produced through better manufacturing processes) than the POWER-based
RISC processors Apple was previously using. Get better processors and
get some level of Windows-compatibility: the decision was clear for
Apple at the time.&lt;/p&gt;
&lt;p&gt;But now, Windows compatibility is not important to hardly any Mac
users. And there are a number of reasons for that. Nowadays, a lot of
software is not translated to machine code, the level at which ISAs
are relevant. A lot of software is delivered to us via the browser,
where a portion runs on servers in the cloud and a portion is written in
Javascript, and then either interpreted in that form, or translated to
the ISA of the computer live by the browser. Once the browser supports
an ISA, all websites come with it.&lt;/p&gt;
&lt;p&gt;And even for apps, many of them are written in higher-level
languages that use a virtual machine or Just-In-Time compilation
to be processor-architecture neutral. These programming language
technologies matured after Intel had already become stuck with its
backwards-compatibility advantage, and apps written with them also are
easily portable, which is to say, brought to a new ISA. Once the Java
virtual machine (for example) is ported to ARM, all Java programs come
with it.&lt;/p&gt;
&lt;p&gt;And even for programs that are compiled in a traditional fashion,
written in an old-fashioned compiled programming language like C or C++
(or the Apple-specific Objective-C or Swift), ISA compatibility is no
longer the issue it once was. These languages have evolved over time to
make it easier to re-target ISAs, and programmers nowadays are better
trained in writing their code in such a way that it can be compiled
for any ISA. Creating an ARM version of a Mac app is just a switch in
the compilation system, and maybe finding a few obscure bugs where the
differences matter a little more deeply.&lt;/p&gt;
&lt;p&gt;And once the new version is made, Android and iOS both transitioned
from 32-bit to 64-bit ARM, requiring new apps to be built, and we as
customers hardly noticed. Developers quietly prepared 64 bit versions of
our apps, and when we upgraded to 64-bit compatible phones, we didn’t
notice that the app store sent us a different version. After all, we get
updated versions of apps from the app store all the time. As long as the
developer can adjust, the end user just has to do some more downloading &amp;ndash;
cheap and easy in an era of widespread broadband.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;And so what does Apple lose out on for the Apple Silicon Macs? The ability
to boot Windows is now more of a liability than an asset for them. Old
programs will rapidly be ported. Due to modern technology, which allows
us to translate between ISAs on the spot, emulating Intel on the new Macs
is often faster than running the Intel programs directly on the old Macs.&lt;/p&gt;
&lt;p&gt;As users, we might be mildly frustrated by it. I certainly will be
a little worried about buying such a computer until I know that some
version of Linux will work smoothly on it &amp;ndash; Linux on ARM is currently
very much so a second-class citizen in the PC Linux world.&lt;/p&gt;
&lt;p&gt;But the advantages are great. No longer constrained by hardware decoders,
Macs will cheat the old trade-off between computational power and battery
life, and get to have their cake and eat it too, at least for one round
of abrupt improvement for the transition. And because now the PC and
phones use the same processor architectures, iOS and iPadOS apps will
now work on macOS as well, saving time for writers of tablet applications.&lt;/p&gt;
&lt;p&gt;And other PC manufacturers will end up having to notice. Windows on ARM
exists already, though it is currently obscure. If Microsoft can cultivate
as modern an ecosystem as Apple, where a combination of emulation and
streamlined distribution make it easy to get ARM versions, these new
Macs might start an ARMification trend.&lt;/p&gt;
&lt;p&gt;This spells (long-term) doom for Intel. Their business model is tied
to their ISA, on the premise that no one can afford to switch away from
the most popular ISA, that everyone is locked in. This was never true for
mobile, in spite of Intel’s best efforts, and as Apple is demonstrating,
it also hasn’t really been true for PCs for a while either.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Components of a Modern Operating System</title>
      <link href="https://www.thecodedmessage.com/posts/os_tour/" />
      <id>https://www.thecodedmessage.com/posts/os_tour/</id>
      <updated>2019-07-11T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;In &lt;a href=&#34;https://www.thecodedmessage.com/posts/operating_system/&#34;&gt;previous&lt;/a&gt; &lt;a href=&#34;https://www.thecodedmessage.com/posts/current_os/&#34;&gt;posts&lt;/a&gt;,
we discussed historic operating systems and where various OS features come
from, but we only gave a brief overview of how they worked.&lt;/p&gt;
&lt;p&gt;Now that we have a modern operating system&amp;rsquo;s full complement of features,
we can look at what components need to exist in a modern operating system
to get those features. As discussed with MS-DOS, an operating system,
even today, is partially code, and partially conventions, like file
formats or rules of good behavior &amp;ndash; the difference being, that modern
operating systems have more ability to enforce some of these
conventions.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;In &lt;a href=&#34;https://www.thecodedmessage.com/posts/operating_system/&#34;&gt;previous&lt;/a&gt; &lt;a href=&#34;https://www.thecodedmessage.com/posts/current_os/&#34;&gt;posts&lt;/a&gt;,
we discussed historic operating systems and where various OS features come
from, but we only gave a brief overview of how they worked.&lt;/p&gt;
&lt;p&gt;Now that we have a modern operating system&amp;rsquo;s full complement of features,
we can look at what components need to exist in a modern operating system
to get those features. As discussed with MS-DOS, an operating system,
even today, is partially code, and partially conventions, like file
formats or rules of good behavior &amp;ndash; the difference being, that modern
operating systems have more ability to enforce some of these
conventions.&lt;/p&gt;
&lt;p&gt;These conventions are still important. Linux is considered a version of Unix
by the original authors of Unix &amp;mdash; even though for legal and trademark reasons
it is not &amp;mdash; not because it has any code in common (it doesn&amp;rsquo;t), but because
it follows the conventions of Unix.&lt;/p&gt;
&lt;p&gt;So on our tour we&amp;rsquo;ll discuss both more concrete software components
that are a body of code, and also conventions that hold the operating
system together at various levels.&lt;/p&gt;
&lt;h2 id=&#34;the-kernel&#34;&gt;The Kernel&lt;/h2&gt;
&lt;p&gt;One big problem with the MS-DOS model is that a program could circumvent
its interfaces. It could directly access hardware if it wanted
to, without regard to the OS&amp;rsquo;s file system code, setting the file system
conventions in stone. A program could install your own procedures to run when
hardware events happened, its own &lt;em&gt;interrupt handlers&lt;/em&gt;, and the system
wouldn&amp;rsquo;t stop you.&lt;/p&gt;
&lt;p&gt;This wasn&amp;rsquo;t really a limitation of MS-DOS per se, but of the 8086,
the processor MS-DOS was designed for. If code is running on an
8086, it can execute any of an 8086&amp;rsquo;s instructions, no matter what.
A more modern processor &amp;ndash; including Intel&amp;rsquo;s later processors and
therefore most of the processors MS-DOS ran on in practice &amp;ndash;
has a distinction between &lt;em&gt;user&lt;/em&gt; mode and a &lt;em&gt;supervisor mode&lt;/em&gt;, which
will only allow hardware access to take place while the
processor is in the supervisor mode (also known as &lt;em&gt;kernel mode&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Application code, regular program code, will all run in user mode.
A lot of operating system code can as well: How much code should
be actually run in kernel mode as opposed to user mode is a
complicated design decision. Certain instructions in the processor
are only allowed in kernel mode, including those that control what
memory is &lt;em&gt;mapped&lt;/em&gt;, or currently accessible, those that install
interrupt handlers, and those that control which pieces of hardware
the processor is currently permitted to send data to.&lt;/p&gt;
&lt;p&gt;In MS-DOS, all code was functionally in kernel mode &amp;ndash; or more precisely,
in a legacy mode of the Intel processor that emulated a time when the
distinction didn&amp;rsquo;t exist, and all instructions were always allowed. A
separate mode, referenced above, put the processor into a different legacy
mode where it also acted like an 8086, but invoked special procedures
whenever the program executed a privileged instruction, basically allowing
MS-DOS to run inside a sandbox inside a larger operating system (I&amp;rsquo;ve
used both Windows and Linux as the larger operating system in this model).&lt;/p&gt;
&lt;p&gt;Unlike MS-DOS, a modern operating system will have controls on what is
allowed to run in kernel mode, and everything else must run instead in
user mode. The body of code that is intended to run in kernel mode is
known as &lt;em&gt;the kernel&lt;/em&gt;, or &lt;em&gt;kernel code&lt;/em&gt;. If someone asks you what an
operating system kernel is, this is the answer &amp;mdash; the set of code that
runs in kernel mode. It might be stored in multiple files, it might be
all in one file, and it might be divided into internal components with
different names, but that is what the kernel is.&lt;/p&gt;
&lt;p&gt;So, if only the kernel can access hardware directly, and most code isn&amp;rsquo;t
allowed to be in the kernel, then how does a normal application access
the hardware? Well, instead of accessing it directly, the application
must ask the operating system to do the thing on its behalf. Just as
the operating system can install procedures as interrupt handlers,
for the processor to trigger in case of hardware events, it can
install system call handlers, procedures that run in kernel mode
but can be invoked in user mode. These procedures will be designed
to make sure that the user program in question is accessing the
hardware in an acceptable way, and only perform the operation
if it is allowed &amp;mdash; possibly, there will be no reasonable
way for the program to even request an impermissable hardware
operation.&lt;/p&gt;
&lt;p&gt;This is a key distinction between MS-DOS and even older Mac operating
systems: whereas all operating systems provide abstractions, those with
an OS kernel can provide &lt;em&gt;mandatory&lt;/em&gt; abstractions. This means that,
if you want to support new features, you can change what the system
calls do, and all programs will automatically adapt to it. If your
file system is suddenly stored over the network, programs won&amp;rsquo;t get
tripped up trying to access the hard drive directly. The operating
system can insert itself at the level of the system call interface
and redirect your request to the network instead &amp;mdash; if the
system call interface is well-designed.&lt;/p&gt;
&lt;h2 id=&#34;the-application-binary-interface&#34;&gt;The Application Binary Interface&lt;/h2&gt;
&lt;p&gt;So let&amp;rsquo;s say you have a Windows program, and you want to run it on Linux.
Or you have a Linux program, and you want to run it on macOS, which
are both Unixes and have a better chance of being compatible. It won&amp;rsquo;t
work &amp;mdash; certainly not &amp;ldquo;out of the box.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Why? Well, one reason is mentioned above. Different operating systems
provide different ways of organizing the functionality of the computer
into system calls. They provide different abstractions, which are nowadays
mandatory.&lt;/p&gt;
&lt;p&gt;For example, on Windows, different drives use different letters, and
volumes shared over the network are also assigned letters, e.g. the famous
&lt;code&gt;C:&lt;/code&gt; drive, or &lt;code&gt;A:&lt;/code&gt; for floppies, or &lt;code&gt;X:&lt;/code&gt; maybe for a shared drive. On
Unixes, different volumes &amp;mdash; Unix doesn&amp;rsquo;t use the word &amp;ldquo;drive&amp;rdquo; as often
&amp;mdash; are assigned different &lt;em&gt;mount points&lt;/em&gt; within the system.  One volume
might be &lt;code&gt;/&lt;/code&gt;, and another at &lt;code&gt;/home&lt;/code&gt;, and another &lt;code&gt;/mnt/network&lt;/code&gt;, and
it would provide the illusion of one unified hierarchical filesystem.
Imagine if you had &amp;mdash; as a simplified example &amp;mdash; a system call to
assign a drive letter to a network share. This would make sense with
the Windows abstraction, but what would it even mean on Linux?&lt;/p&gt;
&lt;p&gt;Another reason has to do with how programs are stored on the drive.
Programs are not just a list of instructions for the processor.
They usually have to be loaded at a particular address. Memory
must be mapped for them to store their variables &amp;mdash; and how much
memory varies program by program. They have to load libraries
of other procedures, which may be stored separately through
&lt;em&gt;dynamic linking&lt;/em&gt; in a &lt;em&gt;shared library&lt;/em&gt; (Unix terminology, &lt;code&gt;.so&lt;/code&gt;)
or a &lt;em&gt;dynamically loadable library&lt;/em&gt; (Windows terminology, &lt;code&gt;.dll&lt;/code&gt;),
which is also going to be mapped at a certain address in
memory according to arcane rules.&lt;/p&gt;
&lt;p&gt;Different operating systems have different &lt;em&gt;binary file formats&lt;/em&gt;, or
formats for storing programs (which are often called &lt;em&gt;binaries&lt;/em&gt; when stored
on disk, although everything a disk stores is in binary).  Linux has
ELF (Executable and Linkable Format, which can use DWARF to store its debugging
information), Windows has PE (standing for portable executable, which falsely
implies it runs on more systems besides just Windows). Different Unix
varieties have different binary file formats &amp;mdash; it&amp;rsquo;s something that
evolves over time. Some operating systems &amp;mdash; many operating systems +++
have different binary formats supported, for backwards-compatibility,
or for simulating other operating system, or even for different types
of programs or programs written in different program languages.&lt;/p&gt;
&lt;p&gt;The combination of the set of available system calls, the available
libraries on the system, and the format of the binaries, constitute
the main blocker to compatibility between operating systems, the
&lt;em&gt;ABI&lt;/em&gt; or &lt;em&gt;application binary interface&lt;/em&gt;, an acronym or phrase that is
intended to sum up everything that needs to match for &lt;em&gt;binary
compatibility&lt;/em&gt;, the ability to run binaries (compiled programs
as they are usually stored for running) from one system on
another.&lt;/p&gt;
&lt;h2 id=&#34;the-application-programming-interfaces&#34;&gt;The Application Programming Interface(s)&lt;/h2&gt;
&lt;p&gt;There are other kinds of compatibility. Even though you can&amp;rsquo;t take the
Windows version of a program and run it on macOS, we see plenty of programs
that have versions available, right on their website, for both Windows and
macOS. Similarly, most phone apps are available in both the iPhone and Android
stores.&lt;/p&gt;
&lt;p&gt;In some cases, that&amp;rsquo;s because there&amp;rsquo;s two applications, written by
different teams, that solve the same problem (and have the same branding)
or interact with the same servers (which run on Linux and where all the
complex stuff happens anyway). But in others, it is substantially the
same program that is run on both systems.&lt;/p&gt;
&lt;p&gt;In many cases, though, that&amp;rsquo;s because the versions were written sharing
a lot of the same &lt;em&gt;source code&lt;/em&gt;, with a layer of software interfacing
between that and the specific operating systems in question. This
might be because there were different teams (or people) who maintained
compatibility layers proprietary to that company (this is what many
traditional software vendors do and have done in the past). Nowadays,
it is more likely because there was a programming language that has
implementations available on both platforms, and versions of the same
library functions available for each (which is what Java was originally
famous for and what Python does today).&lt;/p&gt;
&lt;p&gt;This is fairly common for relatively new programming languages, where
the program language was written after the operating system was already
around, and where part of the point of the programming langauge is to
support multiple operating systems for your programs. For programming in
an operating systems &amp;ldquo;native language,&amp;rdquo; so to speak &amp;ndash; for programming
in C on Linux or Objective-C on macOS, it&amp;rsquo;s a bit harder: An Objective-C
macOS program is unlikely to be particularly portable to anything (except
maybe iOS).&lt;/p&gt;
&lt;p&gt;There are some exceptions to this. A program written for Linux can usually
be made to run on macOS, because of their common Unix heritage. Even
though Linux and macOS have different ABIs or application &lt;em&gt;binary&lt;/em&gt;
interfaces, they have very similar &lt;em&gt;APIs&lt;/em&gt;, which stands for application
&lt;em&gt;programming&lt;/em&gt; interface (NB: This term means something different in a
modern, web programming context). This means that, although they are not
very binary compatible, they are &lt;em&gt;source compatible&lt;/em&gt;, or close to it,
which is to say, that there are few changes to the source code you would
have to make to a Linux C-based program to make it work on macOS. It
might be invoking different system calls with different identification
numbers when you write the code to open and read a file, but that code
looks exactly identical on both platforms, possibly something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    // Simultaneously both Linux and macOS C code
    int file_descriptor = open(filename, O_RDONLY);
    ssize_t res = read(file_descriptor, buffer, sizeof buffer);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As you might have picked up, this applies to only a subset of the
functionality. Any GUI-related code would not enjoy this level of
portability &amp;mdash; macOS and Linux have very different GUIs. More likely
this is code intended to be primary run on servers (and perhaps run
on a Mac for testing), or code used by programmers (like &lt;code&gt;git&lt;/code&gt; and
other development tools designed to be run from the command line)
or by scientists or other researchers (like the non-GUI components
of Matlab and R or even Python).&lt;/p&gt;
&lt;p&gt;The baseline API that all Unix-like operating systems have in common is
called POSIX. Operating systems are certified as brand-name Unixes based
on a bigger API specification, with more functions and more requirements,
called X/Open &amp;mdash; which is to say that Unix is defined not by where the
code originated nor by its ABI, but rather by its C programming API. To
be clear, an operating system based on Linux could probably pass X/Open
and become legally a Unix, but nobody has decided to spend the time and
money to try and make this certification happen. It is the fact that
it is as close as it is that leads many of the original developers of
Unix to consider Linux &amp;ldquo;a Unix,&amp;rdquo; as it is this API that ties the Unix
family together.&lt;/p&gt;
&lt;p&gt;The Unix/Linux API is so important that Microsoft needed to add it to
Windows and that macOS&amp;rsquo;s native use of it is considered a selling point,
especially for developers. This is because a lot of server software
and programmer tools assumes this Unix API (as well as, for example,
Unix filesystem conventions), or else it assumes Linux which has few
enough peculiar features to make much of a difference. Most users are
isolated from this, but anyone who has to write software to run on servers
(which is most programmers) or use programmer tools (which is
all programmers) is very keenly aware of this.&lt;/p&gt;
&lt;p&gt;This Unix API is a core API provided by the operating system itself,
the official, default way for applications to be written, but the other
programming interfaces discussed above are also APIs. That is to say, Java
comes with its own API that it brings to every operating system it runs
on, leading to it its once-famous &amp;ldquo;write once, run everywhere&amp;rdquo; slogan.&lt;/p&gt;
&lt;p&gt;The most important API for application compatibility today is something
irrelevant to most of this discussion though, and relatively new
to operating system history. Most applications that run on your
computer today run in Javascript in the very controlled environment
of a web browser. Part of what a web browser does is provide a stable,
cross-platform (that is, multi-operating system) API for the portion of
a web application that runs on each local computer. This interface is
so important that many modern apps for phone and desktop are internally
implemented as running inside a web browser, or something that resembles
a web browser in more or fewer ways.&lt;/p&gt;
&lt;h2 id=&#34;the-system-librarylibraries&#34;&gt;The System Library/Libraries&lt;/h2&gt;
&lt;p&gt;We spoke in the last section about the POSIX or Unix APIs. There are
a lot of functions that a Unix-like operating system is expected to
provide functionality for, in a lot of domains. Some, like opening or
reading files, more or less have to be implemented as system calls,
at least the most basic versions of them. Others, like calculating a
square root, are simply procedures that run in user mode. Still others,
like printing a number to the console, have to involve some system calls
(to output text to the screen) but also some computation appropriate
for user mode (to convert the number into a string of digits).&lt;/p&gt;
&lt;p&gt;To provide these functions, Unix-like systems will provide their
own version of the C standard library. On most Unix systems, this is
maintained by the same organization that maintains the kernel, with Linux
as the major exception. The set of POSIX APIs that a Unix will maintain is
implemented through the standard library &amp;mdash; some of them system calls,
some of them implemented in user mode, and the programmer doesn&amp;rsquo;t have
to care which.&lt;/p&gt;
&lt;p&gt;In fact, between versions of the same operating system, and certainly
between different operating systems, what used to be a system call might
become a wrapper around a new, more advanced system call interface, where
basically the library is providing compatibility with other versions
of the same operating system. This is especially important in Unix, as
there&amp;rsquo;s a lot of calls descended from different branches of the family
tree with slightly different &lt;em&gt;semantics&lt;/em&gt;, or subtleties of meaning,
all of which are used by modern programmers, who can use whichever is
more convenient to them or simply preferred.&lt;/p&gt;
&lt;p&gt;The library enables source compatibility and API compatibility, even
in situations where the kernel itself is much more particular about
its system calls. The question is, where does the ABI compatibility
layer go? On Linux, the kernel itself is responsible that its updates
don&amp;rsquo;t break working programs, and its founding and lead developer Linus
Torvalds is adament and dictatorial &amp;mdash; sometimes abusively so &amp;mdash; about
this rule.  If you want a system call to behave differently, what you
do in these situations is actually make a new system call that behaves
the new way, and leave the old system call available at the old number
in case a program wants to use it.&lt;/p&gt;
&lt;p&gt;However, all modern operating systems support dynamic linking.
This means that the libraries and the main program binary are stored
in separate files, and the main program binary specifies the &lt;em&gt;names&lt;/em&gt;
of the functions it calls, rather than using numbers. If all programs
use dynamic linking, and only call system calls through the library,
you can update the library to use a different system call interface,
and change the kernel along with it. This is what macOS requires +++
while it is technically possible on macOS to bypass the library to call a
system call, the attitude is, that if you do that, you should not expect
your program to work as expected. The operating system will still ensure
it won&amp;rsquo;t break other programs, but will not guarantee your program to
behave the same from version to version.&lt;/p&gt;
&lt;p&gt;These are two vastly different approaches to maintaining ABI
compatibility. In making the standard library part of the ABI, macOS
doesn&amp;rsquo;t allow &lt;em&gt;static linking&lt;/em&gt;, where all code in a process comes from a
single file and a copy of the libraries are placed into the main binary
when you compile it. It&amp;rsquo;s not only not recommended &amp;mdash; by default, it
will not even run statically compiled binaries. If you want to have an
alternative version of the C library, you can&amp;rsquo;t.  If you&amp;rsquo;re writing in
another programming language that doesn&amp;rsquo;t work like C, you still have
to go through the C library to talk to the operating system, which isn&amp;rsquo;t
written necessarily with other programming languages in mind.&lt;/p&gt;
&lt;p&gt;But, the kernel developers have the ability to control their system call
interface better. If they want to add a new system call, they can make
their old way of doing it call the new system call, and keep the kernel
cleaner. This is important because all code in the kernel constitutes a
greater level of vulnerability &amp;mdash; if a kernel accesses unmapped memory,
it&amp;rsquo;s generally a &lt;em&gt;kernel panic&lt;/em&gt; (the Blue Screen of Death on Windows),
but a user process will just crash with a &lt;em&gt;segmentation fault&lt;/em&gt;. Or worse,
if you exploit a vulnerability in the kernel and manage to manipulate
it into doing something for you it wasn&amp;rsquo;t supposed to, it can literally
do everything on your computer. This as opposed to a regular program,
which still can only do things the kernel permits it to.&lt;/p&gt;
&lt;p&gt;Linux, on the other hand, has more flexibility. You can have statically
linked files, your own C library, or libraries specialized for other
programming languages. You can avoid all the baggage that comes with
its implementation of the C library functions that have nothing to do
with system calls.&lt;/p&gt;
&lt;p&gt;Honestly, my preference would be somewhere in between. I&amp;rsquo;d have a smaller
library than &lt;code&gt;libc&lt;/code&gt; &amp;mdash; maybe &lt;code&gt;libsystem&lt;/code&gt; &amp;mdash; that every program would
be automatically dynamically linked to.  This would be for things that
are usually implemented as system calls, or that were system calls in
previous versions of the operating system. These would be things that any
programming language might reasonably want to use.  The more C-specific
stuff would be relegated to its own, more general library. &lt;code&gt;libsystem&lt;/code&gt;
would be as simple as possible.&lt;/p&gt;
&lt;p&gt;Libraries that form part of the main API and that are provided with
any installation of the operating system definitely constitute
part of the operating system. Libraries that come bundled with
specific application or that exist to do certain program
tasks are not part of the operating system. Which count
as core operating system functionality is up to the operating
system vendor, but all operating systems come with at
least some libraries, to abstract their austere system
call interfaces into something that you can actually
program.&lt;/p&gt;
&lt;h2 id=&#34;the-shell-command-line&#34;&gt;The Shell (Command Line)&lt;/h2&gt;
&lt;p&gt;All modern (non-mobile) operating systems come with a command line
interface, whether on the computer or on the server. When you type
commands into the command line interface, it isn&amp;rsquo;t the kernel itself that
reads the line you typed and decides how to proceed. Instead, a separate
process does that. This process is key to the core job of an operating
system &amp;mdash; letting you run multiple programs and share resources between
them &amp;mdash; and therefore counts as part of the operating system, but is
also not part of the kernel.&lt;/p&gt;
&lt;p&gt;The concept of having the shell be a user process like any other was
actually one of the early innovations of Unix over other contemporary
operating systems. Before that, the kernel would often be responsible
for this. By removing it from the kernel, Unix allows different users
to use different shells, with different syntax for advanced features
like scripting or running commands conditionally on the results
of other commands. Even Windows has two shells now, traditional
&lt;code&gt;cmd&lt;/code&gt; and its newer &amp;ldquo;object oriented&amp;rdquo; PowerShell.&lt;/p&gt;
&lt;p&gt;All shells can run any terminal-oriented program, and usually can also
be used as a starting point to launch graphical programs when the system
supports it, i.e., when it&amp;rsquo;s a desktop OS and not a server OS.&lt;/p&gt;
&lt;h2 id=&#34;the-shell-gui&#34;&gt;The Shell (GUI)&lt;/h2&gt;
&lt;p&gt;Not all modern operating systems have GUIs. Remember that many computers
are servers (or embedded devices) where you don&amp;rsquo;t actually sit at a
monitor and keyboard &amp;mdash; where they likely don&amp;rsquo;t even have a monitor and
keyboard. But for those that do, the concept of shell can be generalized
to the program from which you run other programs.&lt;/p&gt;
&lt;p&gt;On macOS this is called Finder, and it dates back to the early pre-Unix
Macintoshes. On Windows this is called Windows Explorer. On Linux,
and other Unixes that share Linux&amp;rsquo;s user interface philosophy, there
are multiple &lt;em&gt;desktop environments&lt;/em&gt; available, each of which handles
program launching differently, and each of which usually comes bundled
with a &lt;em&gt;window manager&lt;/em&gt; that draws decorations around your windows and
allows you to minimize, maximize, tile or overlap them. This leads to
a rich diversity of Linux systems in their appearance and casual
use.&lt;/p&gt;
&lt;p&gt;It is usually these graphical shells, these desktop environments,
that form your mental image of what an &amp;ldquo;operating system&amp;rdquo; is. But that
can be misleading. Linux can have one of many different graphical user
interfaces &amp;mdash; or none at all &amp;mdash; and most of what makes Linux Linux
will be the same.&lt;/p&gt;
&lt;p&gt;So what about Linux, Android, and ChromeOS? Are they the same operating
system then, because they all share the same kernel? Linux and Android
differ at a deeper level than a shell. An Android program can&amp;rsquo;t be run
on a normal Linux distribution without some layer to accommodate the
additional libraries, and vice versa. The different desktop environments
on Linux all tend to be compatible with X, a unified protocol for
UI interactions, and the many command line shells all run the same
set of command line utilities, but Android display is not done through X.&lt;/p&gt;
&lt;p&gt;In the case of ChromeOS, the situation is different. The shell in ChromeOS
is basically the Google Chrome browser, which is the same thing that
on other platforms acts as a single program in a larger context. So
many programs nowadays are run through the medium of the browser that
it&amp;rsquo;s become more than a single program in practice &amp;mdash; many people only
open the browser on their computer and use that for all or almost all of
their computer-oriented tasks: one tab open to GMail for their e-mail;
one tab open to Twitter; one to Spotify, to play the background music;
another to Slack to talk with their colleagues; and finally yet another
to Google Docs to do the actual productive work of writing whatever it
is they&amp;rsquo;re writing. Is Chrome a shell in practice on these other operating
systems? Is it just an annoyance for some users that there is the taskbar
to switch between multiple programs, in addition to the tab bar to switch
between multiple websites? Google certainly thinks this is true for some
users, and it is for them that the Chromebook is intended.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>Operating Systems Part II: Modern Operating Systems</title>
      <link href="https://www.thecodedmessage.com/posts/current_os/" />
      <id>https://www.thecodedmessage.com/posts/current_os/</id>
      <updated>2019-05-26T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;We use operating systems all the time in our life, whether designed for
a computer, a phone, or for a server we&amp;rsquo;re more indirectly interacting
with, but a lot of people don&amp;rsquo;t know very much about what connects
the different systems we use, and what makes them distinct. We
discussed fundamental concepts of operating systems in the &lt;a href=&#34;https://www.thecodedmessage.com/posts/operating_system/&#34;&gt;last
post&lt;/a&gt;, so in this post we will discuss
how some of the same concepts apply to modern operating systems, going
over them one at a time.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;We use operating systems all the time in our life, whether designed for
a computer, a phone, or for a server we&amp;rsquo;re more indirectly interacting
with, but a lot of people don&amp;rsquo;t know very much about what connects
the different systems we use, and what makes them distinct. We
discussed fundamental concepts of operating systems in the &lt;a href=&#34;https://www.thecodedmessage.com/posts/operating_system/&#34;&gt;last
post&lt;/a&gt;, so in this post we will discuss
how some of the same concepts apply to modern operating systems, going
over them one at a time.&lt;/p&gt;
&lt;h2 id=&#34;macos&#34;&gt;macOS&lt;/h2&gt;
&lt;p&gt;Unix moved on from controlling dumb terminals to having several
graphical user interfaces. When Steve Jobs was fired from Apple in
1985, he started a company called NeXT to develop NextSTEP, a version
of Unix with graphical user interface ideas, some from his work with
the Macintosh, some developed independently:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/next.png&#34; alt=&#34;NeXT&#34;&gt;&lt;/p&gt;
&lt;p&gt;When Apple was struggling to bring its operating system into the modern
era, when Mac OS System 9 was still using cooperative multitasking,
Apple bought NeXT and brought Steve Jobs back into leadership to turn
NextSTEP into the next version of Mac OS, then called Mac OS X for
the Roman numeral 10. In spite of superficial similarities to previous
versions &amp;ndash; the NeXT interface was changed to look more like previous
Mac OS systems &amp;ndash; and application compatibility (which was bolted on
by running Mac OS System 9 as a single process within Mac OS X, which
shows how much more sophisticated Mac OS X really was), the new version
was completely different software descended from the original AT&amp;amp;T Unix.&lt;/p&gt;
&lt;p&gt;It used to be common wisdom in some IT-savvy crowds (including a Best
Buy salesman in my hometown when Mac OS X first came out) to claim that
Mac OS X was a version of Linux, but this is not true. Linux is one of
many operating systems that come from the Unix tradition, and Mac OS
is a different one, sharing much of the Unix core instead with FreeBSD,
a much less common version of Unix descended from the version developed
at UC Berkeley (BSD stands for Berkeley Software Distribution).&lt;/p&gt;
&lt;p&gt;For &amp;ldquo;desktop&amp;rdquo; computers, including laptops, macOS is now by far the
most installed brand-name Unix operating system, and even if you
include Linux in a broader category of Unix-like operating systems,
it still is the most popular one on the desktop.&lt;/p&gt;
&lt;p&gt;This is in spite of the fact &amp;ndash; or perhaps because of the fact &amp;ndash; that
macOS doesn&amp;rsquo;t really emphasize its Unix &amp;ldquo;underpinnings.&amp;rdquo; Its graphical
user interface is proprietary to Apple, and there&amp;rsquo;s often macOS-specific
libraries that circumvent or supercede equivalent Unix ones, especially
when focusing on the GUI applications.&lt;/p&gt;
&lt;p&gt;They also don&amp;rsquo;t invest a lot of resources into making their command line
interface friendly or powerful.  Most Unixes make it easier to install
new applications and frameworks via command line, and the command line
is not particularly well-integrated with their graphical interface,
to the point where it sometimes seems like their GUI is next to Unix
rather than being built on Unix.&lt;/p&gt;
&lt;p&gt;Finally, strangely for a Unix, Apple does not provide a server version
of its operating system, making it difficult for software developers for
Macs to be able to run server-side tasks like bulk automated testing on
the same environment as their workstation.&lt;/p&gt;
&lt;h2 id=&#34;ios-watchos-etc&#34;&gt;iOS, watchOS, etc.&lt;/h2&gt;
&lt;p&gt;iOS, watchOS, and their ilk are locked-down versions of macOS. Unlike
on macOS, each application is locked into its own directory and can
only access its own files, rather than being able to access any files
owned by the current user. The security features of Unix are applied
to isolate applications from each other rather than users, and the
user doesn&amp;rsquo;t really see the concept of the file system &amp;mdash; instead,
each app simply remembers information for the user, and presents
how its organized in its own way.&lt;/p&gt;
&lt;p&gt;Since only one application is visible at a time on many of these
devices, this gives it a feel similar to an old single-tasking
operating system, where each application is more its own universe.
Since they don&amp;rsquo;t visibly share a file system, the applications
also interact less with each other.&lt;/p&gt;
&lt;p&gt;The most scary thing about these operating systems is that they&amp;rsquo;re set up
to protect the owner of the device &amp;ldquo;from themselves.&amp;rdquo; Only Apple-approved
applications can be installed unless you jailbreak the device, which
voids the warranty. Apple constantly lobbies for jailbreaking to be
made illegal, they claim for the users&amp;rsquo; protection and to prevent users
from illegally copying apps, but also because they get a huge cut of all
sales done through iOS apps, which &lt;a href=&#34;https://newsroom.spotify.com/2019-03-13/consumers-and-innovators-win-on-a-level-playing-field/&#34;&gt;Spotify claims is against European
law&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;open-source-and-linux-on-the-desktop&#34;&gt;Open Source and Linux on the Desktop&lt;/h3&gt;
&lt;p&gt;The &lt;em&gt;open source&lt;/em&gt; movement, and its more opinionated cousin the &lt;em&gt;free software&lt;/em&gt;
movement, believe, to various extents, that it is valuable for software to
be &lt;em&gt;open source&lt;/em&gt; (or alternatively phrased &lt;em&gt;free as in speech&lt;/em&gt;). This means that
anyone can read the source code to the software, the version of it
that is human readable and editable by actual programmers. It also means
that anyone can make modified versions of it, and publish them, usually
with different branding. Some open source/free software licenses require
those modified versions to also be open source, while others allow them
to be proprietary, but in all cases, the fundamental nature of open
source software is that anyone can make their own version (given
sufficient programmers and time).&lt;/p&gt;
&lt;p&gt;Linux (sometimes called GNU/Linux because Linux technically only refers
to one part of the operating system, the &lt;em&gt;kernel&lt;/em&gt;) is an open source
reimplementation of Unix. It organizes software in the same way that Unix
traditionally would, is written so that Unix programs can treat it as yet
another version of Unix (of which there were already many incompatible
versions), and follows the design of Unix function call by function call,
command by command.&lt;/p&gt;
&lt;p&gt;Linux is a really big deal on the server, and as a component of the
Android operating system, as we&amp;rsquo;ll discuss later. It also is usable as
a desktop operating system in its own right. It inherited a graphical
user interface framework from Unix, known as the X Windowing System or
X Windows, and the open source movement inspired a lot of work writing
desktop environments within that framework, so that there could be an
entire modern desktop operating system that was open source.&lt;/p&gt;
&lt;p&gt;Throughout the 90&amp;rsquo;s and 2000&amp;rsquo;s, many Linux enthusiasts would hope that
someday, a completely open source operating system could reach common
use. Articles would be written claiming this was immanent, to the point
where it became an easy-to-mock cliche: &amp;ldquo;This is the year of Linux on
the desktop!&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Ultimately, though many companies tried, no one succeeded in arranging
for it to be pre-installed on mainstream desktops or laptops nor in
polishing it enough to convince the normal user to install it over what
their computer came with.  It is now a mostly-usable operating system,
should you choose to install it on your computer or buy a computer wiht it
pre-installed (which is an option some manufacturers now market towards
software developers). It is very well-suited for programming for reasons
we&amp;rsquo;ll discuss later, but still a bit awkward for things like setting up
Bluetooth or getting interesting features to work.&lt;/p&gt;
&lt;h2 id=&#34;windows-nt-xp-etc&#34;&gt;Windows NT, XP, etc.&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/gates.jpg&#34; alt=&#34;Bill Gates teaches how to count&#34;&gt;&lt;/p&gt;
&lt;p&gt;The history of Windows is intricate and arcane, and as a result, the Windows 10 of
today has virtually no code in common with the Windows 3.1 discussed above.
Similar to macOS, the Windows brand at some point was switched out with a
better operating system implementation, although in Windows&amp;rsquo;s case, that
implementation came from Microsoft&amp;rsquo;s &amp;ldquo;workstation&amp;rdquo; or &amp;ldquo;business&amp;rdquo; version,
Windows NT.&lt;/p&gt;
&lt;p&gt;Windows NT first came out shortly after Windows 3.1, and to avoid having a
Windows NT 1.0, which might sound less sophisticated than the existing
Windows 3.1, the very first version of Windows NT was called Windows
NT 3.1. It was based off of OS/2, a failed collaboration between Microsoft
and IBM to render MS-DOS obsolete, and it did not boot off of MS-DOS
nor use MS-DOS as a layer.&lt;/p&gt;
&lt;p&gt;Windows NT was designed from the beginning to support programs designed
for other operating systems. For more sophisticated operating systems,
programs have to go through the operating system to access hardware,
by invoking procedures that invoke operating system code, and different
operating systems provide different procedures. Based on what program
you were running, Windows NT could support many sets of procedures
(also known as APIs, but distinct from what API means on the web),
which it called &lt;em&gt;personalities&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Windows NT had from the get-go a personality to support Windows 3.1
versions, a 32-bit personality to support new Windows NT programs,
and a personality to support MS-DOS (which involved much more
machinery to give the program the illusion of more direct hardware
access). It also originally came with personalities for Unix and
OS/2, which eventually were removed.&lt;/p&gt;
&lt;p&gt;As Windows NT supported traditional Windows programs as a personality,
Windows and Windows NT co-existed for a long time. Windows 95, 98, and
Millenium were versions of Windows that still used MS-DOS as part of their
structure and which did not attempt strong security or rigor (though they
did adopt preemptive multitasking), while Windows NT 4.0 and Windows 2000
(aka NT 5.0) were versions of Microsoft&amp;rsquo;s more sophisticated operating
system, that could more or less run the same programs but focused on
stability and workplace use (with the presumption of professional IT
people), rather than Microsoft&amp;rsquo;s maniacal obsession with application
support and its easy-to-use brand.&lt;/p&gt;
&lt;p&gt;Eventually, in Windows XP, they made the switch. They risked worse
compatibility with really old applications (after all, the operating
system was completely switched out under the hood) in order to push
everyone towards their more modern operating system. Windows XP
was internally Windows NT 5.1 (and remember that Windows NT 3.1 was the first
one because it borrowed its number from the other OS called Windows),
and it replaced Windows 98 and Millenium as Microsoft&amp;rsquo;s flagship
consumer OS.&lt;/p&gt;
&lt;p&gt;Now, they don&amp;rsquo;t have to maintain two completely different operating
systems anymore. Their server OSes are still distributed separately,
but that is mostly for licensing and configuration reasons &amp;ndash; it&amp;rsquo;s
the same fundamental OS with different features enabled and different
auxiliary programs shipped. All in all, Microsoft has a simpler
tech architecture now that they&amp;rsquo;ve pushed everyone towards NT.&lt;/p&gt;
&lt;p&gt;This is a good place to clear up a common misnomer: the Windows command
line, in modern NT-based Windows, is not a version of MS-DOS. It is only
related to MS-DOS aesthetically: It has a similar look to the prompt (&lt;code&gt;C:\&amp;gt;&lt;/code&gt;,
&lt;code&gt;C:\WINDOWS\&amp;gt;&lt;/code&gt;), and similar commands to do similar things (&lt;code&gt;dir&lt;/code&gt; to list files
instead of Unix&amp;rsquo;s &lt;code&gt;ls&lt;/code&gt;). It is simply the Windows command line.&lt;/p&gt;
&lt;p&gt;Furthermore, support for MS-DOS binary compatibility was finally dropped
with the transition to 64-bit computing, not because Microsoft wanted to,
but because that would require a processor mode that AMD (and therefore
Intel) decided not to support in their hardware.&lt;/p&gt;
&lt;p&gt;You can&amp;rsquo;t, on the AMD64/Intel64 platform, have a 64-bit operating system
and a &amp;ldquo;virtual 8086&amp;rdquo; mode process, where the processor would have to
pretend to give you full control over the computer and pretends to be
an ancient MS-DOS-era computer while also giving final say to the real
64-bit operating system.  Intel32 supported this for 32-bit OSes and
16-bit MS-DOS compatibility, but I suppose the processor manufacturers
thought the 64-bit vs 16-bit compatibility bridge was just a bit too far.&lt;/p&gt;
&lt;h4 id=&#34;microsoft-windowss-monopolistic-market-dominance-and-the-open-source-movement&#34;&gt;Microsoft Windows&amp;rsquo;s Monopolistic Market Dominance and the Open Source Movement&lt;/h4&gt;
&lt;p&gt;In the 90&amp;rsquo;s and 2000&amp;rsquo;s, Microsoft had a lot of power through Windows.
It constituted a monopoly on consumer operating systems, and people were
scared to run other operating systems, because application compatibility
was a big deal. Only major application vendors had the resources to
support two operating systems (which was much harder in those days),
and so having a different operating system (especially an ill-supported
open source operating system like Linux) could cut you off from the rest
of the computing world.&lt;/p&gt;
&lt;p&gt;Microsoft used this power to control the application market,
because any application it bundled with the operating system would
drive any competitor out of business. It did this any time
it thought an application was interesting, including writing
its own web browser that drove Netscape out of business, finally
attracting a lawsuit that almost split Microsoft into multiple
companies. When that didn&amp;rsquo;t happen, it looked bad for the
computer industry.&lt;/p&gt;
&lt;p&gt;Microsoft also had corrupt relationships with computer manufacturers.
Deals were signed where the hardware vendors would have to exclusively
install Microsoft Windows on their computers, or else pay Microsoft
based on how many total computers they sold rather than how many
came with Windows. This meant that Microsoft didn&amp;rsquo;t actually have
to improve Windows to compete; they could just rest on their laurels
due to their shrewd and blatently illegal business dealings.&lt;/p&gt;
&lt;p&gt;At that time, it seemed like the only way to break Microsoft&amp;rsquo;s
competitive hold was compatible, open source alternative versions
of everything. OpenOffice was written to try to be an alternative to
Microsoft Office, but it was a non-starter unless it could read and write
Microsoft&amp;rsquo;s proprietary Office file formats.  Similarly, Mozilla Firefox,
the first web browser to erode Internet Explorer&amp;rsquo;s hold on the web,
only worked on many sites because it used to be configured by default to
tell web servers that it was Internet Explorer rather than identifying
itself honestly.&lt;/p&gt;
&lt;p&gt;The crown jewel of this effort would have been working compatibility with
Windows programs on another operating system &amp;mdash; at the time, that was
often seen as the only hope for breaking Microsoft&amp;rsquo;s monopoly on operating
systems. Two efforts co-existed in that regard, Wine and ReactOS.&lt;/p&gt;
&lt;p&gt;Wine was the more serious effort, which would have allowed Windows
programs to run unmodified on Linux, including Microsoft Office,
which was the only program that could perfectly read Microsoft Office
documents. Wine would provide Windows applications with a personality,
like Windows NT had, where they could call Windows&amp;rsquo;s library functions,
and have them translated into the equivalent series of Linux library
function calls to get their work done.&lt;/p&gt;
&lt;p&gt;ReactOS was fascinating to me at the time because it attempted a
complete open source reimplementation of Windows NT. Programs
running on ReactOS would act like programs running on Windows
because the operating system was designed from the beginning
to act like Windows.&lt;/p&gt;
&lt;p&gt;Neither of these projects gained enough stability to be used in any
production setting.  What ultimately lessened Microsoft&amp;rsquo;s stranglehold
on power was the fact that nowadays, it&amp;rsquo;s not really relevant for most
applications what operating system you use, because applications have
transitioned to the web for deployment.&lt;/p&gt;
&lt;p&gt;Nowadays, when you want to do something new with your desktop or laptop
computer, you don&amp;rsquo;t install a new application (although interestingly,
you still do with your phone). Instead, for the most part, you go to
a website, whether for matchmaking services, communicating with people
through many different means of communication, or ordering food to your
apartment. The local program you buy at a store, or even download over
the Internet, has been obsoleted by just going to a website, where you
don&amp;rsquo;t even need to install anything. And as a result, Microsoft&amp;rsquo;s biggest
stranglehold was eroded from a direction they barely expected.&lt;/p&gt;
&lt;p&gt;They tried to hold on, as long as they could, by making their web browser,
Internet Explorer the standard web browser, and encouraging websites
to use Internet Explorer specific features. Eventually, Firefox was
compatible enough with Internet Explorer to break through that monopoly
and force Microsoft to update its browser, which led to the current
situation &amp;mdash; where Chrome is becoming the new monopolistic web browser
and now it is Google that is close to single-handedly controlling our
primary platform for deploying applications.&lt;/p&gt;
&lt;h2 id=&#34;linux-and-unix-on-the-server&#34;&gt;Linux and Unix on the Server&lt;/h2&gt;
&lt;p&gt;I mentioned before that Linux and macOS were both popular among
developers. Linux certainly allows a lot of customization, and you could
see how that would be appealing for advanced users like many developers
are &amp;ndash; but that doesn&amp;rsquo;t really explain the popularity of macOS, which
is the opposite.&lt;/p&gt;
&lt;p&gt;Really, Linux and macOS are popular among developers because they are
Unixes. Unix &amp;mdash; and Linux, which is now basically the best Unix for most
tasks &amp;mdash; never waned in popularity in the minicomputer space, which
evolved into the server space. When you are running a server, having
a powerful (and programmable) command line is a huge plus, and not having a
smooth GUI experience or drivers for every consumer device is a non-issue.
Linux is the &lt;em&gt;de facto&lt;/em&gt; standard for server operating systems now,
and when developing applications to run on the server (like the server
side components of any web application, including Facebook, Twitter,
GMail, and more or less any you can think of), it is useful to have
a match between what you run on the server and what you run on
your personal computer.&lt;/p&gt;
&lt;p&gt;macOS provides a close enough match to Linux servers to be useful
for development. Most Linux software also runs on macOS, because of
their shared Unix heritage and continuing efforts to keep compatibility.
The compatibility isn&amp;rsquo;t perfect, and many programmers like the flexibility
that comes with Linux (and don&amp;rsquo;t mind the inconvenience), and so Linux
is also popular among developers as a client OS.&lt;/p&gt;
&lt;p&gt;Windows is actually actively trying to catch up with macOS in this
domain; it has introduced the Windows Subsystem for Linux, an NT-based
personality that allows Windows to run Linux programs, unmodified. This
is an impressive technology marketed at devleopers and used for practical
applications by many people I know.&lt;/p&gt;
&lt;h4 id=&#34;what-is-a-server&#34;&gt;What is a server?&lt;/h4&gt;
&lt;p&gt;What does a server do? It waits for incoming connections from other
servers and from client computers like your laptop or phone, and responds
to requests. It stores your data in databases and file systems, and
does the heavy lifting that needs to be done by a more powerful computer
than you really need to have in your own home. We interact with servers
every time we use a web browser or an e-mail client, and most phone apps
and games have a server-side component &amp;mdash; certainly if they involve
coordination with other people and other phones!&lt;/p&gt;
&lt;p&gt;As the &amp;ldquo;cloud&amp;rdquo; grows as a concept, more and more of our computing is
done on servers owned by big companies. We store our documents and
spreadsheets on Google Drive, keep our contact information on iCloud,
or let our photos be saved on Instagram. All of these services use
Linux to power the servers that actually store the data and provide
it to us in an organized and secure way.&lt;/p&gt;
&lt;h3 id=&#34;android&#34;&gt;Android&lt;/h3&gt;
&lt;p&gt;As mentioned earlier, Linux is technically only one component of the
operating system called Linux (or rather the family of operating systems,
because many companies and organizations leverage its open source
nature and distribute their own Linux-based operating systems, and there
is no one official complete distribution), namely, the &lt;em&gt;kernel&lt;/em&gt;.
The kernel is the portion of the operating system that runs in a privileged
mode on the processor, which forces the applications to go through it
rather than access the hardware directly (as on MS-DOS).&lt;/p&gt;
&lt;p&gt;Android uses the Linux kernel &amp;mdash; but nothing else from the operating
system commonly called Linux. Like iOS, it uses its kernel in an
idiosyncratic, locked-down way &amp;mdash; not quite as locked-down as iOS,
but much more locked down nevertheless than any desktop operating system.&lt;/p&gt;
&lt;p&gt;Android is open source, but you need to pay Google to use their app
store and standard apps and brand. Off-brand Android can only be used in
practice by companies rich and powerful enough to build out their own app
store, like Amazon. Being able to run Android apps would be a relatively
easy way for another mobile OS to gain a pre-existing developer base.&lt;/p&gt;
&lt;h2 id=&#34;chromeos&#34;&gt;ChromeOS&lt;/h2&gt;
&lt;p&gt;And Google somehow, after writing Android, wanted yet another
Linux-based operating system. ChromeOS, popular in American public
schools like Mac OS was in my school days, is exactly what it sounds
like: a laptop operating system where you just run Google Chrome. With so many
apps in the browser anyway, what&amp;rsquo;s the downside?&lt;/p&gt;
&lt;p&gt;In a ChromeOS context, from a user&amp;rsquo;s point of view, you begin to wonder what
the difference is between a browser and an operating system, really. An operating
system lets you run multiple applications &amp;mdash; but now those are just different
browser tabs. Who cares whether the Linux kernel or Chrome itself are the
pieces of software that separate the applications from each other &amp;mdash; from the
user&amp;rsquo;s perspective, it&amp;rsquo;s all the same.&lt;/p&gt;
&lt;p&gt;If you unlock the developer mode, you get a somewhat dumb version of &amp;ldquo;Linux
on the desktop,&amp;rdquo; with a Linux command line interface. This is convenient
for people who only want to use the web and log into remote servers,
which is a surprisingly large demographic.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
      <title>What is an operating system?</title>
      <link href="https://www.thecodedmessage.com/posts/operating_system/" />
      <id>https://www.thecodedmessage.com/posts/operating_system/</id>
      <updated>2019-04-28T00:00:00+00:00</updated>
      
      <summary type="html">&lt;p&gt;A user of modern technology hears the term &amp;ldquo;operating system&amp;rdquo; thrown
around a lot. Most people can name a few examples: Windows and macOS on
workstations and laptops, iOS and Android on phones. Some people might
even throw in Linux or Unix or ChromeOS. Most people also understand
that a program or a game or even a sufficiently advanced website might
work on some operating systems but not others, and might require different
versions for different operating systems. But it&amp;rsquo;s a bit less clear what
an operating system actually is, how it fits into the general model of
a computer, and how it works.&lt;/p&gt;</summary>
      <content type="html">&lt;p&gt;A user of modern technology hears the term &amp;ldquo;operating system&amp;rdquo; thrown
around a lot. Most people can name a few examples: Windows and macOS on
workstations and laptops, iOS and Android on phones. Some people might
even throw in Linux or Unix or ChromeOS. Most people also understand
that a program or a game or even a sufficiently advanced website might
work on some operating systems but not others, and might require different
versions for different operating systems. But it&amp;rsquo;s a bit less clear what
an operating system actually is, how it fits into the general model of
a computer, and how it works.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t surprising, because &amp;ldquo;operating system&amp;rdquo; is a bit of an
amorphous concept. Is it a type of program? It&amp;rsquo;s certainly different
from most programs we think of!&lt;/p&gt;
&lt;p&gt;It wasn&amp;rsquo;t my idea to ask this question. I listened to a talk
recently by the lead programmer on a project to develop a new operating
system, and he spent at least the first quarter of the lecture and many
slides trying to come up with a workable definition that jived well with
most programmers&amp;rsquo; and users&amp;rsquo; intuitions. [Edited to add: It was Bryan
Cantrill, who brings this up in multiple talks. I am unsure which one
inspired this.]&lt;/p&gt;
&lt;p&gt;But now that I&amp;rsquo;ve heard the question posed, I feel compelled to try to
answer it. So, to explore this concept, I&amp;rsquo;m going to talk about a lot
of operating systems from history. These aren&amp;rsquo;t going to be the operating
systems that invented the models in question, but rather typical examples
of those models, especially very popular operating systems of their era
and ones that were direct predecessors to popular operating systems today.
All of the fundamental technologies discussed pre-date the operating
systems I discuss to typify them.&lt;/p&gt;
&lt;h2 id=&#34;computers-without-operating-systems&#34;&gt;Computers Without Operating Systems&lt;/h2&gt;
&lt;p&gt;To see what an operating system is, and why we might want one, let&amp;rsquo;s
imagine a computer without an operating system, or perhaps with a very
minimal operating system. Such computers once existed; people my age
or older might remember the Apple II or the Sega Genesis. A more recent
example might include earlier versions of the Game Boy. These computers
(and a game console is a type of a computer for these purposes) could only
run one program at a time; if you wanted to run a different program or
game, you had to turn the device off, insert a new floppy or cartridge,
and turn the device back on again.&lt;/p&gt;
&lt;p&gt;The same physical machine took on an entirely different interface based
on what software you provided. Each program has full control of the
computer while you&amp;rsquo;re running it, to the extent that you have to turn
the computer off to stop running the program. Each program also managed
its own storage; you would save your Sega Genesis games on the cartridge,
not the console, and could then resume them on your neighbor&amp;rsquo;s console
if you wanted to.&lt;/p&gt;
&lt;p&gt;This is very different from how computers with operating systems work,
and leads me to the following definition of an operating system: an
operating system is a set of software that allows multiple programs to
co-exist on a computer. You need an operating system to, for example,
reasonably have a permanent hard disk, because there needs to be some
or another convention as to tell which programs should write their data
to which portions of the disk.&lt;/p&gt;
&lt;h2 id=&#34;a-minimal-operating-system-ms-dos&#34;&gt;A Minimal Operating System: MS-DOS&lt;/h2&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/Msdos-icon.png&#34; alt=&#34;MS-DOS icon&#34;&gt;&lt;/p&gt;
&lt;p&gt;This definition includes older operating systems like MS-DOS (see the
&lt;a href=&#34;https://github.com/microsoft/ms-dos&#34;&gt;original source code&lt;/a&gt;), Microsoft&amp;rsquo;s
flagship operating system from the 80&amp;rsquo;s and early 90&amp;rsquo;s. MS-DOS only could
run one application at a time, like the Apple II or the Sega Genesis. The
difference is that MS-DOS would at least let you share a hard disk between
applications and it also let you switch which application you were using
without rebooting or inserting new media. Sharing a hard disk between
programs was its defining feature, to the point where DOS actually stands
for &amp;ldquo;disk operating system.&amp;rdquo; MS-DOS shared this acronym DOS with other,
similarly featured microcomptuer operating systems of its day, which
also focused on simply letting programs share a hard drive.&lt;/p&gt;
&lt;p&gt;To share a hard drive between multiple programs over time, all the
programs have to agree on how the hard drive is organized.
It wouldn&amp;rsquo;t do for a game to store its game data on sector 13 of
the hard drive when a word processing editor wanted to store its
list of documents on the same sector. The hard drive required
not only an organization scheme, but one shared between different
programs by different authors.&lt;/p&gt;
&lt;p&gt;This was done through a &lt;em&gt;file system&lt;/em&gt;, which allowed you to assign names
to long blobs of bytes, called &lt;em&gt;files&lt;/em&gt;. A programmer could have a program
store whatever it wanted in the files it created, but as long as it
created files with different names from the other programs, the operating
system, with its file system, would ensure that the data could be
found again without each program having to have its own, possibly
conflicting, ideas of where to look directly on the disk.&lt;/p&gt;
&lt;p&gt;On MS-DOS, these files had to be 12 characters long or less:
8 characters of name, a dot &lt;code&gt;.&lt;/code&gt;, and an 3-character &lt;em&gt;extension&lt;/em&gt;,
for example, &lt;code&gt;teleport.doc&lt;/code&gt; or &lt;code&gt;taxr1998.xls&lt;/code&gt;. The extension served
as a convention to indicate which program was supposed to care about
this file. Your spreadsheet program would let you save spreadsheets on
the same file system that your word processor would let you save your
documents &amp;mdash; some mechanism was needed to say which program should be
run to make sense of which blob of binary bytes, especially because
the first version of MS-DOS didn&amp;rsquo;t even have support for directories
(which we now might call folders).&lt;/p&gt;
&lt;p&gt;If you opened a file with the wrong program, the program might notice
you used the wrong extension &amp;mdash; or it might not, and give you gibberish
results from misinterpreting the data. It would certainly encourage you
to save files with the proper extension &amp;mdash; a concept that survives in
Windows to this day, where programs only offer to open files that have
an appropriate extension.&lt;/p&gt;
&lt;p&gt;By modern standards, MS-DOS and its file system didn&amp;rsquo;t do very much.
It didn&amp;rsquo;t stop a program from modifying files intended for another
program &amp;mdash; or even from wiping the computer entirely; it simply created
an organizational system that allowed programs to co-exist and store their
data in an organized fashion, as long as the program&amp;rsquo;s were well-behaved
and not buggy (or malicious).&lt;/p&gt;
&lt;p&gt;It did have to define a format for programs themselves to be stored on
the disk.  You could tell which files represented runnable programs
because they had the extension &lt;code&gt;com&lt;/code&gt; (for &amp;ldquo;command&amp;rdquo;) or &lt;code&gt;exe&lt;/code&gt; (for
executable). It also had to provide a program to launch your application
programs: This was known as a &lt;em&gt;shell&lt;/em&gt;: It was the first program that
ran when you turned on the computer, and you could use it to select
other programs to run. At the time through a &lt;em&gt;command-line interface&lt;/em&gt;:
It would prompt you with the text &lt;code&gt;C:\&amp;gt;&lt;/code&gt;, and you would have to type
the name of the file that contained the program you wanted to load
(or alternatively do some very basic file management directly from the
command line through built-in commands).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/StartingMsdos.png&#34; alt=&#34;Starting MS-DOS&amp;hellip;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Besides its core mission of providing a system to operate a disk, the
&amp;ldquo;disk operating system&amp;rdquo; did also have other code, to help programs
interact with the hardware. As most components besides the disk could
be used by the programs however they wanted without damaging others
(because only one ran at a time), this code wasn&amp;rsquo;t as essential to its
functionality, but it did exist. Software used to interact with hardware
is called &lt;em&gt;drivers&lt;/em&gt;, and they might be included in an operating system
or might be loaded separately, depending on the design. Driver code
is organized into procedures that programs invoke to do things to the
hardware (e.g. draw on the screen or print a file), or code that is
installed as &lt;em&gt;interrupt handlers&lt;/em&gt; so that the processor will interrupt
the current task whenever a certain hardware event happens (e.g., what
to do when the user presses a key). Because MS-DOS was so minimal,
both types of drivers could be circumvented.&lt;/p&gt;
&lt;p&gt;And in actuality, application programs could circumvent the driver that
was the most core to its role as a &amp;ldquo;disk&amp;rdquo; operating system &amp;mdash; the driver
for the hard drive, and the layer that allowed you to edit it in terms
of files.  MS-DOS couldn&amp;rsquo;t even force programs to use its procedures for
the one abstraction it absolutely had to maintain.  Though the existence
of official filesystem procedures provided some stability, many programs
circumvented these procedures and modified the hard disk directly,
(hopefully) making sure to respect the conventions but not using MS-DOS&amp;rsquo;s
actual code. MS-DOS, especially at first, was a little bit of code, and a
lot of &amp;ldquo;gentlemen&amp;rsquo;s agreement&amp;rdquo; &amp;mdash; it had no security or rigor whatsoever.&lt;/p&gt;
&lt;p&gt;This had some upsides. Every application had access to the full power of
the computer. Microcomputers were much slower then, and so every ounce
of direct hardware access could be a major performance boon, especially
for games. Furthermore, many applications supported hardware that the
operating system itself could not: In MS-DOS days, you often had to do
separate sound card or even graphics configuration for every game you had,
but at least you weren&amp;rsquo;t limited by what Microsoft had chosen to provide
support for.&lt;/p&gt;
&lt;p&gt;It also had some downsides. Obviously, securing your files was impossible:
there was a way to mark files as read-only, but it could only be advisory.
There was no system of multiuser file ownership &amp;mdash; though an application
could individually provide an encryption feature. These downsides weren&amp;rsquo;t
too bad &amp;mdash; if you trusted everyone who used your computer, it wasn&amp;rsquo;t
really a problem. It&amp;rsquo;s generally better anyway to secure your computer
with encryption or just by putting it in a locked room.&lt;/p&gt;
&lt;p&gt;More importantly, this was a hazard for the stability of the system. Any
program could decide to circumvent the standard ways of doing file access,
and many did, to cut corners on performance. But many different pieces
of code all interacting with the same file system is many opportunities
to mess up and have bugs instead of just one. There was a real risk of
a poorly-written program corrupting your file system, deleting files
it wasn&amp;rsquo;t even supposed to touch or potentially rendering the entire
filesystem unusable.&lt;/p&gt;
&lt;p&gt;The biggest long-term problem for Microsoft was a subtler version of
this: If Microsoft wanted to change the file system &amp;mdash; if they, for
example, wanted to make filenames longer than 8.3 (so you could say
&lt;code&gt;real_long_name.html&lt;/code&gt; instead of &lt;code&gt;rllngnam.htm&lt;/code&gt;), they couldn&amp;rsquo;t just
go do it themselves. Changing a bit of code is easy. Changing a subtle
gentlemen&amp;rsquo;s agreement requires all the gentlemen in question to agree.
If they had changed the format to allow more characters, programs that
used their officially recognized libraries would keep working, but
those that accessed the file system on the hard drive directly would
be following the old ways when the conventions had changed. They would
be thrown off by the long filenames like old people thrown off by how
young people dress. The software that followed the old conventions could
easily accidentally delete data that no longer follows them.&lt;/p&gt;
&lt;p&gt;If this were just an occasional program that was doing things its own
way, then Microsoft could just break that one program. Unfortunately,
many many programs had their own ways of accessing the disk. The &amp;ldquo;disk
operating system&amp;rdquo; couldn&amp;rsquo;t even keep control of its central feature.&lt;/p&gt;
&lt;p&gt;The other major downside of MS-DOS and OSes like it is that you couldn&amp;rsquo;t
run multiple programs at the same time. It allowed different programs to
run in sequence, and to share permanent resources (the filesystem). On
a modern operating system we take for granted the ability to multitask
programs. We listen to music while being ready to receive a call at any
moment &amp;mdash; and to return to the music when the call is finished.  We
expect to be able to look up directions or text messages while talking
to our friends while a file is downloading in the background. This takes
much more sophistication than MS-DOS could provide.&lt;/p&gt;
&lt;p&gt;Luckily for those who wanted multitasking, many systems existed to
add multitasking to an MS-DOS installation. Because MS-DOS was so
minimalistic, an MS-DOS program took full control of the computer
when it was run. If it used that control to dispatch between multiple,
simultaneously running programs, it fits our definition of an operating
system: a software system that allows multiple programs to coexist on
a computer. Basically, operating systems existed that used DOS as their
launching point, taking over the computer and providing richer and more
modern services to the programs running under its scope.&lt;/p&gt;
&lt;p&gt;These programs/OSes were called &amp;ldquo;DOS extenders,&amp;rdquo; and the most famous
of them was written by Microsoft, DOS&amp;rsquo;s vendor, to add multitasking
(and GUI, which in the personal computer world often went hand in hand)
to their otherwise primitive operating system. This was called &amp;ldquo;Windows.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.thecodedmessage.com/images/windows.png&#34; alt=&#34;Microsoft Windows has changed a lot since 3.0&#34;&gt;&lt;/p&gt;
&lt;p&gt;For those of you who don&amp;rsquo;t remember this era, Windows was not always
the operating system a computer would immediately boot into. It used to
be that Windows masqueraded as a MS-DOS program, that you&amp;rsquo;d boot up the
computer and see a command-line prompt, and have to type &lt;code&gt;win&lt;/code&gt; before
you saw any graphical user interface whatsoever. Without a preexisting
MS-DOS installation to set up the file system and do initial hardware
configuration, you couldn&amp;rsquo;t run Windows at all &amp;mdash; not that Windows wasn&amp;rsquo;t
sophisticated enough, but it had always been run that way, and so it never
replicated that functionality in the boot process.  Similarly, Windows at
the time was constrained, just as DOS was, by its 8.3 filename convention.
It had to share a filesystem with DOS programs, as it was itself a DOS
program &amp;mdash; as well as an operating system in its own right.&lt;/p&gt;
&lt;p&gt;By the time Windows had gotten to version 3, it had the ability, on
sufficiently powerful computers, to run multiple copies of MS-DOS at
the same time and an MS-DOS program in each of those copies &amp;mdash; and yet,
at another layer of abstraction, it was itself a program run from the
one copy of MS-DOS that your program booted. Microsoft cleaned up this
situation in Windows 95, which still used DOS internally as part of
its boot process, but went straight to graphical, Windows mode when the
computer turned on.&lt;/p&gt;
&lt;h2 id=&#34;cooperative-multitasking&#34;&gt;Cooperative Multitasking&lt;/h2&gt;
&lt;p&gt;Windows 3 supported graphical user interfaces and running multiple
programs at the same time, and so did Mac OS System 7, both from
the early 1990&amp;rsquo;s. However, multiple programs did not, and could not,
literally run at the same time &amp;mdash; the processor executed instructions
in a stream and that stream of instructions represented only one
program at a time.&lt;/p&gt;
&lt;p&gt;To maintain the illusion of running multiple programs at the same
time, these systems used &lt;em&gt;cooperative multitasking&lt;/em&gt;. In cooperative
multitasking a program runs for a short amount of time, and then it
is expected to &lt;em&gt;yield&lt;/em&gt; control of the processor back to the
operating system.&lt;/p&gt;
&lt;p&gt;In a graphical user interface, this usually corresponded to an event
of some sort. When the user clicked in some window, the program
that owned the window would get to run for enough time to decide
how to respond to it: what internal memory should it update,
what should it write to the hard drive, and what new things should
it display on the screen. Once it was done handling the event,
it would return to the operating system, which would then
see if the user has clicked a key in the meantime, which might
mean sending an event to another program. The program could
also, however &amp;mdash; maliciously or accidentally &amp;mdash; not return
to the operating system, in which case the computer would simply
hang and refuse to respond to more input. This is why operating
systems of that time would regularly freeze completely in the
presence of a poorly-written program.&lt;/p&gt;
&lt;p&gt;The memory of all the programs were loaded in memory at the same time,
and there was nothing protecting one program&amp;rsquo;s internal data from being
overwritten, maliciously or accidentally, by another program. Basically,
the different programs could be thought of, in a modern sense, as
collections of loadable event-handling subroutines for one graphical
interface system. They were kept separate again by convention,
by gentlemen&amp;rsquo;s agreement.&lt;/p&gt;
&lt;p&gt;For certain background tasks, like playing music, the code to
keep sending data to the speakers has to be run repeatedly, on a
timer &amp;mdash; so any apps that use that feature can crash the computer
at any time by simply failing to complete.&lt;/p&gt;
&lt;p&gt;So while these operating systems were more sophisticated than MS-DOS
and its cohorts, in another sense they promised more than they could
deliver, and relied even more on the good behavior of the programs
they managed.&lt;/p&gt;
&lt;p&gt;They allowed multiple programs to run simultaneously, but actually
required more out of the individual programs to have a harmonious
system. After all, if an MS-DOS program crashes, the computer could be
rebooted, but at least you only lost your work in that program. If a
Windows 3.1 or Mac OS System 7 program were to crash, you&amp;rsquo;d lose work
in all the other programs it was &amp;ldquo;multitasking&amp;rdquo; with.&lt;/p&gt;
&lt;p&gt;By this point, there were stronger protections against a program
circumventing the operating system with its own drivers. It was still
generally possible, but less likely to be done. This is important, because
while in MS-DOS, it makes perfect sense for each program to define what
happens when you click the mouse, on a graphical system, the mouse has
to control a mouse pointer which moves from window to window and acts
the same whichever application is in the foreground.  When more than
one application runs at a time, more hardware becomes shared resources,
and so the operating system must take on responsibility for it,
even if this responsibility is only carried out cooperatively.&lt;/p&gt;
&lt;h2 id=&#34;time-sharing-or-preemptive-multitasking&#34;&gt;Time-Sharing or Preemptive Multitasking&lt;/h2&gt;
&lt;p&gt;Windows wasn&amp;rsquo;t Microsoft&amp;rsquo;s first attempt at a more robust operating
system than MS-DOS. For a while, it tried to market a more
sophisticated version of MS-DOS, still command-line centric, but
without many of the deficits we&amp;rsquo;ve discussed. This operating system
was Xenix.&lt;/p&gt;
&lt;p&gt;Xenix was Microsoft&amp;rsquo;s entry into a longer, older tradition of the Unix
operating system. This tradition is mostly present today in Unix&amp;rsquo;s
off-brand workalike clone, Linux. It is from the world of minicomputers,
which is what we used to call what we now call server-class computers,
from before the primary use of them was to provide centralized infrastructure
for other &amp;ldquo;client&amp;rdquo; computers.&lt;/p&gt;
&lt;p&gt;Before any of the other operating systems we&amp;rsquo;ve discussed, Unix was
developed at Bell Labs for minicomputers (see the &lt;a href=&#34;https://github.com/dspinellis/unix-history-repo&#34;&gt;original source
code&lt;/a&gt;. Don&amp;rsquo;t let the name
fool you &amp;mdash; they&amp;rsquo;re named because they&amp;rsquo;re the size of a refrigerator
rather than the size of a warehouse room like a mainframe. It ran on a
single computer that had multiple &lt;em&gt;dumb terminals&lt;/em&gt; connected to it, which
means that there was a non-computer device that the user would sit at,
and use a command-line interface to interact, over the phone or some other
connection, with a centralized computer that was shared with other users.&lt;/p&gt;
&lt;p&gt;In such an environment, the laxness of MS-DOS or Windows 3.1 was simply
unacceptable. While security against malicious users was not necessarily
important, depending on your user-base, there needed to be some level
of robustness against ill-behaved programs, especially as at the time,
most computer users would regularly write new programs that could easily
behave poorly, as they were still being developed.&lt;/p&gt;
&lt;p&gt;More importantly, programs would often have to bulk-process data. On the
spectrum of &amp;ldquo;consumer interaction&amp;rdquo; to &amp;ldquo;serious work,&amp;rdquo; these early minicomputers
were very much on the side of &amp;ldquo;serious work&amp;rdquo; in their common use cases. You
might leave a program running for hours as it processed a large bulk of
data. You didn&amp;rsquo;t want to have to worry about letting other users&amp;rsquo; programs
get a chance to run &amp;mdash; at the very least, you didn&amp;rsquo;t want to have to
put active effort into making it possible. It would be inconvenient.&lt;/p&gt;
&lt;p&gt;On the hardware side, these computers&amp;rsquo; processors, like processors
on microcomputers (as personal desktop and laptop computers were once
called), processed one series of instructions at a time. Something had
to be done to give each of the users the illusion that they were the
only one running their tasks on the computer.&lt;/p&gt;
&lt;p&gt;If a process &amp;mdash; meaning a currently active instance of a user running a
program &amp;mdash; was waiting for more data, because it had requested a read
from the operating system (which mediated all reads from files or any
terminal), it was similar to the cooperative situation: the operating
system would suspend or &lt;em&gt;block&lt;/em&gt; the execution of the current process,
and schedule it again when the read had completed, perhaps in response
to a terminal user hitting the &lt;code&gt;[Enter]&lt;/code&gt; key.&lt;/p&gt;
&lt;p&gt;But there could be long gaps between when a process would enter
into a &lt;em&gt;blocked&lt;/em&gt; state like this. A user could try to calculate
a million digits of Pi. On Mac OS System 7, some sort of
yield function would have to be called from time to time, to give other events
a chance to be handled, but ideally we don&amp;rsquo;t want that complexity to
be passed onto the application programmer.&lt;/p&gt;
&lt;p&gt;Instead, before letting a process run on the processor, the operating
system will first set a timer in the hardware. When the timer goes
off, it will cause a &lt;em&gt;timer interrupt&lt;/em&gt;, where the processor will stop
what it&amp;rsquo;s doing and run an operating system procedure instead. That
operating system procedure will suspend the currently running process,
using features of the processor to make it so that when the process is
resumed, it is almost impossible for the user &amp;mdash; or even for the program
&amp;mdash; to detect that it had ever been interrupted.&lt;/p&gt;
&lt;p&gt;In that case, while we hope that only one user is running a complicated
task at a time, even when multiple are, their long-running tasks simply
split the processor 50/50 &amp;mdash; or in some other proportion deemed fair
by the system&amp;rsquo;s &lt;em&gt;scheduler&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For every purpose but speed, however, the user has the illusion that
they&amp;rsquo;re the only one using the computer, although in fact many users
might be using it at the same time. Just as sharing a disk was the
primary feature of MS-DOS, splitting processor time was the primary
feature of Unix, as evidenced by its original full name, the
&amp;ldquo;Unix Time-Sharing System.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Time sharing was often, but not always, paired with &lt;em&gt;memory protection&lt;/em&gt;,
the idea that a process was limited in what memory it could modify, and
isolated from other processes. This was a feature that most minicomputers
had, but that it took a longer time to mature on microcomputers. This
feature usually goes hand-in-hand with a mechanism to force programs to
interact with hardware through the operating system, which also requires
hardware support, known in the Intel universe &amp;mdash; appropriately &amp;mdash; as
&lt;em&gt;protected mode&lt;/em&gt;. MS-DOS did not run in protected mode. Windows 3 could.
Windows 95 always did.&lt;/p&gt;
&lt;p&gt;There were other time-sharing systems of that time, but Unix was
one of the most famous, partially because it has survived in
continuous evolution to this day. Its off-brand open source clone,
Linux, is the most popular OS for servers as well as part of the
Android operating system for mobile devices. One of the more popular
workstation operating systems, macOS, is nowadays also a fully licensed
brand-name Unix.&lt;/p&gt;
&lt;p&gt;I bring up Unix to show that time-sharing features pre-date MS-DOS
and much of the microcomputer era. They were considered overkill for
microcomputers while they were still underpowered, but they existed in
other contexts. At the time, the focus was more on supporting multiple
simultaneous users &amp;mdash; the fact that a single user might be able to
run multiple processes at once was a minor side benefit. After all,
these systems were mostly command-line based, and it was only possible
for a user to interact with one process at a time (per terminal), so
besides background computation (which some users did really care about),
it didn&amp;rsquo;t have the same immediate practical use as being able to edit
your Word document while playing music.&lt;/p&gt;
&lt;p&gt;So why did cooperative operating systems ever exist, if Unix predates
Windows 3.1 and MacOS System 7? Well, they existed in different
domains. Preemptive multitasking was difficult to program, and was
mostly available on operating systems for minicomputers &amp;mdash; more powerful
systems than individuals could generally own &amp;mdash; or else expensive
desktop computers known as &amp;ldquo;workstations&amp;rdquo; for particular
specialized jobs.&lt;/p&gt;
&lt;p&gt;The operating system, is, after all, about coordinating between
programs in sharing hardware resources. It makes sense that
what those hardware resources are should influence operating
system design. When it is a single terminal and no disk, you
barely need an operating system, but when it is a graphical
user interface, you need more of one, and when it is several
terminals, you have different needs. Nowadays, we expect a
lot out of simple devices, beyond what would be necessary
to get good use out of them, but in the past, the hardware
(and human/programmer) resources were not not as up to the
challenge.&lt;/p&gt;
&lt;p&gt;Modern operating systems combine
all of these concepts, and provide graphical user interfaces
while using all the technical advantage of time-sharing and
memory protection, and more can be read about them in
the &lt;a href=&#34;https://www.thecodedmessage.com/posts/current_os/&#34;&gt;next post&lt;/a&gt;.&lt;/p&gt;
</content>
    </entry>
    
</feed>
