Can C++ fix its biggest problem?

C++, like all things, has numerous problems. Pointing out how Rust addresses many of them is a major topic 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’s attention and resulted in a surreal flame war between Dr. Bjarne Stroustrup and the NSA (which I also commented on/contributed to), is C++’s lack of memory safety.

What Bits Mean: Meta-Data and Static Typing

This is part of my new series on what the 0’s and 1’s in computers mean, how computers use them to store various kinds of information, and why all of this works the way it does. 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:

What Bits Mean: Binary Integers and Two’s Complement

I was explaining two’s complement recently1 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’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!

Sorting Polymorphically in Many Languages

Polymorphism is a powerful programming language feature. In polymorphism, we have generic functions that don’t know exactly what type of data they will be operating on. Often, the data types won’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.

Minor News: Some Repos on GitHub

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’d let everyone know nevertheless, and write up a few notes about it. Both have been added to my programming portfolio garden. Repo #1: Crate Version of Prefix Ranges Arvid Norlander (blog, GitHub) reached out to me to ask if I wanted to publish my little Rust module from my post on prefix ranges as a crate, or, failing that, if I could license it as open source so he could publish it.

Rust Is Beyond Object-Oriented, Part 3: Inheritance

In this next1 post of my series explaining how Rust is better off without Object-Oriented Programming, I discuss the last and (in my opinion) the weirdest of OOP’s 3 traditional pillars. It’s not encapsulation, a great idea which exists in some form in every modern programming language, just OOP does it oddly. It’s not polymorphism, 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++).

Endianness, and why I don’t like htons(3) and friends

Endianness is a long-standing headache for many a computer science student, and a thorn in the side of practitioners. I have already written some about it in a different context. Today, I’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. Before we get to that, I want to make some preliminary clarifications about endianness, which will help inform our API design.

My Dream C++ Additions

UPDATE: I have updated this post to address C++ features that address these issues or have been purported to. 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. Explicit self reference instead of implicit this pointer UPDATE: This is coming out in C++23, and they did it right!

In Defense of ‘C/C++’

One of the minor points I discussed in my response to Dr. Bjarne Stroustrup’s memory safety comments 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. A little background: Many people, especially outside the C and C++ communities (which, to be clear, don’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 “C and C++” or “C or C++.

C++ Papercuts

UPDATE: Wow, this post has gotten popular! I’ve written a new post 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++’s deeper-than-papercut issues, I recommend specifically my post on its move semantics. Thank you for reading! 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++.

Walk-Through: Prefix Ranges in Rust, a Surprisingly Deep Dive

Update: Arvid Norlander has gone through the trouble of refactoring this code into a crate and publishing it. Thank you, Arvid! Rust’s BTreeMap and corresponding BTreeSet are excellent, B-tree-based sorted map and key types. The map implements the ergonomic entry API, more flexible than other map APIs, made possible by the borrow checker. They are implemented with the more performant but more gnarly B-Tree data structure, rather than the more common AVL trees or red-black trees.

There is No One True Best Programming Language (but some are still better than others)

I am no stranger to programming language controversy. I have a whole category on my blog dedicated to explaining why Rust is better than C++, and I’ve taken the extra step of organizing it into an MDBook for everyone’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’ve been exposed to every corner, every trope and tone and approach of programming language debate religious war, from the polite and well-considered to the tiresome and repetitive all the way to the rude and non-sensical.

A New Garden: Rust vs C++ mdbook

Here it is, the Rust vs C++ mdbook. I’ve wanted for a while to re-organize some of the content on my blog into gardens. I got the idea from the blog post “The Garden and the Stream: A Technopastoral”. 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 some exceptions), but rapidly becomes less discoverable after I’ve written it, as it is buried by newer posts.

Rust: A New Attempt at C++’s Main Goal

I know I set the goal for myself of doing less polemics and more education, but here I return for another Rust vs C++ 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 – which is the majority of the work of writing – was already done when I set that goal.

Guest Collaboration: Paradigm Shift

Does the choice of programming language matter? For years, many programmers would answer “no”. There was an “OOP consensus” 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. To the extent there was a spectrum of opinions, it was between OOP denizens and those that didn’t really think software architecture mattered at all — an feeble attempt of corporatization against true programmers and their free-spirited ways.

Rust Tidbits #1

This is a collection of little Rust thoughts that weren’t complicated enough for a full post. I saved them up until I had a few, and now I’m posting the collection. I plan on continuing to do this again for such little thoughts, thus the #1 in the title. serde flattening What if you want to read a JSON file, process some of the fields, and write it back out, without changing the other fields?

The Importance of Logging

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 bad). 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.

Rust Is Beyond Object-Oriented, Part 2: Polymorphism

In this post, I continue my series on how Rust differs from the traditional object-oriented programming paradigm by discussing the second of the three traditional pillars of OOP: polymorphism. 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 – yes, polymorphism exists outside of OOP), how to use it effectively, and when not to use it.

My Reaction to Dr. Stroustrup’s Recent Memory Safety Comments

The NSA recently published a Cybersecurity Information Sheet 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 waves with his response. To be honest, I was disappointed. As a current die-hard Rustacean and former die-hard C++ programmer, I have thought (and blogged) quite a bit about the topic of Rust vs C++.

Rust and Default Parameters

Rust doesn’t support default parameters in function signatures. And unlike in many languages, there’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 Default trait and struct update syntax to achieve similar results. 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.

Rust Is Beyond Object-Oriented, Part 1: Intro and Encapsulation

Rust is not an object oriented programming language. Rust may look like an object-oriented programming language: Types can be associated with “methods,” either “intrinsic” or through “traits.” Methods can often be invoked with C++ or Java-style OOP syntax: map.insert(key, value) or foo.clone(). Just like in an OOP language, this syntax involves a “receiver” argument placed before a . in the caller, called self in the callee. 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.

How to Write a JIRA Ticket in … Relatively Few Steps

If you’re confused by how to use JIRA effectively, do not worry! If you learn this process, which is very simple not literally impossible, you too can become good at JIRA passingly competent at JIRA not liable to being fired for being bad at JIRA. Here are the steps: Create personal TODO item to write JIRA ticket Accumulate requirements for JIRA ticket in personal notes Often more complicated than the feature itself This is the System Working™ Write TODO items strategizing how to: Share the JIRA ticket with other people Connect it properly with other JIRA tickets Advanced: Also epics, projects, or other meta-JIRA constructs Write JIRA ticket Fail to understand what any of the fields are for Oh, they’re required?

RAII: Compile-Time Memory Management in C++ and Rust

I don’t want you to think of me as a hater of C++. In spite of the fact that I’ve been writing a Rust vs C++ blog series in Rust’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++.

A Strong Typing Example

I’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’t actually give examples of the bugs it can prevent, or it gives overly simplistic examples that don’t really ring true to actual experience. Today, I have a longer-form example of where static typing can help prevent bugs before they happen. The Problem Imagine you have a process that receives messages and must respond to them.

Exploring Traits with Erased ‘serde’

I came across a programming problem recently where I wanted to use dynamic polymorphism with serde. This turned out to be much easier than I expected, and I thought it was an interesting enough case study to share, especially for people who are learning Rust. A Brief Discussion of Polymorphism in Rust As most of you will know, Rust’s system for polymorphism – traits – supports both static and dynamic polymorphism, with a bias towards static polymorphism.

Blocking Sockets and Async

Using async 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 async 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.

Why Rust should only have provided expect for turning errors into panics, and not also provided unwrap

UPDATE 2: 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 Err into a panic. Indeed, such situations exist. I am not advocating for panic-free code. I am advocating that expect should be used for those functions, and if a function is particularly prone to being called like that (e.g. Mutex::lock or regex compilation), there should be a panicking version.

Another Confusing Haskell Error Message

The Error Message I’ve written before about just how befuddling 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’s clear to me now when I look at the error message what it’s trying to say, but I legitimately was stumped by it, and so, even though it’s embarrassing for me now, I feel the need to write about how this error message could have been easier to understand:

Command Line Interface UXes Need Love, Too

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.

Trivia About Rust Types: An (Authorized) Transcription of Jon Gjengset’s Twitter Thread

Preface (by Jimmy Hartzell) I am a huge fan of Jon Gjengset’s Rust for Rustaceans, an excellent book to bridge the gap between beginner Rust programming skills and becoming a fully-functional member of the Rust community. He’s famous for his YouTube channel as well; I’ve heard good things about it (watching video instruction isn’t really my thing personally). I have also greatly enjoyed his Twitter feed, and especially have enjoyed the thread surrounding this tweet:

Function Overloading in Rust

I just made a pull request to reqwest. I thought this particular one was interesting enough to be worth blogging about, so I am. 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: void use_connector(ConnectorA conn) { // IMPL } void use_connector(ConnectorB conn) { // IMPL } The compiler then chooses which method to call, at compile-time, based on the static type of the argument.

Can you have too many programming language features?

There’s more than one way to do it. Perl motto There should be one– and preferably only one –obvious way to do it. The Zen of Python (inconsistent formatting is part of the quote) 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 Rust vs C++ series, I will attempt to explain why C++’s feature-set is problematic, and explain how Rust does better.

A Checklist of Dev-Ops Disciplines

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.

Can you reproduce it?

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 “nontechnical”. What is the most important skill for a software engineer? It’s definitely not any particular programming language; they come and go, and a good programmer can pick them up as they work.

A Rust Gem: The Rust Map API

For my next entry in my series 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 entry API – I literally squealed when I first learned about entries. And as we shall discuss, this isn’t just because Rust made better choices than other standard libraries when designing the maps API.

The Good Ol’ Days of QBasic Nibbles

Let’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. Do you remember MS-DOS? Do you remember that it came with an interpreted programming language?

Warnings and Linter Errors: The Awkward Middle Children

What is “bad” Rust? When we say that a snippet of code is “bad” Rust, it’s ambiguous. We might on the one hand mean that it is “invalid” Rust, like the following function (standing on its own in a module): fn foo(bar: u32) -> u32 { bar + baz // but baz is never declared... } In this situation, a rule of the programming language has been violated. The compiler stops compiling and does not output a binary.

Haskell Error Messages: Come on!

I am a big fan of strongly typed languages, and my favorite GC’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. So here’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 – could I demonstrate that this strange language was worth some investigation?

Burying the Lede

Imagine you don’t know who Napoleon was. You know he’s a figure from history, but you don’t even know he has to do with France. And imagine, when you read the Wikipedia article, for some reason you skip the opening paragraphs above the fold, and you’re reading about his upbringing in Corsica as a petty Italian noble under French rule. And you just want to know, why’s this guy important, what’s his deal, why do people keep talking about him (something military, it seems?

Being Fair about Memory Safety and Performance

For this next iteration in my series comparing Rust to C++, I want to talk about something I’ve been avoiding so far: memory safety. I’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’d have relatively little to add to the conversation. I’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’t “truly memory safe” or “memory safe enough,” Rust still wins.

In Defense of Async: Function Colors Are Rusty

Finally in 2019, Rust stabilized the async feature, which supports asynchronous operations in a way that doesn’t require multiple operating system threads. This feature was so anticipated and hyped and in demand that there was a website whose sole purpose was to announce its stabilization. async was controversial from its inception; it’s still controversial today; and in this post I am throwing my own 2 cents into this controversy, in defense of the feature.

Endianness, API Design, and Polymorphism in Rust

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.

C++ Move Semantics Considered Harmful (Rust is better)

This post is part of my series comparing C++ to Rust, which I introduced with a discussion of C++ and Rust syntax. 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 – though not as confusing as move semantics in C++ – 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++.

Sayonara, C++, and hello to Rust!

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’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++’s application space, that for any new programming project where C++ would make sense as the programming language, Rust would make more sense.

The Haskeller’s Hungarian Notation

When I was first learning to program, a long time ago, it was in BASIC, and you had to annotate your variable names to indicate what type something is. foo would be a number, whereas foo$ would be a string. This meant that there could only be as many types of information as there were symbols to put after your variable, but that was okay for the sort of programming BASIC was used for.

Function Pointers in C and C++

Programmers of functional programming languages will often point out that, in functional programming languages, the order of the arguments is often significant, because of currying. If you have a function that takes two arguments (e.g. map which takes a function to apply and a list to apply it to) it actually takes the first argument, and returns a function that takes the second argument and returns the final result. This makes it more convenient to write a lambda where the second argument is the unknown parameter: \x -> map someFunc x can be written as map f, whereas \f -> map f someValue has no such convenient shorthand (flip map someValue is actually clunkier).