polybits Software and stuff

365 Days of GitHub

“A man who can't bear to share his habits is a man who needs to quit them.” ― Stephen King, The Dark Tower

It started off as a simple challenge to refamiliarize myself with areas I rarely cover in my day job. Inspired by the previous works of John Resig, Ryan Seys, and Geoff Greer, my daily habit snowballed into 20,000+ lines of code, 12 programming languages, 11 merged pull requests, and 8 new repositories.

The final body of work includes solutions to Project Euler, a RESTful content-addressable storage server, a proxy for local and remote filesystems, a LINQ-inspired shell, a simple performance monitor, a beanstalkd library, a library for writing an AI bot for Vindinium, and documentation for Rust. Other minor projects included a visualization of local crime data and a script that plots the intensity of accelerometer values from a Wiimote.

Unintended effects

After writing a non-trivial amount of code in a dozen languages, I've developed a feel for which programming language concepts and syntax are better suited for certain domains, especially the mathematical and performance-critical space inhabited by Project Euler.

When tackling a new problem, Clojure and Python were essential for testing out potential solutions in small incremental steps. Both are armed with a REPL, good libraries, and a dynamic type system. I solved many problems without worrying about the total run time of each solution.

As the problems increased in space and time complexity, I typically switched over to Go and Rust in order to find a solution in a reasonable amount of time. Both languages balance the need for performance and quick development without getting sidelined by too much boilerplate or scaffolding. Even though this doesn't matter as much for personal projects, I especially like the attention and thought put into Go's and Rust's development tools.

When looking back, I continuously found myself using pattern matching, list comprehensions, guards, closures, type inference, and traits. These features mapped well to mathematical domains, but readable yet compact code was a fortunate side-effect.

Lies, damned lies, and statistics

Due to the breadth of the implementations, my Project Euler solutions turned into a mini programming language shootout. The following table shows only lines of code and relative expressiveness of each language (as represented by the LOC Per Problem column). I do have run time performance statistics, but it didn't seem fair to publish the data until I reduced the startup cost for certain languages. I will say that Go, Rust, SML, and Haskell were very competitive with C++.

Language Lines of Code (LOC) Solved Problems LOC Per Problem
Haskell 505 37 13.6486
Scala 333 24 13.875
Clojure 1318 71 18.5634
Ruby 1443 73 19.7671
SML 264 12 22
Python 1828 82 22.2927
Erlang 1083 48 22.5625
PHP 1378 56 24.6071
Java 2005 62 32.3387
Rust 2420 72 33.6111
C++ 2528 73 34.6301
Go 3004 82 36.6341

So what's next?

I'm not exactly sure. The daily act of committing code is ingrained at this point so I'll probably continue for the forseeable future. As noted by others who have undertaken similar challenges, the benefits have far outweighed any downsides.