ezyang's blog

the arc of software bends towards understanding

Sup: Mail for Nerds

Update (September 1, 2012): This post is a bit out of date. I’m planning on writing an update, but the main new points are: if you have an SSD, the startup time of Sup is really fast, so you can easily run it on your laptop and you should use the maildir-sync branch, which gives you backwards synchronization of your labels (or my patchset, which is pretty sweet but needs to be polished and published.)


I use Sup and I love it; never mind the ridiculing from friends who’ve found their inbox get painfully slow as they broke the hundred thousand message mark or managed to get their index obliterated. It’s not quite been an easy road to email nirvana and a ten email inbox, so here’s a step-by-step guide for setting up Sup for your own geeky emailing needs. We’ll be using tip-top everything, which means running off a Git checkout of the next branch, using Xapian indexes and using OfflineImap.

  1. Get a server you can SSH into and run screen on. Sup has a nontrivial startup time, so the best way to work around it is to never shut down the process. It also saves you the trouble from needing to have ISP sensitive SMTP switching.
  2. Setup OfflineIMAP to slurp down your mails. IMAP is generally slow, and I find I care enough about my mail to want a local backup. The configuration of .offlineimaprc was slightly fiddly (I blew away my results twice before getting the right setup); see end of post for the template I ended up using. Since the import process will take a long time, double-check your configuration before running.
  3. Setup a Ruby environment; Sup works on Ruby 1.8 but not 1.9. If you’re on Ubuntu Jaunty, you’ll want to manually install RubyGems; on Karmic the packaged version works fine.
  4. Grab the dependency gems. This is as simple as installing the Sup gem using gem install sup, and then removing just the Sup gem with gem uninstall sup.
  5. Grab a copy of Sup from Git using git clone git://gitorious.org/sup/mainline.git sup. Inside your shell’s rc file (.bashrc for Bash users), set your PATH to include $SUPDIR/bin and your RUBYLIB to include $SUPDIR/lib. An example set of lines to add can be found at the bottom of this post.
  6. Run sup-config to setup general configuration. When it prompts you to add a new source, add a Maildir source, specifying a folder inside the directory you asked OfflineImap to sync to (for example, I asked OfflineImap to download my mail to ~/Mail/MIT, so ~/Mail/MIT/INBOX would be a valid folder for my Maildir). When I switched to Sup, I stopped using server side folders, so this is the only one I have a source for; if you still want to use them you’ll need to add them each as independent sources.
  7. Open up .sup/config.yaml in your favorite editor and on a new line add :index: xapian. An alternative method would have been to set an environment variable, but I prefer this method as more resilient.
  8. There are a few hooks that I unilaterally recommend you setup when you start Sup. Since you are using OfflineImap, the before-poll hook that executes OfflineImap prior to a poll is a must. There is also no good reason for you to not be running “Automatic backups of your labels” startup hook.
  9. Load up sup in a screen session and enjoy!

.offlineimaprc template:

[general]
accounts = MIT

[Account MIT]
localrepository = LocalMIT
remoterepository = RemoteMIT

[Repository LocalMIT]
type = Maildir
localfolders = ~/Mail/MIT

[Repository RemoteMIT]
type = IMAP
ssl = yes
remotehost = $HOST
remoteuser = $USERNAME
remotepass = $PASSWORD

.bashrc template (assuming Sup lives in $HOME/Dev/sup):

export PATH=$HOME/Dev/sup/bin:$PATH
export RUBYLIB=$HOME/Dev/sup/lib

First impressions of the VX-8R

The VX-8R is the first Ham radio I’ve ever owned; I have used the VX-7R before, but the extent of my usage of it was someone handing me the radio is “Here is the radio preconfigured to the frequencies you’ll need; here’s how squelch works; here’s how to debug common problems; don’t fuck it up.” Here are my impressions of the VX-8R

  • Despite the sturdy construction, I am sending it back for warranty replacement. The battery indicator is defective; it is stuck at 100% battery while discharging, and 0% battery when charging. According to a HRO representative, this was highly unusual. Having to send the radio back for replacement is kind of obnoxious, but eh, what can you do.
  • The Yaesu tries hard to be non-modal, but when it is it’s slightly difficult to tell what keys do what. For example, when scanning, pressing the PTT terminates the scan, but so does BAND and the arrow keys. PTT is actually a fairly reliable method for getting out of FOO mode
  • I love the scanning interface. Hold UP/DOWN to initiate scanning, use the dial to nudge it if it gets stock on the wrong thing, whack PTT when you hear something interesting.
  • The stereo headphone jack is by far one of the best things about the VX-8R, and partially offsets the suckage of needing two adapters in order to get a split speaker and PTT microphone set. I’ve, uh, been listening to a lot of FM radio with my Yaesu (perhaps not the most interesting use, but a use nonetheless!) The stereo plug is contained inside a somewhat appreciable well, so you may have some difficulty getting shorter jacks to plug in soundly.
  • On the subject of mods, it appears that despite having been released about a year ago, the VX-8R still has no software mod software available. The current hardware mod only opens up MARS/CAP transmission frequencies.

Still no word about the microphone dilemma; I might just pony up some cash for a Pryme headset (they’re a smidge more expensive than I’d like them to be).

Why Haskell? The big question

Language selection is a contentious thing, and often a compromise between “pick the right language for the job” and “use as few languages as possible to increase mindshare.” Google, for example, limits the programming languages their employees are allowed to use; and I have come to associate picking whatever language you want for your own projects as irresponsible, having once been told, “Yeah… that project was written in X and no one besides the guy who wrote it knows X… probably not a good use of your time to work on it.” Of course, I’ve been quite culpable of this myself; I wrote the member dues tracking system for the Assassins’ Guild in Haskell, and unless a miracle happens I am kind of doubtful future maintainers will be able to deal with it.

When I am not being irresponsible, Python is my favored language for most of my scripting needs, and as such I am painfully aware of quirks in the language that Haskell would smooth away.

  • Python code is dynamically typed and variables have no scoping. Brain-o typing errors, variable misnamings and plain ole broken code isn’t caught unless a code path is exercised. What makes it better: pylint -e catches large classes of errors (but you commonly have to wade through recursion limit errors to find it, and I strongly believe any error checking not built in the compiler is doomed to be ignored by the people who need it most), as is full code coverage on whatever automated tests you have. Why Haskell rocks: the static analysis is complete enough that if it compiles, it runs correctly.
  • Python is slow. If you don’t believe it: ask yourself why the runtime can’t be loaded quickly enough to make running Python as CGI tenable, or why Google has banned it from living in public facing code, or why engineers treat rewriting a Python daemon in C++ as the inevitable conclusion when you just can’t wring out anymore speed. What makes it better: Not everything has to be blazing fast. Why Haskell rocks: Insane people writing insane compilers like GHC which compile into native binaries and have absolutely epic speed.
  • Python has an limit to comprehensible code golfing. While duplication of high-level code structure is no where as bad in Python as it might be for Java or C++, attempts to purify code even further often lead to highly incomprehensible higher order functions that require copious documentation. As people say, “Don’t write Haskell in Python.” Why Haskell rocks: The type system not only becomes essential to the documentation of the code, it also serves as a framework by which a user can “snap” together combinators and data like legoblocks, leading to a much higher tolerance of complexity.
  • Python has inherited an aging object-oriented paradigm. However, I am increasingly convinced that typeclass based systems (Go is one decidedly imperative language that has picked them up) are the way to go. In combination with type signatures, they provide the two primary benefits of OOP: a logical organization of functionality and polymorphism, without all of the complicated gunk that is multiple inheritance, mix-ins, metaclasses, etc. Why Haskell rocks: First-class support for type-classes.
  • Python has abysmal threading support. It has the global interpreter lock. Why Haskell rocks: It not only has fast, green threads and the notion of purity to make splitting computations feasible, it has made it extremely simple to experiment with scheduling algorithms with the computation. I can’t say much more in this field, because I have very little experience writing parallel Haskell code.

But I would cringe to attempt to write in Haskell one of the large projects that I have done in imperative languages like PHP or Python (I mention these two particular languages, because within them I have built two systems that are actually large), for these very important reasons:

  • Haskell has not grown sufficient library support to become fully multiparadigm. I am highly skeptical that a straight-forward port of any given piece of Python code would be possible; despite great advances in shepherding the more dynamic features of Python into Haskell’s type system with packages such as Text.Printf, action at a distance intrinsic of an imperative program would require heavy IO wizardry in Haskell.
  • It’s not obvious which problems in the imperative domain truly are better kept in the imperative domain, as James Hague has mused recently. The Haskell community is fairly unified in its stance that as little code should be in the IO monad as possible, but when we bring in small bits of the imperative world to help us in cases such as the State monad, we acknowledge the imperative paradigm is useful… or at least an easy way out. Perhaps if we tried harder we could find a more elegant, maintainable, purely functional solution; and one of the favorite pastimes of academics is to figure these things out. But this is hard even for those used to thinking functionally, and the answers often need to be discovered, let alone implemented.
  • All of the engineering folklore, wisdom and best practices that have been accumulated from years of hacking on large, imperative codebases may or may not apply to functional codebases anymore. If functional libraries are encouraged to be as decoupled as possible, do we need to allow for further decoupling in the API? Does pure code need to be logged, or is its determinism make it trivial to debug? What testing do we need, and how much trust do we put in the types? How does API documentation and cross-referencing need to evolve for functional codebases? How the heck do you go ahead and debug a logic error in a section of pure Haskell code?

Yet, there are companies that are putting out production size codebases in Haskell, which makes me optimistic that answers to these questions will soon become public knowledge; if not for Haskell, for some other purely functional language. And the “classic” solutions in the imperative world have often lead to insidious errors, especially in a world of multithreaded applications, and we must not settle for “good enough.” Software sucks, but purely functional systems with strong, flexible types have the promise to eliminate large swaths of this suckage. And that is why I Haskell.

rxvt-unicode for gnome-terminal refugees

When I switched from Ubuntu’s default Gnome desktop to the tiling window manager Xmonad, I kept around Gnome Terminal, although with the menu bar and the scroll bars removed. I changed from the default white to a nice shade of #2B2B2B (a hue that Sup originally introduced me to).

Over the months, however, I got increasingly annoyed at the slowness at which Gnome Terminal rendered when I switched windows (a not uncommon task in a tiling window manager, made especially important when you have a relatively small screen size); the basic symptom was the screen would flash white as the old terminal left and the new one was being drawn. After testing xterm and finding that it did not flash when I switched screens, I hereby resolved to find a faster terminal emulator; on the advice of David Benjamin I finally settled on rxvt-unicode, also known as urxvt.

rxvt-unicode is part of a proud tradition of X terminal emulators, so its settings are managed by the X window manager (as opposed to gnome-settings, which gnome-terminal used). You can manipulate the settings at runtime using a program named xrdb; but I found it mostly easier to place the settings I wanted in .Xdefaults, which automatically gets loaded at session start. The syntax is simple: a newline-separated file, with the form Appname*option: value. Appname in the case of rxvt-unicode is URxvt.

Having used gnome-terminal for a long time, I was somewhat loathe to part with the colors and behaviors I’d come to love. So here is my .Xdefaults file, with notes about what the various bits do:

URxvt*background: #2B2B2B
URxvt*foreground: #DEDEDE
URxvt*font: xft:Monospace:pixelsize=12
URxvt*boldFont: xft:Monospace:bold:pixelsize=12
URxvt*saveLines: 12000
URxvt*scrollBar: false
URxvt*scrollstyle: rxvt

These parts are all fairly self-explanatory; rxvt-unicode supports anti-aliased fonts, which means bold text looks good (one of the primary reasons I couldn’t stand xterm, since bold fonts tend to bleed into each other without anti-aliasing).

URxvt*perl-ext-common: default,matcher
URxvt*urlLauncher: firefox
URxvt*matcher.button: 1
URxvt*colorUL: #86a2be

These lines implement clickable URLs inside your terminal. The launcher doesn’t give any visual cue in your cursor when a link is clickable, but I find the underlining and change in color to be enough change.

! black
URxvt*color0  : #2E3436
URxvt*color8  : #555753
! red
URxvt*color1  : #CC0000
URxvt*color9  : #EF2929
! green
URxvt*color2  : #4E9A06
URxvt*color10 : #8AE234
! yellow
URxvt*color3  : #C4A000
URxvt*color11 : #FCE94F
! blue
URxvt*color4  : #3465A4
URxvt*color12 : #729FCF
! magenta
URxvt*color5  : #75507B
URxvt*color13 : #AD7FA8
! cyan
URxvt*color6  : #06989A
URxvt*color14 : #34E2E2
! white
URxvt*color7  : #D3D7CF
URxvt*color15 : #EEEEEC

I absolutely adore gnome-terminal’s color scheme, which is a bit more subdued than the rxvt default. So in it goes. The first color is “normal”; the second color is “bright.”

Audio connectors and radios

Over winter break, I purchased a Yaesu VX-8R, the newest model from Yaesu and the successor to the VX-7R, which is favored by many in the MIT community. Deciding that this was the particular radio I wanted to buy was difficult: purchasing a (cheaper) VX-7R would mean I could tap into the immense pool of knowledge that has already rallied itself around this particular model. But my father was willing to put down the extra $50 for the newer version, and so I decided to be experimental.

That’s, however, not the point of this post (a review of the VX-8R will have to wait until I actually get my hands on it): the real puzzling part of the exercise was figuring out what accessories to purchase in order to get a microphone headset. If that sounds vague, that’s because it is. Yaesu’s official accessories—which were strongly Bluetooth oriented—were devoid of a standard, wired headset. After some investigation, and a very informative conversation with Kelsey, here is what I found.

First, some vocabulary. If you’ve ever plugged in headphones to your computer, you are familiar with the TRS connector, also known as an audio or headphone jack. It is the exposed, tapered jack, and contain multiple conductors (the black rings separate them). The connector for the stereo speakers you own probably has three conductors; one for ground, one for the left channel, and one for the right. There is a wide variety of TRS connectors in both size and number of conductors. For a radio (and more generally equipment that can utilize a push-to-talk (PTT) headset), we are interested in TRS connectors of 3.5mm (1/8in) diameter with four conductors: one ground, one audio, one microphone, and one PTT.

A DIN connector has a number of pins protected by metal shielding. The pins in a DIN connector correspond to conductors, and it is not unusual for there to be three to eight pins (greater than four conductor TRS connectors are quite rare.) DIN connectors have standard size (13.2mm), but the assignment of pins varies from application to application.

Now, for the actual radios. We’ll start with the VX-7R, since the VX-8R jack is strictly more powerful than the 7R’s. The VX-7R sports a four conductor 3.5mm TRS connector, but with a twist: it’s specially designed to be waterproof, so to get a snug fit you need a special TRS connector that has a screw after the actual jack. The CT-91 is such a TRS connector, and it splits the connection into a three-conductor 3.5mm headset TRS plug, and a three-conductor 2.5mm microphone TRS plug; these are apparently standard jacks and thus you can find an assortment of headsets as well as individual earbuds and ptt microphones for them. (Note: I didn’t have any lying around the house, and didn’t get a chance to head out to a radio store, so this is strictly hearsay.)

The VX-8R, on the other hand, has support for GPS, so it can’t get away with just four conductors: instead, it sports an 8-pin DNS plug, which for all intents and purposes is proprietary. You can hook up the GPS unit (CT-136 and FGPS-2), but in general you’ll need the $30 connector, the CT-131, to translate it into a four-conductor 3.5mm TRS jack. This is the same four-conductor form as the TRS plug on the VX-7R, but without the waterproof screwy bit. To split it, you can use CT-91, but the screw bit will show and for a more snug fit you’ll have to buy their suggested CT-44.

We were able to find a four-conductor headset lying around the house, but it didn’t work; like the miscellaneous three-conductor stereo headsets I tried, plugging it in resulted in a working sound signal, but caused PTT to be persistently activated. The current theory is that stereo was messing with things.

Here are the things I’d like to know:

  1. The VX-8R has a separate stereo-headphone jack, so I’m a bit curious what would happen if I stuck a PTT microphone into the four-conductor plug. If by some miracle the two were compatible, it would mean that a secondary adapter is not necessary. Given that the splitter suggests a 2.5mm mic, and the 4-conductor plug is 3.5mm, this seems unlikely.
  2. The CT-131 and CT-91 form a kind of sketchy-looking connection, and I’m not sure if this would actually prove to be a problem in practice, or if I’d want to electrical tape the two together. Some field-testing is required here, and I’d also be curious to know how difficult it would be to purchase or make a 4-conductor to 2.5mm PTT mic adapter.
  3. I need to find a store close by Cambridge/Boston where I can test various push-to-talk microphones. Any suggestions here would be greatly appreciated!

Adventures in Three Monads

I’ve been busy at work over this winter break working on an article for The Monad Reader, entitled “Adventures in Three Monads.” The material will overlap the second part of my IAP talk Haskell Typeclasses that I will be delivering under the auspices of SIPB IAP.

The article itself is a literate Haskell file, and contains sample code I’ve cribbed from the various Haskell applications I’ve written over my year long flirtations with the language: included is code and explanation for the probabilistic Turing machine I built in order to brute-force a 6.004 assignment. (To the course staff: the code is incomplete enough that it’s not equivalent to publishing all of the solutions; intrepid readers will still have to write a search function themselves.)

I’ll be keeping a pre-print of the article available in my public directory. Questions, comments and suggestions would be greatly appreciated!

2010: A Roadmap

I did one of these for 2008, and it was highly amusing to see some of the goals I had put down that, in fact, I do not care at all about in the middle of my sophomore year in college. (For a more technically oriented one, see “Get PHP to compile with VS2008”… ick.) They are not quite resolutions, because I know enough that to actually get things done I should set schedules. These are tendencies; guiding principles for the New Year. Things to make habits. Things that are hard.

  • Pay more attention to the people I live with and care about, so that I know when they are distressed, and know what I can do to help.
  • Pay more attention to what people feel. Develop empathy.
  • Do interesting research. Write an academic paper. Get it submitted to a major journal.
  • Become involved in ham radio. Get certified.
  • Be romantic.
  • Continue to increase my palette of cooking, especially for greens.
  • Continue to study mathematics.
  • Increase physical flexibility, figure out how to make exercise a part of my schedule, and not just something I do when I decide I need exercise to concentrate.
  • Learn C++ metaprogramming. Find a good excuse to hack in this language.
  • Push myself beyond my limits, because you don’t know what they are until you are past them.
  • Cold call old friends every once in a while.
  • Tell stories.

Iron Blogger

This social experiment has already hit number four Google spot for “Iron Blogger,” and there’s no reason it shouldn’t rise any higher. Iron Blogger is an experiment in beer (well, not quite for me), blogging, and peer pressure.

Since we’re on the topic of blogging, and why people (including myself) can’t seem to do it, we might as well look over the aborted attempts at blogging that I’ve had over the years.

The very first blog I made was done when Blogger was still a shiny new service, and blogs were just hitting mainstream in 2004. The blog was named Library of Murmurs and in its initial incarnation was very much ramblings of a crackpot. Bad puns abounded. It was the era of “The Writing Pot.” I think during this time period was dying for feedback and communication, and when a semi-regular posting schedule failed to elicit any comments, the blog fell into disrepair.

In 2007, I repurposed the blog into an HTML Purifier development log, in hopes that the many users of HTML Purifier might find an insight into its development process of interest. Those were the heady days of architecture astronauts, of writing Java in PHP and the proliferation of design patterns. I also occasionally wrote bad poetry. Once again, a lack of feedback and response made the blog fall into disrepair. Also, I had learned to absolutely hate Blogger’s interface and total incompetence at line-breaking HTML.

Over summer 2009, I had charted for myself the ambitious goal of writing a substantial blog post every week; each post would have been meticulously written and revised, content would be king, and as an MIT student, surely I had something to say that the world would care about. The opening post was to be thus:

To write is to articulate.

It is to coalesce what has been in the periphery of your mental vision to the structure of letters, words, sentences, paragraphs, chapters. It is to lock down the meaning of what you want to say, and yet open up the possibilities of what you could say, but haven’t said yet.

So, do not think of this as a web log, for if it was a log the captain would regularly go back to the ledgers and rewrite the scritch scratch of history to make it pretty. Think of it as a collection of essays, each an encapsulation of something I wanted to say.

But the plan was derailed by the fact that it’s really hard to write essays, it’s not actually quite an appropriate medium for blogs (if you are writing an expository piece, you would very much like to keep it up to date), and Wordpress code is, quite frankly, kind of horrifying.

Iron Blogger, more than a “threat” of financial burden due to lameness, is helpful because it is an observation function: it cannot work unless someone is at least vaguely paying attention to your blog. And thus I am proud to embark upon this grand experiment. Let the lameness begin!