MicroPythonOS
GNU Units
A general purpose calculator for numbers with units.
Normal algebraic precedence applies, and you can use normal operators like +,-,*,/,^,sin,cos,exp,ln,log,round,floor,ceil.
Some extra guidance:
| Symbol | Explanation | Example |
|---|---|---|
* |
Low priority multiplication | 3 N * m |
| <space> | High priority multiplication -- Useful combined with / |
3 N m |
/ |
Low priority division -- Everything after is in the denominator | 1/2 kg m = 0.5 / (kg m) |
per |
Low priority division -- Everything after is in the denominator | 1 per 2 kg m = 0.5 / (kg m) |
| |
High priority division -- Only adjacent numbers are divided | 1|2 kg m = 0.5 kg m |
_ |
The result of the last computation |
OnStep
Reversing abstractions
Top of the slops
In higher education, I'd argue our common goal, across all disciplines (we use that word for a reason) is to turn out humans who are less sloppy than they would otherwise be. At present LLMs stand to drive sloppiness upwards, because they are seen as ways to “relieve” humans of the tasks that deliver the real insights—the writing, programming and perhaps even proof through which we discover the ways in which what we previously thought was sloppy. When people don't go through that process of discovery, they don't get the skills to make them less sloppy. To become rigorous, you have to be confronted with your own sloppiness.
How systolic arrays work
Tiny Tapeout
Parse, don’t validate aka some C safety tips
You can even apply the popular parse don't validate idea to C!
The author also makes the point that C is a strictly typed language. Just because you can cast every pointer to (void *) doesn't mean misusing other types of pointers won't result in a compiler error.
This lets you make new types, as structs, and then to make functions that only operate on those. Then, you can make a parser accept plain old data, and return a pointer to a new instance of the struct on successful parse and to null otherwise. The fields of the structs can even be hidden from the header file.
Another nice tip is to make the destruction functions work like this:
struct name_t {
char *name;
};
void name_del (name_t **name)
{
if (name && *name) {
free ((*name)->name);
free (*name);
*name = NULL;
}
}
to avoid double freeing memory (by detecting the pointer is set to null).
The C programming language: myth vs reality [hidden strict fields]
Struct internals can be hidden from public consumers by hiding the struct definition in a source (not header) file like this:
Header File:
typedef struct MyType MyType;
MyType* init(int a, float b, ...);
Source File:
struct MyType { int a, float b, ... };
MyType* init(...) { ... };
The user of the header file doesn't even know how big a MyType is! They can't mess with it.
How video games inspire great UX
The invisible problem
iPhone's hidden trackpad
In search of the origins of financial fluctuations: the inelastic markets hypothesis
Gabaix, X. and Koijen. In search of the origins of financial fluctuations: the inelastic markets hypothesis. NBER Working Paper, 2021.
I found it via an article in The Economist: Is passive investment inflating a stockmarket bubble? by Buttonwood.
It describes how $1 invested in a broad-market index increases the price of the index by $3 to $8, and that this is due to inelasticity in the market due to most participants just buying and holding.
Also interesting is that $1 of stock buybacks leads to $2 of increase in stock price.
The important part for future research is that their financial model is dependent on easily-tracked flows of money in/out of the market, rather than e.g. sentiment.
Giving university exams in the age of chatbots
Mailing list etiquette
Includes tips for using E-mail in sourcehut, following conventions long used in open-source. Includes:
- Plain text; useplaintext.email has a nice guide to doing this in various clients
- Don't "top post" and include the entire email chain below your reply, instead delete unnecessary parts and post your new comments at the bottom
- Wrap lines at 72 columns
- Attach PGP signatures instead of including inline
- Use
git send-emailfor sending patches
RuBee
Quickref.ME
A site with a bunch of quick reference pages. Pages include: Vim, C, Python, AWK, and some websites like GitHub.
The trick to avoid deeply-nested error-handling code
Inside a do-block for the Either monad, Left short-circuits out of the block. Keep in mind return doesn't. That could be a good reason to use pure instead.
Cosmopolitain libc
your build-anywhere run-anywhere c library
They do some crazy magic putting together the executable so that it works on Windows, Mac, and Unix.
You need a kitchen slide rule
Funny but a good idea.
Three Inverse Laws of Robotics
- Humans must not anthropomorphise AI systems.
- Humans must not blindly trust the output of AI systems.
- Humans must remain fully responsible and accountable for consequences arising from the use of AI systems.
OpenPrinter
An open-source design for a printer. It looks like it will use HP 63 compatible ink cartridges with no restriction on refilling. I love the roll of paper and integrated paper-cutting knife.
Powerful data analysis and composition with the UNIX-shell
Highlights commands that can be used for command-line data analysis using UNIX pipes.
Including:
- less
- head
- tail
- cut
- grep
- sed
- awk
- sort
- uniq
- comm
- join
- tr
- wc
- diff
- comm
I'd add seq for testing things out.
Idiomatic awk
I've wanted to learn awk for a long time. I can't decide if it's too cryptic to learn and maintain or would be useful.
I have this idea of using old-fashioned text processing Unix tools for data analysis. Awk would be helpful, since it is a bit like sed but can do math (among other things).
Another resource is the second edition of the book The AWK Programming Language.
Visidata
A terminal-based spreadsheet data exploration program. It leverages Python's data analysis ecosystem, in particular Pandas.
Data-oriented design (or why you might be shooting yourself in the foot with OOP)
The main point is to move the focus from code: classes, objects and functions, to data. Then working on blocks of data inputs and outputs can lead to a higher-performance and simpler design.
SoAx: A generic C++ structure of arrays for handling particles in HPC codes
A nice discussion of structure of arrays vs array of structures in the context of multi-particle simulations.
As of 2017, they show that structure of arrays performs better. The performance is especially great when the data fits in the CPU cache.
A3: avoid memos with an agenda
A nice way to structure communication in an organization. Focuses on describing the situation and problem before collaboratively working toward improvement.
Zathura
A minimal, keyboard-oriented document viewer. It seems like a nice thing to pair with VimTeX for LaTeX document editing.
Drones, physics and rats: Studies show how the people of Rapa Nui made and moved the giant statues – and what caused the island’s deforestation
The authors show that the Easter Island statues were moved by rocking them in the vertical position. Here is a video of researchers moving a mockup.
They also showed that deforestation had to do with the invasive rat population introduced by the Polynesian colonists. The rats ate seeds and kept trees from growing back after they were cut down by the colonists.
BOOX Palma 2
Interesting e-ink reader with Android the size of a large phone.
Daylight Computer
A reflective LCD tablet optimized for eye comfort.
Sun Vision Display
Reflective LCD Monitors
Hedy
A programming curriculum meant to be a step between things like Scratch and Python. It gradually introduces concepts and syntax so the student isn't overwhelmed by e.g. punctuation. It also localizes keywords to a student's language, so e.g. print and for are translated into Chinese, Spanish, etc.
How to slow down a program? And why it can be useful.
- Slowing down parts of a program can trigger hidden race conditions
- Slowing down all parts except a part you plan to optimize can be used to estimate the impact of the optimization
How to use computing power faster: on the weird economics of semiconductors and GenAI
The author posits that increasing sales of ever more powerful processors requires a market need for more powerful processors. During Microsoft's heyday, that was each version of Windows or Office requiring more computing power (the author thinks mostly because of bloat). The proliferation of smartphones, then crypto, then AI have continued the trend. So the semiconductor industry has become dependent on AI.
Unless a new fad emerges, given the supposed unprofitability of AI, the author sees a few future possibilities:
- AI companies become much more efficient, using much less computing power. This would lead to a bust in the semiconductor industry.
- AI companies can't become efficient enough to become profitable, leading to an AI bust that also brings a bust in the semiconductor industry.
- AI increasing efficiency just enough to become profitable while not harming the semiconductor industry too much. This is the "inference inefficiency optimum."
lazygit
A terminal UI for git that helps make the difficult workflows easy, e.g. staging individual lines, interactive rebasing, cherry-picking, amending an old commit.
FatNums: an alternative representation for school arithmetic
The idea is, rather than performing carries, just write down the "fat" number in its place.
For example, adding 1234 + 5678:
1 2 3 4
5 6 7 8
----------
6 8 10 12
6 8 11 2
6 9 1 2
The result is 6912.
Instead of carrying at each digit, you "normalize" at the end. This could be useful for elementary students struggling with the concept of carrying.
John Law and the Mississippi Bubble Video
A funny animated video explaining the Mississippi Bubble in France. It was an early implementation of paper money (redeemable for gold) and a market bubble.
git-bug
This is the kind of thing I mentioned looking for when talking about Radicle. The goal is to integrate bug reports, pull-requests, and comments as objects in the git repository itself. The project still has a way to go, but I might try it out.
Manifest Telephone
I'm not sure what the seven deadly sins of the religion of the telephone are, but I can promise that Comcast is guilty of every one.
Plain text sports
Neat website created because the author was tired of waiting for ESPN to load. Really nice idea and design. Too bad sports score APIs are too expensive for more people to do this on personal sites.
NGINX introduces native support for the ACME protocol
NGINX will soon be able to use the ACME protocol to automatically get and renew SSL certificates. This seems like it has been a long time coming, as it's just now in a preview release. Apache's stable release has been able to do it for a while.
Radicle code forge
Radicle is an open source, peer-to-peer code collaboration stack built on Git.
Radicle is pretty neat, replicating cryptographically signed repositories between peers. "Collaborative objects (COBs)" like issues, patches, and comments are stored as git objects in the same repository as code.
I like the storage of COBs in the git repository and Radicle's nice command-line and TUI access to them. I'd like just those parts in a traditional client-server system rather than a peer-to-peer system.
I'm not sure I need all of the fancy features of GitHub. The core seems to be git repositories, issue tracking, and pull requests (or patches), which Radicle implements.
SIMD instructions considered harmful
Interesting how vector instructions can be more performant than SIMD instructions. Also nice to not have a million SIMD instructions as registers grow in bit-width. It seems like a clear win to use vector instructions for RISC-V, so the vector registers can vary in size between implementations.
Bag of words, have mercy on us
I think this approach of thinking of LLMs as "bags of words" or, I might say boxes of text, is appropriate. AIs aren't honest or dishonest, but the box of text may be biased in one way or another. To me, the Internet is biased toward a lot of BS and inaccuracy. That's what I expect from LLMs.
Since source texts of varying quality are all mixed up in hard to understand ways, it's hard for the user to evaluate the quality of the LLM output. People who don't understand that rely on an appeal to authority, even though an LLM is not necessarily a good authority on anything.
Anthropomorphising AI is only natural, but it's interesting how AI seeming to be smart makes people think of it as an authority or even godlike.
A dive into open chat protocols
This post dives deeper into the criticisms of Matrix chat that have been on Lobste.rs lately. It compares Matrix and XMPP to Discord in a pretty even-handed way.The author makes the case pretty clear that chat protocols should be simpler than what Matrix is trying to do. It does seem that a chat protocol should just send messages as events between federated servers rather than trying to replicate chat history state between servers. If the history is that important (which I don't think it usually is in chat), then it should just be on a single server for simplicity.
Ergo IRC server
As in my entry on open chat protocols, I've been following discussions on what open chat should look like, wondering what my friends/colleagues should do if Discord or Slack become too annoying or expensive to use. Note that I don't have experience with any open chat protocol besides XMPP, and little with that.
Since Matrix and XMPP both seem to have complexity and compatibility downsides, I wondered if the solution is to go with IRC. The Ergo server seems the way to go for a private IRC server, because it integrates history as well as nick and channel registration in one simple program.
After spending a little time trying to use it, I've changed my mind. If I think it's a pain to setup and use a client with it, then how am I going to convince anybody else to use it! It also requires the sacrifice of GIFs, Markdown formatting, and even Emojis (it's ASCII and terminal-ish control codes only).
Apache SSLPolicy Directive
Makes configuring SSL simple by enabling a whole set of security policy directives in one command.
Apache includes policies from the Mozilla organization, including the most secure option: "modern"
2025-07-29 update: SSLPolicy is only in Apache 2.5.0 or later. It's currently not even in Debian Sid :-(
Enriching exceptions with notes
You can add notes to exceptions in Python 3.13. Combined with f-strings, you can include extra debugging info.
except Exception as e:
e.add_note('put extra debug info here')
e.add_note(f"x={x}")
raiseNotes on structured concurrency, or: Go statement considered harmful
The origin post about Trio. I first saw this a few years ago and think it's the way to do async.
A quantum-inspired classical algorithm for recommendation systems
By Tang, Ewin
Interesting that the quantum algorithm inspired an equally performant classical one.
See also Tang's paper published in PRL: arXiv:1811.00414 (cs)
FTXUI
FTXUI is simple cross-platform C++ library for terminal based user interfaces!
Seems easy to make nice UIs.
Oracle Separation of BQP and PH
A paper showing that there are problems quantum computers solve that aren't even solvable by a generalization of NP in classical computers.
Django SQLite Production Config
# yourproject/settings.py
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"OPTIONS": {
"transaction_mode": "IMMEDIATE",
"timeout": 5, # seconds
"init_command": """
PRAGMA journal_mode=WAL;
PRAGMA synchronous=NORMAL;
PRAGMA mmap_size = 134217728;
PRAGMA journal_size_limit = 27103364;
PRAGMA cache_size=2000;
""",
},
}
}Shoggoth Mini
When choosing cleaners, it helps to know your chemistry
Hyperfine
Automatic benchmarking tool. Runs the given command at least 10 times in at least 3 seconds, and then shows the mean, error in the mean, min and max time. Lots of configurability, too.
MacPaint Art From The Mid-80s Still Looks Great Today
This 1-bit art is so good!
Simple live reload for developing static sites
I could use this backend-agnostic script. Right now I just spam Ctrl-R!
Build123d
Python-based parametric CAD modeling software.
There seem to be a lot of nice features. It seems more like Fusion360 than OpenSCAD does, in that you create 2D sketches and then extrude or revolve them into 3D models.
See: Awesome build123d
Monitoring tiny web services
I've been trying to decide if I want to move my small dynamic websites to a VPS from Heroku or just use simple PHP and basic web hosting. My main problem with VPS is I don't want to deal with maintaining it. Simple monitoring like updown.io or Uptime Robot hooked up to email could help.
git notes
You can add notes to commits, branches, and all kinds of things in git. The only problem is they aren't easy to view on anything except commits via git log. GitHub doesn't show them at all, but I think Forgejo/codeberg.org does show them and let you add/edit them (see PR4753 and PR6025).
stack overflow: how to push git notes to a central server:
git push origin 'refs/notes/*'
and
git fetch origin 'refs/notes/*:refs/notes/*'
See also the git website doc on git notes
ArUco: Camera position detection using square markers
Code smell: boolean blindness
This post points out that it's often difficult to tell what a function does when passed true (or false). The given example of the ubiquitous "filter" function is great; does true or false make you keep a list element? Renaming filter to "select" and/or "discard" makes the boolean clearer.
The author points out that substituting a function that returns the Haskell Maybe type makes makes more sense in some "filter" scenarios.
mapMaybe :: (a -> Maybe b) -> [a] -> [b]
builds a list with only entries where the given function returns Just b
See Data.Maybe.mapMaybe for lists and the more general Data.Witherable.mapMaybe.
Related: the wrong abstraction
Modules for Experiments in Stellar Astrophysics (MESA)
Modules for Experiments in Stellar Astrophysics (MESA) is an advanced, open-source 1D stellar evolution code. The code is developed and maintained by a globally distributed team of researchers. MESA is written primarily in Fortran with a modular, flexible design that facilitates easy interfacing.
It seems to be for both research and teaching.
Pressure Stall Information
Found in /proc/pressure/ are cpu, memory, and io, text files that contain info on the fraction of processes "stalled" due to contention for the given resource.
Other links:
The misunderstood Kelly criterion
To maximise something which grows geometrically, choose the course of action that maximises the expected log-wealth of the thing.
The author wrote a related post When is insurance worth it? that I enjoyed as well.
Faster RANLUX Pseudo-Random Number Generators
RANLUX is highly regarded in the particle physics simulation community, but as far as I remember, we used the Mersene Twister in the Compact Muon Solenoid experiment. It must have been because it was faster.
The linked post is an effort to modernize RANLUX and make it faster.
Generative AI runs on gambling addiction
That is: generative AI works the same way as gambling addiction. Spin the gacha! Just one more spin, bro, I can feel it!
Large language models work the same way as a carnival psychic. Chatbots look smart by the Barnum Effect — which is where you read what’s actually a generic statement about people and you take it as being personally about you. The only intelligence there is yours.
Linux dd vs cp
Tutorials and instructions usually recommend dd over cp for copying disc images to devices (like USB sticks). It seems that this is mostly superstition.
The main benefit is that dd lets you specify the block size used for copying, but cp automatically selects the block size at least as well as I would.
The other benefit of dd is a progress display. Piping the output of the pv command to the destination disc may be a better option.
Luciole math
A "typeface for visual impairment" that even includes mathematical symbols. It seems to be developed by some groups in France and Switzerland.
Street smarts: how a hawk learned to use traffic signals to hunt more successfully
A hawk learning that an audio pedestrian walk signal at a traffic light leads to backed up cars it can use as cover to approach prey.
The published paper is here: https://doi.org/10.3389/fetho.2025.1539103
Ardux
An evolution of Artsey, with the addition of larger key layouts.
Artsey
An Easy, Fast, Open One-Handed Keyboard System
The layout diagrams are really nice!
On ad-hoc datatypes
Adding an enum datatype can simplify code. Don't be afraid to add module-internal ones.
rr debugger
rr aspires to be your primary C/C++ debugging tool for Linux, replacing — well, enhancing — gdb. You record a failure once, then debug the recording, deterministically, as many times as you want. The same execution is replayed every time.
This seems like it could be really useful, especially for intermittent bugs e.g. race conditions.
Lightstream sqlite replicator
Continuously stream SQLite changes to AWS S3, Azure Blob Storage, Google Cloud Storage, SFTP, or NFS. Quickly recover to the point of failure if your server goes down.
Type safety back and forth
If pushing responsibility forward means accepting whatever parameters and having the caller of the code handle possibility of failure, then pushing it back is going to mean we accept stricter parameters that we can’t fail with.
An example of the former is:
uncons :: [a] -> Maybe (a, [a])
and of the latter is:
head :: NonEmpty a -> a
Working with the latter pushes error handling to the data input code and cleans up all the rest.
Cron vs SystemD timers
A really nice explanation of how to use SystemD timers to replace cron.
Simplify: Move code into database functions
Keep as much logic in the database, using constraints, stored procedures, and functions (Postgres even lets you write them in Python) as possible.
This reduces duplication of logic between the DB and external code, and allows the external code to change without issue.
Find and replace in a codebase
I never really have figured this out before. Here is a way:
grep -l pattern | xargs sed -ri 's|pat(tern)|\1s are birds|g'
The -l option to grep (and ripgrep) makes it just output filenames containing matches. The sed option -r enables extended regex (-E may alternatively be used like in grep), and -i replaces in place.
If any filenames contain spaces, newlines, or quotes, then xargs can get messed up. Terminating lines with null characters fixes that:
grep -lZ pattern | xargs -0 sed -ri 's|pat(tern)|\1s are birds|g'
or
rg -l0 pattern | xargs -0 sed -ri 's|pat(tern)|\1s are birds|g'Linux is built for control but not for people
A story about using Linux blind. It makes me sad that accessibility in Linux has severely declined over the last 15 or so years!
fdfind
Intuitive to use version of the find program.
fdfind -e py # finds all Python files in current directory
fdfind pattern -t d # finds all directories matching patternncdu: NCurses Disk Usage
ncurses-based disk usage program. It seems fast and easy to use.
Watchexec
watchexec can rerun a command when a set of files is modified and is designed for ease of use. Two examples from the README are:
$ watchexec -e js,css,html npm run build
$ watchexec -r -e py -- python server.py
Frustratingly, it's not a Debian package. Installation with cargo install --locked watchexec-cli isn't hard, but you don't have much control over 300+ dependencies.
Types as assertions
Using custom types wherever there is some concept of validity can help make a codebase free from checking validity everywhere. It only must be done in the constructor and errors handled by the caller of the constructor.
So look through a codebase for functions that take string, int, and float!
Design for 3D printing
Modern LaTeX
"A short guide to LaTeX that avoids legacy cruft."
OpenFlexure Microscope
An open-hardware microscope. Make with 3D-printed parts!
The Field Guide to 3D Printing in Optical Microscopy for Life Sciences
Paper about 3D printers applied to microscopy. Some interesting projects and observations about 3D printing.
Quadlet: Running Podman containers under systemd
This lets you run containers using systemd, rather than having a complex, resource-hungry Kubernetes or Docker daemon manage them.
Podman is also capable of updating containers automatically, so the combination is something like Heroku.
The one ring problem: abstraction and our quest for power
"Design is figuring out how to find a point in the middle."
You cannot make an abstraction more powerful without sacrificing some properties that you used to know about it. Necessarily. You cannot require a new property be true about an abstraction without sacrificing some of its power and flexibility. Always.
The mistake is to forget this. Nearly always, this error happens in one direction. To look on a design, see what cannot be done with it, and attempt to “fix” it. To make it more powerful, and forget that it necessarily becomes more meaningless.
Designing type inference for high quality type errors
A bunch of things to note in designing a type system to make error messages better. I think the examples of bad error messages in languages being due to the type system (C++!) are broadly interesting.
When type annotations are code too
Type annotations affect runtime behavior in statically compiled languages, but not ones where types are bolted-on after the fact (Python).
This makes runtime behavior depend on the type inference algos and can be difficult to reason about.
The example in Haskell is wild!
Common mistakes to avoid in PHP
(The only proper) [PHP] PDO tutorial
A nice tutorial on PDO, the built-in SQL interface for PHP.
In particular, the official documentation doesn't say much about querying, but it's covered well here.
The other pages on the site are good too.
Psalm PHP Static Analyzer
A static analyzer with (optionally very strict) type checking. Developed at Vimeo.
Includes a language server (link to docs)
Packer
Declarative tool for creating virtual machine images. This way you can bake all of the installed software into an image, rather than having to provision once a virtual machine boots.
This plus it's parent Terraform (open source version: OpenTofu) seem to be the best way to do infrastructure as code, at least at a certain scale.
A similar tool, for bare metal, is goldboot
pyinfra
Think
ansiblebut Python instead of YAML, and a lot faster.
This seems more up my alley than ansible.
For a server or two, I'm not sure if this is the way to go or something more complicated like Packer
How to Specify It!: A Guide to Writing Properties of Pure Functions
A guide to writing property-based tests. The author, John Hughes, co-wrote QuickCheck in Haskell, the first package for property-based testing.
Published conference paper: http://dx.doi.org/10.1007/978-3-030-47147-7_4
Some quotes:
"Avoid replicating your code in your tests," because it's lot of work and likely to contain the same errors as your code.
"Test your tests," because if your generator and shrinker produce invalid values, everything else will fail too.
Validity testing
Validity testing consists of defining a function to check the invariants of your datatypes, writing properties to test that your generators and shrinkers only produce valid results, and writing a property for each function under test that performs a single random call, and checks that the return value is valid.
Postcondition testing
A postcondition tests a single function, calling it with random arguments, and checking an expected relationship between its arguments and its result.
Metamorphic testing
A metamorphic property tests a single function by making (usually) two related calls, and checking the expected relationship between the two results.
Inductive testing
Inductive properties relate a call of the function-under-test to calls with smaller arguments. A set of inductive properties covering all possible cases together test the base case(s) and induction step(s) of an inductive proof-of-correctness. If all the properties hold, then we know the function is correct–inductive properties together make up a complete test.
Model-based testing
A model-based property tests a single function by making a single call, and comparing its result to the result of a related “abstract operation” applied to related abstract arguments. An abstraction functions maps the real, concrete arguments and results to abstract values, which we also call the “model”.
py-spy Python profiler
A Python profiler that profiles unmodified Python processes from its own process. It can profile production code with little performance impact. It profiles extensions and all threads, which the standard library cprofile can't do.
Inverting a dictionary of lists in Python
I've needed to do this countless times in particle physics data analysis and other areas.
What I've done before:
data = {'a' : ['alpha', "beta"], 'b' : ["alpha"]}
result = {}
for key in data:
for value in data[key]:
try:
result[value].append(key)
except KeyError:
result[value] = [key]
and the simpler solutions suggested in the link:
data = {'a' : ['alpha', "beta"], 'b' : ["alpha"]}
result = {}
for key in data:
for value in data[key]:
result.setdefault(value,[]).append(key)
or
from collections import defaultdict
data = {'a' : ['alpha', "beta"], 'b' : ["alpha"]}
result = defaultdict(list)
for key in data:
for value in data[key]:
result[value].append(key)
dict.setdefault and collections.defaultdict are new to me and useful!
Stop writing Python __init__ methods
The idea is to just set members in object constructors to keep them simple. Any complex data conversion, or side-effects should be moved to a class-method.
This seems like a great way to deal with constructors taking multiple different inputs.
I do think using traditional constructors has the advantage of following a widely used convention (the principle of least surprise in API design) and can be simpler to use.
Apache mod_md: built-in Let's Encrypt certificate retrieval
Apache's built-in mod_md can handle automatic retrieval and renewal of Let's Encrypt certificates (or similar with ACME) without external software. Convenient!
ASCIIFlow
A web-app for drawing ASCII diagrams.
Muometric positioning system (μPS) with cosmic muons as a new underwater and underground positioning technique (2020)
Using the time of flight of relativistic cosmic ray muons to estimate relative position.
There is also a 2024 paper on a more practical, wireless system and another on time synchronization from 2022.
Here is the author, Hiroyuki K.M. Tanaka's inspirehep page.
Neovim
A more modern, but mostly compatible, version of Vim.
After trying Kakoune and Helix, I realized it would be too much work to re-learn a bunch of key-bindings and ways of doing things. I'm not ready to put the effort into a project that isn't very far along. With Neovim, I can always go back to Vim if the project fails.
I've been messing with configuring Neovim for a few days now, and it can be intimidating when you see a bunch of code to configure something in a web search result. I've found my way around that, and have things mostly up and running.
Overall, I think I'm happy to use Neovim for now.
tldr pages
The tldr pages are a community effort to simplify the beloved man pages with practical examples.
They are a really nice set of examples. I especially like the ones for git commands, like git rebase.
Helix text editor
2025-04-10 Update: I tried Helix for a few days, and like it, but miss features from Vim and want something more complete. Maybe I'll try to get LSP and completion working in Vim or give NeoVim a shot!
Helix is a Vim and Kakoune inspired editor. It follows Kakoune's philosophy of multiple selections and redesigned keybindings, but brings back Vim's visual mode. It is written in Rust and tries to include what most users would include through Vim plugins, e.g. tree-sitter and language server support (LSP). It doesn't currently have plugin support.
I'm writing this post in Helix. It's nice to have more of the "batteries-included" features like tiling window support and a file manager. I haven't figured out the tree-sitter/LSP integration yet.
A few things are missing, like spell checking (maybe can use a language server?) There does seem to be Git support. It's a nice little colored line between the line numbers and the text. It doesn't work the same as Vim-Fugitive, though, as it only shows the diff from HEAD, not from staged.
Using chroot for Linux system recovery
This technique lets you boot your broken installation with a live USB disc, then use chroot to switch the running Linux over to the broken installation. You can then run package manager commands, etc.
arch-chroot is a script that does all of the steps for you and is even available on Debian.
systemd-nspawn can be used in a similar way:
systemd-nspawn --directory /tmp/target-rescue --boot -- --unit rescue.target
It is usually used as a light weight host virtualization technique, and is new to me!
Light bulb shape and size chart
Chart for shape and size of light bulbs. A19 is the standard size.
They also have a base chart here. Medium/26mm/E26 is the standard one that goes with A19.

Freefall webcomic "quark" ice cream
I've just started reading the long-running webcomic "Freefall." I particularly like this joke about "quark" ice cream:
I thought everyone liked "quark" ice cream. I've got all three colors in all six flavors.
Choose boring technology
Author: Dan McKinley
The idea is that the more new, exciting, "poorly-understood" things you choose, the more complex and difficult to deal with your system becomes. He advocates for a company to pick three or less non-boring technologies and to pick them where it maximizes your competitive advantage.
This whole article is great!
What counts as boring? That’s a little tricky. “Boring” should not be conflated with “bad.” There is technology out there that is both boring and bad (we often casually refer to the boring/bad intersection of doom as “enterprise software,” but that terminology may be imprecise). You should not use any of that. But there are many choices of technology that are boring and good, or at least good enough. MySQL is boring. Postgres is boring. PHP is boring. Python is boring. Memcached is boring. Squid is boring. Cron is boring.
The nice thing about boringness (so constrained) is that the capabilities of these things are well understood. But more importantly, their failure modes are well understood.
Emphasis theirs:
One of the most worthwhile exercises I recommend here is to consider how you would solve your immediate problem without adding anything new. First, posing this question should detect the situation where the “problem” is that someone really wants to use the technology. If that is the case, you should immediately abort.
Python range is not an iterator
Counterintuitively, Python's range function isn't an iterator, because you can't call next() on it. It is lazy like iterators but is more like a "lazy collection." Like a collection, you can make an iterator from one with the iter() function.
The wrong abstraction
A good sign of an abstraction, e.g function, that needs to be replaced by copy-pasted code is one with boolean flag parameters. It's probably better to "inline" the code back to the call site, and then see what parts of it, if any, are still shared and make a new abstraction.
Tayloe Quadrature Product Detector
This simple circuit directly converts from RF down to baseband. Four square waves operating at and shifted 90° from each other control a multiplexer thus producing four quadrature signals. These can be combined to give I and Q signals. A copy of the PDF is here.
I found this while reading about the Pi Pico Rx, which uses this circuit and a Raspberry Pi Pico to make a software defined radio.
Haskell conditional for
To only perform a monadic or applicative action if a value exists, you can use
for_ value $ actionSo for example, if x is a Maybe String, you could print it if it exists with:
for_ x $ putStrLn xI think that's the beauty of Haskell, this thing with a name from lists, when generalized to (Traversable) Applicatives, can do useful things for all kinds of things.
Since for_ is just traverse_ with it's arguments flipped, you could also do:
traverse_ (action) valueKeep in mind for_ and traverse_ are in Data.Foldable and not present in the Prelude.
Also, oddly, is the linked blog post scheduled to be published in the future?
Haskell guard sequence
guard condition *> action -- Perform action if condition is true else fail
guard condition $> value -- Return value if condition is true else fail
value <$ guard condition -- Like the 1st line, but switched aroundThis can effectively make sure a condition is true before doing something or returning a value.
Keep in mind "failure" can mean lots of things depending on the surrounding Applicative. It could mean returning Nothing, or raising an exception.
You will need the following imports to do this:
import Control.Mondad (guard)
import Data.Functor ((*>),($>),(<$))Picking glibc versions at runtime
How do you test code against a different version of libc than the system default one? You can't reliably use an alternate libc by putting it in LD_LIBRARY_PATH. It will often crash.
You might think that the kernel is somehow responsible for dealing with dynamic libraries, but that’s not the case. Dynamic libraries are a user-space concept and this is precisely where the [ELF] interpreter [ld-linux.so] comes into play.
To summarize, glibc ships both the ld-linux.so dynamic linker and the libc.so.6 shared library. The two are closely coupled. Running a binary against the C library without also using a matching dynamic linker can lead to crashes. But running a binary directly with a specific dynamic linker ensures that the binary picks up the matching C library.
At compile time, you can include the interpreter ld-linux with:
bash gcc -o myexe -Wl,--dynamic-linker=/wherever/ld-linux-x86-64.so.2 mycode.c
At runtime, you can use patchelf to replace the reference to the interpreter in the binary:
bash patchelf --set-interpreter /wherever/ld-linux-x86-64.so.2 myexe
Keep in mind that glibc backwards compatibility means a newer glibc will work with code compiled with an older version, but not the other way around.
PaperWM
PaperWM is a scrolling window manager for the GNOME Shell. It's similar to tiling window managers like dwm and XMonad, but instead of tiling windows within the desktop, windows scroll to the right as they are created. So you just navigate left and right to various windows.
I like the conceptual idiom a lot better than normal tiling. I'm not sure if it works for me in practice. I've tried it in Debian 12/GNOME Shell 43.9 and installed the extension from extensions.gnome.org here on my laptop. I usually use each window in full screen on my laptop and alt-tab between them, so I'm not sure how useful the scrolling is for me. After an hour or so of use, it does seem to encourage me to have more than one window at a time on the desktop.
The default keybinding for switch window is super+tab, but I like alt+tab a lot better, so had to add that. The instructions on moving around and re-sizing windows are a bit confusing to me. I'm yet to really figure it-out.
Kakoune text editor
Kakoune is a Vim-inspired editor. Major differences from Vim include a focus on multiple selections and "orthogonal design", meaning normal-mode keybindings are redesigned to be more orthogonal. It also follows the Unix philosophy by not having much built-in. For example, to format paragraphs into a certain number of columns, I select text, hit | to pipe it to a shell program and run fmt. I'd just run gq in Vim.
I made this post with Kakoune. It took me a while to figure out how to get back to my text buffer from the documentation (type :buffer and then it shows in the autocomplete). In Vim, I tend to select things in visual mode and then perform actions on them. So I do like the selection-verb idiom of Kakoune, but don't like that visual mode is missing. It would take a while to transition from Vim.
Borg Backup Software
Borg seems like the best open source backup solution right now. It deduplicates chunks of data within files across multiple backups, saving a lot of space. Encryption and compression are also supported.
It only works locally or over SSH, and doesn't work on Windows. I wish it had support for parity so it could recover from a bit of storage corruption.
rclone
File copy/sync/move to and from the cloud, and even between clouds.
It works with S3 and similar, but also OneDrive, Dropbox, Google Drive, FTP, and SFTP.
Rsync for the cloud sounds useful, as well as copy and move. Two-way sync, bisync, sounds like a mess waiting to happen.
Archaeology of the pork taboo
For early Israelites and Muslims, the pork taboo seems to be a way to identify with their ancestral origin as herders, where pigs weren't practical.
Beause pigs didn't need a bunch of graising land, government officials couldn't track them. They could live their entire lives in a backyard. This, combined with nice secondary products of ruminants like milk and wool, lead to pigs being a lower-class thing, while ruminants were prized by the wealthy and religious/social elite.
Butterick's practical typography
How to Favicon
Dozens of images aren't required for a favicon. The article recommends 6, but I would try just .ico at only 32x32 and a SVG.
Includes a description of the files required and why, as well as how to generate them with Inkscape and Gimp.
Magic Wormhole
Peer to peer file sharing protocol. Ideal for sharing ssh keys and similar. Very well regarded cryptography.
The Night Watch
Funny musings about how systems programmers are hard-core.
Excerpts:
The systems programmer has traced a network problem across eight machines, three time zones, and a brief diversion into Amish country, where the problem was transmitted in the front left hoof of a mule named Deliverance
A systems programmer will know what to do when society breaks down, because the systems programmer already lives in a world without law.
Listen: I’m not saying that other kinds of computer people are useless. I believe (but cannot prove) that PHP developers have souls. I think it’s great that database people keep trying to improve select-from-where, even though the only queries that cannot be expressed using select-from-where are inappropriate limericks from “The Canterbury Tales.” In some way that I don’t yet understand, I’m glad that theorists are investigating the equivalence between five-dimensional Turing machines and Edward Scissorhands. In most situations, GUI designers should not be forced to fight each other with tridents and nets as I yell “THERE ARE NO MODAL DIALOGS IN SPARTA.” I am like the Statue of Liberty: I accept everyone, even the wretched and the huddled and people who enjoy Haskell. But when things get tough, I need mission-critical people; I need a person who can wear night-vision goggles and descend from a helicopter on ropes and do classified things to protect my freedom while country music plays in the background. A systems person can do that. I can realistically give a kernel hacker a nickname like “Diamondback” or “Zeus Hammer.” In contrast, no one has ever said, “These semi- transparent icons are really semi-transparent! IS THIS THE WORK OF ZEUS HAMMER?”
When you debug a distributed system or an OS kernel, you do it Texas-style. You gather some mean, stoic people, people who have seen things die, and you get some primitive tools, like a compass and a rucksack and a stick that’s pointed on one end, and you walk into the wilderness and you look for trouble, possibly while using chewing tobacco. As a systems hacker, you must be prepared to do savage things, unspeakable things, to kill runaway threads with your bare hands, to write directly to network ports using telnet and an old copy of an RFC that you found in the Vatican.
Nothing ruins a Friday at 5 P.M. faster than taking one last pass through the log file and discovering a word-aligned buffer address, but a buffer length of NUMBER OF ELECTRONS IN THE UNIVERSE.
You might ask, “Why would someone write code in a grotesque language that exposes raw memory addresses? Why not use a modern language with garbage collection and functional programming and free massages after lunch?” Here’s the answer: Pointers are real. They’re what the hardware understands. Somebody has to deal with them. You can’t just place a LISP book on top of an x86 chip and hope that the hardware learns about lambda calculus by osmosis.
That being said, if you find yourself drinking a martini and writing programs in garbage-collected, object-oriented Esperanto, be aware that the only reason that the Esperanto runtime works is because there are systems people who have exchanged any hope of losing their virginity for the exciting opportunity to think about hex numbers and their relationships with the operating system, the hardware, and ancient blood rituals that Bjarne Stroustrup performed at Stonehenge.
Triggering Javascript at the Right Moment
The best way to run javascript is in the head with the "defer" attribute. That immediately starts fetching the script, but waits to execute it until the whole page is parsed.
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<meta charset="UTF-8">
<script src="blahblah.js" defer></script>
</head>
<body>
<p>Stuff here</p>
</body>
</html>Emergence of collective oscillations in massive human crowds
Forgejo: Free Software Light-Weight GitHub Alternative
Interesting alternative to GitHub. It's also meant to be much lighter weight than GitLab, which I understand is quite heavy.
The hosted version is https://codeberg.org
TigerBeetle OLTP Database
Interesting architecture for a database specialized for OLTP. Single threaded, and each record is just 128 bytes to fit in a CPU cache line!
OWASP Security Cheat Sheets
Cheet sheets on all kinds of security, from C-based toolchain hardening to HTTP headers.
Stack Overflow Definitive Guide to Form-based Website Authentication
A really nice guide to the best, most secure ways to do website authentication. Lots of nice links