Rogers, AR 2021
Architecting GenServers for Testability in Elixir
[Post-publication update: This post turned into a conference talk at ElixirConf 2021, embedded here for posterity.]
Continue reading…TIL Elixir's || supports nil fallback
TIL Elixir can do nil || something
(evaluating to something
) just like the Javascript trick:
default_value = 123
my_value = my_map[:some_field] || default_value
If :some_field
is present & non-nil
, my_value
will be assigned the value from the map; otherwise it will fall back to default_value
.
(Note that this works with the ||
operator, but not or
—if this is as surprising to you as it was to me, see TIL about the differences between Elixir’s boolean operators. 😅)
San Diego 2021
TIL Elixir's for
comprehension supports filtering
TIL about the filtering support in Elixir’s for
comprehensions (“don’t call it a loop”):
# Create a record every 5 seconds for a day
for seconds <- 0..(60 * 60 * 24),
rem(seconds, 5) == 0 do
create_record_at_offset(seconds)
end
For more on the amazing superpowers of the for
comprehension, see Mitch Hanberg’s Comprehensive Guide to Elixir’s List Comprehension.
TIL: Elixir's match?/2
turns a match result into a predicate
TIL about Elixir’s Kernel.match?/2
.
iex> list = [a: 1, b: 2, a: 3]
iex> Enum.filter(list, &match?({:a, _}, &1))
[a: 1, a: 3]
So many times I’ve hacked around not knowing about this. 🤯
Where this gets really useful is in tests where you want to assert part of the shape of a map. For instance:
assert Enum.count(
results,
&match?(%{id: ^my_id, inserted_at: ^time}, &1)
) == 1
Iterating Over a Generic Sequence in Swift
Here’s a goofy bit of generic programming I do all the time in Swift—ironically, it’s one thing C++ makes easier than Swift!
Continue reading…A look inside X-Plane’s massive multiplayer server
This morning I published a blog post on the X-Plane Developer blog titled “Have You Heard the Good News About Elixir?.” It’s a look at the requirements and goals that drove me to choose Elixir for X-Plane’s massive multiplayer game server, with a look at both the pros and cons of that choice.
This post (and the feature itself!) was a long time in coming. It’s cool to be able to talk about it publicly.
On a related note, we open-sourced the Elixir implementation of the networking protocol we use for MMO. The README there gives a pretty good overview of the architecture of our MMO server—long story short, we go to great lengths to minimize shared state.
This won’t be of use to many people, but I do hope it’s useful to the next poor soul who needs to build a server around RakNet. ☺️
Missing SwiftUI Preview Window in Xcode
This is no doubt obvious if you’ve dutifully watched all the WWDC sessions on SwiftUI, but if you’re like me and just diving in and hacking the hell out of it, you might be baffled that the much-renowned preview pane isn’t showing up when you create your SwiftUI View
.
Creating a SwiftUI Window in an Objective-C AppKit App
I’ve been “rehabbing” a legacy Objective-C app (the Unbound photo browser), trying to make up for a couple years of neglect, and I wanted to start building new views in SwiftUI. There are a lot of good tutorials online for hosting SwiftUI views in UIKit apps (either iOS/iPadOs or macOS + Catalyst), but not much on how to do this for Mac and AppKit… and especially not when you’re still mostly Obj-C!
Continue reading…Warning: std::numeric_limits::min() > 0
Here’s a baffling design choice (which I’m reliably informed C++ inherited from older C limits.h
).
std::numeric_limits<int>::min()
is roughly -2 billion (assuming 32 bit ints, etc.).
But std::numeric_limits<float>::min()
is smallest positive floating point value… something like +0.00000000000000000000000000000000000001.
CppReference warns this is the case for all floating point types with denormalization (thus it applies to double
and long double
as well on vaguely x86-like platforms).
What you’re probably looking for (the actual opposite of std::numeric_limits<float>::max()
) is std::numeric_limits::lowest()
.
Default Capacity & Growth Rate of C++ std::vector
If you’re creating a lot of small vectors in C++, you should probably consider using a small-size optimized vector instead. But, if you can’t do that for some reason, you might wonder if there is any win to be had by reserve()
ing a small size in advance.
Warning: __attribute__((const)) does not mean function purity
Clang and GCC (and others) support function attributes __attribute__((const))
and __attribute__((pure))
. These had always been explained to me thus:
The fastest way to iterate a Map’s values in Elixir
Say you have an Elixir Map
. What’s the fastest way to iterate the values?
Go ahead, call yourself a software engineer.
No Size Fits All
The most recent episode of CppCast featuring David Sankel ends with a good reminder:
There is no One Software Methodology to Rule Them All, because we work in different contexts.
Your environment matters. If you’re a startup whose principle threat is obscurity, “move fast and break things” is good advice. If you’re an avionics developer, not so much.
When you push your way of doing things—even when it works really well for you!—as a universal panacea, something everyone everywhere should adopt, you’re missing the fact that it works in a particular set of circumstances… a particular time, with a particular team, with a particular set of goals, on a codebase with a particular history.
Benchmarks of Cache-Friendly Data Structures in C++
Suppose you’re a savvy C++ developer who knows all about data-oriented design and the importance of optimizing for cache locality if you want a prayer of running fast on modern hardware. Now suppose you want to go beyond basics—”just use std::vector
” is a good starting point, but you want more!
San Diego, CA
Data Normalization Matters
In describing for a coworker a place where two different subsystems have their own (hopefully identical!) ideas about the state of the UI, I was reminded of this quote from the database world:
Between any two copies of the same data, there will be differences.
I’ve tried unsuccessfully to find attribution for this… if you know where it comes from, give me a shout!