Programming

Go: More UNIX than UNIX

Go comes in part from Rob Pike and Ken Thompson, both influential in early UNIX. Both Rob Pike and Ken Thompson also were influential in working on Plan 9, a followup to UNIX.

UNIX's ideal is that "everything is a file". In Go terminology, this is a declaration that everything should be accessible via a uniform interface, which the OS specially privileges. One of Plan 9's core reasons for existing is that UNIX didn't take this anywhere near as far as it could be taken, and it goes much further in making everything accessible as a file in a directory structure.

I'm skeptical of both of these approaches. Everything isn't a "file".

There's numerous "files" that require ioctls to correctly manipulate, which are arbitrary extensions outside of the file interface. On the flip side, there are all kinds of "files" that can't be seeked, such as sockets, or files that can't be closed, like UDP streams. Pretty much every element of the file interface is one that doesn't apply to some "file", somewhere.

The Procrustean approach to software engineering tends to have the same results as Procrustes himself did, gravely or even fatally wounding the code in question.

Suture - Supervisor Trees for Go

Supervisor trees are one of the core ingredients in Erlang's reliability and let it crash philosophy. A well-structured Erlang program is broken into multiple independent pieces that communicate via messages, and when a piece crashes, the supervisor of that piece automatically restarts it.

This may not sound very impressive if you've never used it. But I have witnessed systems that I have written experience dozens of crashes per minute, but function correctly for 99% of the users. Even as I have been writing suture, I have on occasion been astonished to flip my screen over to the console of Go program I've written with suture, and been surprised to discover that it's actually been merrily crashing away during my manual testing, but soldiering on so well I didn't even know.

(This is, of course, immediately followed by improving my logging so I do know when it happens in the future. Being crash-resistant is good, but one should not "spend" this valuable resource frivolously!)

I've been porting a system out of Erlang into Go for various other reasons, and I've missed having supervisor trees around. I decided to create them in Go. But this is one of those cases where we do not need a transliteration of the Erlang code into Go. For one thing, that's simply impossible as the two are mutually incompatible in some fundamental ways. We want an idiomatic translation of the functionality, which retains as much as possible of the original while perhaps introducing whatever new local capabilities into it make sense.

To correctly do that, step one is to deeply examine not only the what of Erlang supervision trees, but the why, and then figure out how to translate.

The Environment Object Pattern in Go

One of the things I've been really enjoying about Go is how easy testing is. The pervasive use of interfaces and composition-instead-of-inheritance synergize nicely for testing. But as I've expressed this online on reddit and Hacker News a couple of times, I've found that this does not seem to be a universally-shared opinion. Some have even commented on how hard it is to test in Go.

Since we are all obviously using the same language, the difference must lie in coding behavior. I've internalized a lot of testing methodology over the years, and I find some of the things work even better in Go that most other imperative languages. Let me share one of my core tricks today, which I will call the Environment Object pattern, and why Go makes it incrementally easier to use than other similar (imperative) environments.

So you want to write a Monad tutorial in Not-Haskell...

There are a number of errors made in putative Monad tutorials in languages other than Haskell. Any implementation of monadic computations should be able to implement the equivalent of the following in Haskell: minimal :: Bool -> [(Int, String)] minimal b = do x <- if b then [1, 2] else [3, 4] if x `mod` 2 == 0 then do y <- ["a", "b"] return (x, y) else do y <- ["

Scientists (and, in my experience, especially bioinformaticians) tend to make horrible, awful messes no matter how maintainable you think a language is. (You can hand them Inform 7 and it'll still end up looking like Fortran ate the csh manual and vomited all over an APL keyboard.)-- chromatic on HN

I've pushed two repos to GitHub with Go code: gomempool (godoc): A []byte pool manager for Go. It's less generic than the Pool implementation that is working its way into Go tip, but also therefore understands more about []bytes, and is much simpler than the I-don't-even-know-what magic is in that implementation. It also tracks stats, which I've hooked up to my monitoring so I can see the usefulness of the pool in my real running code.

Computer Security Haiku

Gold in vault, target Steel door closed, locked, key thrown away; Thief laughs "There's no wall!" Data stream flows, filling Lake overflows; disaster! Arbitrary code Man trusts fellow Man, fellow Man undeserving. Script code injected. Novice celebrates, Output easy, just append strings! Master needs new novice. Dark secrets made, shared Tells foe the password is lost... Rubber hose finds it. "Love", Alice tells Bob In anger, Eve flips one bit

Parametricity in Go

One of my objections to Erlang is that despite paying the price of being a functional language, it often fails to reap the advantages. An example of this is in testability; nominally, a purely functional bit of code ought to be easier to test than the imperative equivalent, because it is just a matter of setting up your parameters and checking the results, with no IO or state in between.

Erlang doesn't make this impossible, but it's less convenient than the brochure promises. The core of your application is generally locked up in the various gen_* handlers. These handlers have very stereotyped ways of being called, which include the full state of the thing being tested. I find this very tedious to test, for two reasons: 1. Every test assertion must define some sort of "complete state" for the handler, which is probably full of real-world concerns in it. In particular if it has further messages it is going to send, those are often relatively hard-coded somehow... an inconvenient-to-mock Mnesia entry, an atom-registered process name, etc. (Erlang programs end up having a surprising amount of global state like that.) 2. If you want to test some sort of sequence of events, you are responsible for threading through the code, or manually invoking the proper gen_* start up functions, or something. It's possible to refactor your way out of this mess, but in practice it's a lot of work for the reward. So many of the tools you could use in other languages aren't available.

Go, in theory, ought to be harder to test than Erlang, being an imperative programming language. In practice, I'm finding it much easier, and I'm doing a lot more testing in it.

Sum Types in Go

A couple of months back, I analyzed whether I wanted to propose switching to Go for work. I've still technically got the blog post with the results of that analysis in the pipeline (though who knows when I'll get it up), but there's a part of it that keeps coming up online, and I want to get this bit out faster. It's about whether Go has "sum types".

Review: Learn You a Haskell for Great Good!

Learn You a Haskell for Great Good! (A Beginner's Guide) by Miran Lipovača, published by No Starch Press (2011). No Starch was kind enough to send me an advance copy for review.

Haskell books for "real programmers" are still thin on the ground, being limited at the moment to Real World Haskell (2008) and possibly Programming in Haskell (2007). As its introduction states, this book is aimed at existing programmers who are currently fluent in something like Java, C++, or Python, and would like to learn Haskell.

I put my take on the traditional discussion of why you should consider learning Haskell in another blog post, so we can get on with the review here.

The hardest thing about learning Haskell with no previous functional experience is bootstrapping the strong foundation that you've long since taken for granted in your imperative language. If you don't have this strong grasp of the fundamentals, then every line of code is an invitation to get stuck on some subtle issue, and you'll never have the fluency that great work requires until you have that foundation.

This book is the best way I know to obtain the Haskell foundation you need for fluency.