What I'm Up To

I’ve got a few projects rolling at the moment. The overall trend is to pursue intelligibility. Document publishing I’m in the process of learning Pollen, a next-generation document publishing tool written in Racket, a dialect of Scheme. I intend to use it for my résumé, this blog (sorry Hugo, you’re too complex), and random typographical stuff I produce for events such as parties. Matthew Butterick’s Practical Typography has turned me into an amateur typographer, such that I now offer free, unsolicited design services to friends who ask me to improve their writing. [Read More]

Designing a Platform for Programming Language Experimentation

Roughly two years ago, I read a description of how a Forth interpreter works. The Forth interpreter is very simple. It just does this over and over: Read a line of input While there is more data in the line: Parse a whitespace-delimited word Lookup the word in a list of defined words. If found, execute the code for that word. Otherwise, try to interpret the word as a number in the current number base. [Read More]

I Slayed a Callback Dragon Today

I was writing some Core Bluetooth code on iOS when the dragon appeared. A callback looks like a function. But it’s not a function; it’s an event disguised as a function. Once you know the beast’s weakness, it’s simple, though not easy. Don’t write callbacks. Write code to handle events. All events implicated by a particular objective. That code might be a state machine, or it might be something more complex. [Read More]

Designing a Concatenative Language

The tasks of designing a language and creating an interpreter are distinct, but practically, they are tightly coupled. The interpreter serves as a research vehicle for design choices. The language serves as an occasion for interpreter design. The first interpreter I wrote was for a Forth-like, stack-based, postfix language. It was extremely simple, consisting of a tokenizer and a word evaluator, inspired by a description of the Open Firmware Forth interpreter. [Read More]

Write C to Test C

It disappoints me to see messy, procedural, assertion-based testing in C codebases. Here’s an example from the wild: const char *key = "404"; const int values[3] = { 0, 1, 2 }; plan_no_plan(); Map *map = map_new(); ok(map && map_empty(map), "Creation"); ok(map_first(map, &key) == NULL && strcmp(key, "404") == 0, "First on empty map"); ok(map_empty(map_prefix(map, "404")), "Empty prefix map"); In assertion-based testing, it’s common to test an entire data structure in a single function, instead of testing one of its operations. [Read More]

What I learned from trying TCR

test && commit || revert (TCR) is a coding workflow proposed by extreme programming guru Kent Beck. I just tried it out. Here’s what I learned. 1. Starting out is somewhat paradoxical You have to write tests that pass, otherwise they get deleted. So you end up aiming for silly things, like tests that test nothing or test stubs. After that, it seems to work well enough for something like a Fibonacci function. [Read More]

Code Framing

I assume that our conceptualization of programming languages has been influenced by the grammatical moods of natural language. The imperative mood: imperative, statement-driven programming; the conditional and subjunctive moods: condtional statements and clauses; the indicative mood: declarations—be they data, constraints, relationships, or whatever. Most programmers have more experience with programming constructs than with grammatical moods. But if such moods influence our idea of programming, maybe they can be a research vehicle in programming language design. [Read More]

Clean Concurrency in Go

The Go programming language makes it possible to write readable software. But readability is not an ingredient of a language. It follows from the language’s design and how it is used. In my brief experience with Go, using interfaces enhances readability. Interfaces can be used to separate concerns, so that unrelated thoughts don’t intrude on one another. Concurrency, one of Go’s “headline features,” enables separation of concerns in a different way. [Read More]

The Case for a Cooperative Internet Service Provider

As the Internet has evolved, new services have challenged the engineering and business assumptions of existing networks. BitTorrent and Comcast, Skype/iPhone and AT&T, Netflix/Level 3 and Comcast are just a few cases in which changing relations among Internet organizations have caused consumer dissatisfaction. Consumers rightly see the risk in giving ISPs too much power. However, they typically lack insight into the technical and business situations that ISPs confront, for example, routing and peering agreements, making it easy for the actions of ISPs to be seen as Orwellian. [Read More]